Fluentdata 支持很多种数据库驱动,但对Firebird不友好,不过可以使用DB2Provider来操作大部分功能,
例如: new DbContext().ConnectionString(connectionString, new DB2Provider(), FirebirdClientFactory.Instance)
但是对于Insert后获取自动生成的最大Id,就会报错,因为DB2的语法不通。
起初怀疑获取最大Id方法是通过自动添加select max(id)来获取,这样就有可能访问量大时会存在错误。
好在官网有源码可以查看,结果不是的。
每种数据库都有insert后获取inserted记录的Id的方法,Firebird也不例外,语法是: insert A (x,x) values (x,x) returning id, x, x 和Oracle语法差不多。
那就果断添加一个 FirebirdProvider ,后续我们再查看下其他各数据库ExecuteReturnLastId的具体做法。
FirebirdProvider 代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Data; 4 using System.Linq; 5 using System.Text; 6 using FluentData.Providers.Common; 7 using FluentData.Providers.Common.Builders; 8 9 namespace FluentData 10 { 11 public class FirebirdProvider: IDbProvider 12 { 13 public string ProviderName 14 { 15 get 16 { 17 return "FirebirdSql.Data.FirebirdClient"; 18 } 19 } 20 21 public bool SupportsOutputParameters 22 { 23 get { return true; } 24 } 25 26 public bool SupportsMultipleResultsets 27 { 28 get { return true; } 29 } 30 31 public bool SupportsMultipleQueries 32 { 33 get { return true; } 34 } 35 36 public bool SupportsStoredProcedures 37 { 38 get { return true; } 39 } 40 41 public bool RequiresIdentityColumn 42 { 43 get { return false; } 44 } 45 46 public IDbConnection CreateConnection(string connectionString) 47 { 48 return ConnectionFactory.CreateConnection(ProviderName, connectionString); 49 } 50 51 public string GetParameterName(string parameterName) 52 { 53 return "@" + parameterName; 54 } 55 56 public string GetSelectBuilderAlias(string name, string alias) 57 { 58 return name + " as " + alias; 59 } 60 61 public string GetSqlForSelectBuilder(SelectBuilderData data) 62 { 63 var sql = ""; 64 sql = "select " + data.Select; 65 sql += " from " + data.From; 66 if (data.WhereSql.Length > 0) 67 sql += " where " + data.WhereSql; 68 if (data.GroupBy.Length > 0) 69 sql += " group by " + data.GroupBy; 70 if (data.Having.Length > 0) 71 sql += " having " + data.Having; 72 if (data.OrderBy.Length > 0) 73 sql += " order by " + data.OrderBy; 74 if (data.PagingItemsPerPage > 0 75 && data.PagingCurrentPage > 0) 76 { 77 sql += string.Format(" rows {0} to {1}", data.GetFromItems(), data.GetToItems()); 78 } 79 80 return sql; 81 } 82 83 public string GetSqlForInsertBuilder(BuilderData data) 84 { 85 return new InsertBuilderSqlGenerator().GenerateSql(this, "@", data); 86 } 87 88 public string GetSqlForUpdateBuilder(BuilderData data) 89 { 90 return new UpdateBuilderSqlGenerator().GenerateSql(this, "@", data); 91 } 92 93 public string GetSqlForDeleteBuilder(BuilderData data) 94 { 95 return new DeleteBuilderSqlGenerator().GenerateSql(this, "@", data); 96 } 97 98 public string GetSqlForStoredProcedureBuilder(BuilderData data) 99 { 100 return data.ObjectName; 101 } 102 103 public DataTypes GetDbTypeForClrType(Type clrType) 104 { 105 return new DbTypeMapper().GetDbTypeForClrType(clrType); 106 } 107 108 public object ExecuteReturnLastId<T>(IDbCommand command, string identityColumnName = null) 109 { 110 if (identityColumnName == null) identityColumnName = "id"; 111 112 string temp = command.Data.Sql.ToString().Trim(); 113 if (temp.EndsWith(";")) 114 command.Data.Sql.Clear().Append(temp.Substring(0, temp.Length - 1)); 115 116 command.ParameterOut("FluentDataLastId", command.Data.Context.Data.FluentDataProvider.GetDbTypeForClrType(typeof(T))); 117 command.Sql(" returning " + identityColumnName); 118 119 120 object lastId = null; 121 122 command.Data.ExecuteQueryHandler.ExecuteQuery(false, () => 123 { 124 command.Data.InnerCommand.ExecuteNonQuery(); 125 126 lastId = command.ParameterValue<object>("FluentDataLastId"); 127 }); 128 129 return lastId; 130 } 131 132 public void OnCommandExecuting(IDbCommand command) 133 { 134 } 135 136 public string EscapeColumnName(string name) 137 { 138 return name; 139 } 140 } 141 }
具体调用方法: new DbContext().ConnectionString(connectionString, new FirebirdProvider(), FirebirdClientFactory.Instance)
DB2做法是: select IDENTITY_VAL_LOCAL() as LastId from sysibm.sysdummy1;
Mysql做法是: select LAST_INSERT_ID() as `LastInsertedId`
Oracle做法是:sql结尾添加输出参数 returning id into :FluentDataLastId
PgSql做法是: select lastval();
Sqlite做法是: select last_insert_rowid();
SqlCe做法是: select cast(@@identity as int)
SqlServer做法是: select SCOPE_IDENTITY()
===================================================
实体方法扩展:
1 public class Base 2 { 3 public long id { get; set; } 4 } 5 6 public class T_session : Base 7 { 8 public string token { get; set; } 9 public long? user_id { get; set; } 10 public DateTime login_time { get; set; } 11 public DateTime? logout_time { get; set; } 12 public DateTime update_time { get; set; } 13 } 14 15 public static class DbExt 16 { 17 public static long Insert(this Base enty, IDbContext db) 18 { 19 return db.Insert(enty.GetType().Name, enty).AutoMap(x => x.id).ExecuteReturnLastId<long>(); 20 } 21 22 public static int Update(this Base enty, IDbContext db) 23 { 24 return db.Update(enty.GetType().Name, enty).AutoMap(x => x.id).Where(x => x.id).Execute(); 25 } 26 27 public static int Delete(this Base enty, IDbContext db) 28 { 29 return db.Delete(enty.GetType().Name, enty).Where(x => x.id).Execute(); 30 } 31 32 }