public bool HasChanged(MappingMemberDescriptor memberDescriptor, object val) { object oldVal; if (!this._fakes.TryGetValue(memberDescriptor.MemberInfo, out oldVal)) { return true; } if (memberDescriptor.MemberInfoType == UtilConstants.TypeOfByteArray) { //byte[] is a big big hole~ return !AreEqual((byte[])oldVal, (byte[])val); } return !Utils.AreEqual(oldVal, val); }
public virtual int Update <TEntity>(TEntity entity, string table) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); EnsureEntityHasPrimaryKey(typeDescriptor); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; MemberInfo keyMember = keyMemberDescriptor.MemberInfo; object keyVal = null; IEntityState entityState = this.TryGetTrackedEntityState(entity); Dictionary <MappingMemberDescriptor, DbExpression> updateColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { MemberInfo member = kv.Key; MappingMemberDescriptor memberDescriptor = kv.Value; if (member == keyMember) { keyVal = memberDescriptor.GetValue(entity); keyMemberDescriptor = memberDescriptor; continue; } if (memberDescriptor.IsAutoIncrement) { continue; } object val = memberDescriptor.GetValue(entity); if (entityState != null && !entityState.HasChanged(memberDescriptor, val)) { continue; } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); updateColumns.Add(memberDescriptor, valExp); } if (keyVal == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMember.Name)); } if (updateColumns.Count == 0) { return(0); } DbTable dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema); DbExpression left = new DbColumnAccessExpression(dbTable, keyMemberDescriptor.Column); DbExpression right = DbExpression.Parameter(keyVal, keyMemberDescriptor.MemberInfoType); DbExpression conditionExp = new DbEqualExpression(left, right); DbUpdateExpression e = new DbUpdateExpression(dbTable, conditionExp); foreach (var item in updateColumns) { e.UpdateColumns.Add(item.Key.Column, item.Value); } int ret = this.ExecuteSqlCommand(e); if (entityState != null) { entityState.Refresh(); } return(ret); }
public virtual object Insert <TEntity>(Expression <Func <TEntity> > content, string table) { Utils.CheckNull(content); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; MappingMemberDescriptor autoIncrementMemberDescriptor = typeDescriptor.AutoIncrement; Dictionary <MemberInfo, Expression> insertColumns = InitMemberExtractor.Extract(content); DbTable explicitDbTable = null; if (table != null) { explicitDbTable = new DbTable(table, typeDescriptor.Table.Schema); } DefaultExpressionParser expressionParser = typeDescriptor.GetExpressionParser(explicitDbTable); DbInsertExpression e = new DbInsertExpression(explicitDbTable ?? typeDescriptor.Table); object keyVal = null; foreach (var kv in insertColumns) { MemberInfo key = kv.Key; MappingMemberDescriptor memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(key); if (memberDescriptor == null) { throw new ChloeException(string.Format("The member '{0}' does not map any column.", key.Name)); } if (memberDescriptor == autoIncrementMemberDescriptor) { throw new ChloeException(string.Format("Could not insert value into the identity column '{0}'.", memberDescriptor.Column.Name)); } if (memberDescriptor.IsPrimaryKey) { object val = ExpressionEvaluator.Evaluate(kv.Value); if (val == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", memberDescriptor.MemberInfo.Name)); } else { keyVal = val; e.InsertColumns.Add(memberDescriptor.Column, DbExpression.Parameter(keyVal)); continue; } } e.InsertColumns.Add(memberDescriptor.Column, expressionParser.Parse(kv.Value)); } if (keyMemberDescriptor != null) { //主键为空并且主键又不是自增列 if (keyVal == null && keyMemberDescriptor != autoIncrementMemberDescriptor) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name)); } } if (keyMemberDescriptor == null || keyMemberDescriptor != autoIncrementMemberDescriptor) { this.ExecuteSqlCommand(e); return(keyVal); /* It will return null if an entity does not define primary key. */ } IDbExpressionTranslator translator = this.DbContextServiceProvider.CreateDbExpressionTranslator(); List <DbParam> parameters; string sql = translator.Translate(e, out parameters); sql = string.Concat(sql, ";", this.GetSelectLastInsertIdClause()); //SELECT @@IDENTITY 返回的是 decimal 类型 object retIdentity = this.Session.ExecuteScalar(sql, parameters.ToArray()); if (retIdentity == null || retIdentity == DBNull.Value) { throw new ChloeException("Unable to get the identity value."); } retIdentity = ConvertIdentityType(retIdentity, autoIncrementMemberDescriptor.MemberInfoType); return(retIdentity); }
public virtual TEntity Insert <TEntity>(TEntity entity, string table) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; object keyValue = null; MappingMemberDescriptor autoIncrementMemberDescriptor = typeDescriptor.AutoIncrement; Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { MappingMemberDescriptor memberDescriptor = kv.Value; if (memberDescriptor == autoIncrementMemberDescriptor) { continue; } object val = memberDescriptor.GetValue(entity); if (memberDescriptor == keyMemberDescriptor) { keyValue = val; } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); insertColumns.Add(memberDescriptor, valExp); } if (keyMemberDescriptor != null) { //主键为空并且主键又不是自增列 if (keyValue == null && keyMemberDescriptor != autoIncrementMemberDescriptor) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name)); } } DbTable dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema); DbInsertExpression e = new DbInsertExpression(dbTable); foreach (var kv in insertColumns) { e.InsertColumns.Add(kv.Key.Column, kv.Value); } if (autoIncrementMemberDescriptor == null) { this.ExecuteSqlCommand(e); return(entity); } IDbExpressionTranslator translator = this.DbContextServiceProvider.CreateDbExpressionTranslator(); List <DbParam> parameters; string sql = translator.Translate(e, out parameters); sql = string.Concat(sql, ";", this.GetSelectLastInsertIdClause()); //SELECT @@IDENTITY 返回的是 decimal 类型 object retIdentity = this.Session.ExecuteScalar(sql, parameters.ToArray()); if (retIdentity == null || retIdentity == DBNull.Value) { throw new ChloeException("Unable to get the identity value."); } retIdentity = ConvertIdentityType(retIdentity, autoIncrementMemberDescriptor.MemberInfoType); autoIncrementMemberDescriptor.SetValue(entity, retIdentity); return(entity); }
DataTable ToSqlBulkCopyDataTable <TModel>(List <TModel> modelList, TypeDescriptor typeDescriptor) { DataTable dt = new DataTable(); List <SysColumn> columns = GetTableColumns(typeDescriptor.Table.Name); List <ColumnMapping> columnMappings = new List <ColumnMapping>(); var mappingMemberDescriptors = typeDescriptor.MappingMemberDescriptors.Select(a => a.Value).ToList(); for (int i = 0; i < columns.Count; i++) { var column = columns[i]; MappingMemberDescriptor mappingMemberDescriptor = mappingMemberDescriptors.Where(a => string.Equals(a.Column.Name, column.Name)).FirstOrDefault(); if (mappingMemberDescriptor == null) { mappingMemberDescriptor = mappingMemberDescriptors.Where(a => string.Equals(a.Column.Name, column.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); } ColumnMapping columnMapping = new ColumnMapping(column); Type dataType; if (mappingMemberDescriptor == null) { /* * 由于 SqlBulkCopy 要求传入的列必须与表列一一对应,因此,如果 model 中没有与列对应的属性,则使用列数据类型的默认值 */ SysType sysType = GetSysTypeByTypeName(column.TypeName); columnMapping.DefaultValue = column.IsNullable ? null : sysType.DefaultValue; dataType = sysType.CSharpType; } else { columnMapping.MapMember = mappingMemberDescriptor.MemberInfo; dataType = mappingMemberDescriptor.MemberInfoType.GetUnderlyingType(); if (dataType.IsEnum) { dataType = Enum.GetUnderlyingType(dataType); } } columnMappings.Add(columnMapping); dt.Columns.Add(new DataColumn(column.Name, dataType)); } foreach (var model in modelList) { DataRow dr = dt.NewRow(); for (int i = 0; i < columnMappings.Count; i++) { ColumnMapping columnMapping = columnMappings[i]; MemberInfo member = columnMapping.MapMember; object value = null; if (member == null) { value = columnMapping.DefaultValue; } else { value = member.GetMemberValue(model); if (member.GetMemberType().GetUnderlyingType().IsEnum) { if (value != null) { value = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())); } } } dr[i] = value ?? DBNull.Value; } dt.Rows.Add(dr); } return(dt); }
public override void InsertRange <TEntity>(List <TEntity> entities, bool keepIdentity = false) { /* * 将 entities 分批插入数据库 * 每批生成 insert into TableName(...) values(...),(...)... * 该方法相对循环一条一条插入,速度提升 2/3 这样 */ Utils.CheckNull(entities); if (entities.Count == 0) { return; } int maxParameters = 2100; int batchSize = 50; /* 每批实体大小,此值通过测试得出相对插入速度比较快的一个值 */ TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); var e = typeDescriptor.MappingMemberDescriptors.Select(a => a.Value); if (keepIdentity == false) { e = e.Where(a => a.IsAutoIncrement == false); } List <MappingMemberDescriptor> mappingMemberDescriptors = e.ToList(); int maxDbParamsCount = maxParameters - mappingMemberDescriptors.Count; /* 控制一个 sql 的参数个数 */ string sqlTemplate = AppendInsertRangeSqlTemplate(typeDescriptor, mappingMemberDescriptors); Action insertAction = () => { int batchCount = 0; List <DbParam> dbParams = new List <DbParam>(); StringBuilder sqlBuilder = new StringBuilder(); for (int i = 0; i < entities.Count; i++) { var entity = entities[i]; if (batchCount > 0) { sqlBuilder.Append(","); } sqlBuilder.Append("("); for (int j = 0; j < mappingMemberDescriptors.Count; j++) { if (j > 0) { sqlBuilder.Append(","); } MappingMemberDescriptor mappingMemberDescriptor = mappingMemberDescriptors[j]; object val = mappingMemberDescriptor.GetValue(entity); if (val == null) { sqlBuilder.Append("NULL"); continue; } Type valType = val.GetType(); if (valType.IsEnum) { val = Convert.ChangeType(val, Enum.GetUnderlyingType(valType)); valType = val.GetType(); } if (ToStringableNumericTypes.ContainsKey(valType)) { sqlBuilder.Append(val.ToString()); continue; } if (val is bool) { if ((bool)val == true) { sqlBuilder.AppendFormat("1"); } else { sqlBuilder.AppendFormat("0"); } continue; } else if (val is double) { double v = (double)val; if (v >= long.MinValue && v <= long.MaxValue) { sqlBuilder.Append(((long)v).ToString()); continue; } } else if (val is float) { float v = (float)val; if (v >= long.MinValue && v <= long.MaxValue) { sqlBuilder.Append(((long)v).ToString()); continue; } } else if (val is decimal) { decimal v = (decimal)val; if (v >= long.MinValue && v <= long.MaxValue) { sqlBuilder.Append(((long)v).ToString()); continue; } } string paramName = UtilConstants.ParameterNamePrefix + dbParams.Count.ToString(); DbParam dbParam = new DbParam(paramName, val) { DbType = mappingMemberDescriptor.Column.DbType }; dbParams.Add(dbParam); sqlBuilder.Append(paramName); } sqlBuilder.Append(")"); batchCount++; if ((batchCount >= 20 && dbParams.Count >= 120 /*参数个数太多也会影响速度*/) || dbParams.Count >= maxDbParamsCount || batchCount >= batchSize || (i + 1) == entities.Count) { sqlBuilder.Insert(0, sqlTemplate); string sql = sqlBuilder.ToString(); this.Session.ExecuteNonQuery(sql, dbParams.ToArray()); sqlBuilder.Clear(); dbParams.Clear(); batchCount = 0; } } }; Action fAction = () => { bool shouldTurnOff_IDENTITY_INSERT = false; string tableName = null; if (keepIdentity == true) { tableName = AppendTableName(typeDescriptor.Table); this.Session.ExecuteNonQuery(string.Format("SET IDENTITY_INSERT {0} ON ", tableName)); shouldTurnOff_IDENTITY_INSERT = true; } insertAction(); if (shouldTurnOff_IDENTITY_INSERT == true) { this.Session.ExecuteNonQuery(string.Format("SET IDENTITY_INSERT {0} OFF ", tableName)); } }; if (this.Session.IsInTransaction) { fAction(); } else { /* 因为分批插入,所以需要开启事务保证数据一致性 */ this.Session.BeginTransaction(); try { fAction(); this.Session.CommitTransaction(); } catch { if (this.Session.IsInTransaction) { this.Session.RollbackTransaction(); } throw; } } }
public override TEntity Insert <TEntity>(TEntity entity, string table) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo; object keyValue = null; string sequenceName; object sequenceValue = null; MappingMemberDescriptor defineSequenceMemberDescriptor = GetDefineSequenceMemberDescriptor(typeDescriptor, out sequenceName); if (defineSequenceMemberDescriptor != null) { sequenceValue = ConvertIdentityType(this.GetSequenceNextValue(sequenceName), defineSequenceMemberDescriptor.MemberInfoType); } Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { MemberInfo member = kv.Key; MappingMemberDescriptor memberDescriptor = kv.Value; object val = null; if (defineSequenceMemberDescriptor != null && memberDescriptor == defineSequenceMemberDescriptor) { val = sequenceValue; } else { val = memberDescriptor.GetValue(entity); } if (memberDescriptor == keyMemberDescriptor) { keyValue = val; } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); insertColumns.Add(memberDescriptor, valExp); } if (keyMemberDescriptor != null && keyValue == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name)); } DbTable dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema); DbInsertExpression e = new DbInsertExpression(dbTable); foreach (var kv in insertColumns) { e.InsertColumns.Add(kv.Key.Column, kv.Value); } this.ExecuteSqlCommand(e); if (defineSequenceMemberDescriptor != null) { defineSequenceMemberDescriptor.SetValue(entity, sequenceValue); } return(entity); }
static Expression <Func <TEntity, bool> > BuildPredicate <TEntity>(object key) { /* * key: * 如果实体是单一主键,则传入的 key 与主键属性类型相同的值 * 如果实体是多主键,则传入的 key 须是包含了与实体主键类型相同的属性的对象,如:new { Key1 = "1", Key2 = "2" } */ Utils.CheckNull(key); Type entityType = typeof(TEntity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); EnsureEntityHasPrimaryKey(typeDescriptor); KeyValuePairList <MemberInfo, object> keyValueMap = new KeyValuePairList <MemberInfo, object>(); if (typeDescriptor.PrimaryKeys.Count == 1) { keyValueMap.Add(typeDescriptor.PrimaryKeys[0].MemberInfo, key); } else { /* * key: new { Key1 = "1", Key2 = "2" } */ object multipleKeyObject = key; Type multipleKeyObjectType = multipleKeyObject.GetType(); for (int i = 0; i < typeDescriptor.PrimaryKeys.Count; i++) { MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKeys[i]; MemberInfo keyMember = multipleKeyObjectType.GetProperty(keyMemberDescriptor.MemberInfo.Name); if (keyMember == null) { throw new ArgumentException(string.Format("The input object does not define property for key '{0}'.", keyMemberDescriptor.MemberInfo.Name)); } object value = keyMember.GetMemberValue(multipleKeyObject); if (value == null) { throw new ArgumentException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name)); } keyValueMap.Add(keyMemberDescriptor.MemberInfo, value); } } ParameterExpression parameter = Expression.Parameter(entityType, "a"); Expression lambdaBody = null; foreach (var keyValue in keyValueMap) { Expression propOrField = Expression.PropertyOrField(parameter, keyValue.Key.Name); Expression wrappedValue = Chloe.Extensions.ExpressionExtension.MakeWrapperAccess(keyValue.Value, keyValue.Key.GetMemberType()); Expression e = Expression.Equal(propOrField, wrappedValue); lambdaBody = lambdaBody == null ? e : Expression.AndAlso(lambdaBody, e); } Expression <Func <TEntity, bool> > predicate = Expression.Lambda <Func <TEntity, bool> >(lambdaBody, parameter); return(predicate); }
public override TEntity Insert <TEntity>(TEntity entity, string table) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); Dictionary <MappingMemberDescriptor, object> keyValueMap = CreateKeyValueMap(typeDescriptor); string sequenceName; object sequenceValue = null; MappingMemberDescriptor defineSequenceMemberDescriptor = GetDefineSequenceMemberDescriptor(typeDescriptor, out sequenceName); if (defineSequenceMemberDescriptor != null) { if (defineSequenceMemberDescriptor.IsPrimaryKey && typeDescriptor.PrimaryKeys.Count > 1) { /* 自增列不能作为联合主键成员 */ throw new ChloeException("The member of marked sequence can not be union key."); } sequenceValue = ConvertIdentityType(this.GetSequenceNextValue(sequenceName), defineSequenceMemberDescriptor.MemberInfoType); } Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { MemberInfo member = kv.Key; MappingMemberDescriptor memberDescriptor = kv.Value; object val = null; if (defineSequenceMemberDescriptor != null && memberDescriptor == defineSequenceMemberDescriptor) { val = sequenceValue; } else { val = memberDescriptor.GetValue(entity); } if (keyValueMap.ContainsKey(memberDescriptor)) { keyValueMap[memberDescriptor] = val; } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); insertColumns.Add(memberDescriptor, valExp); } MappingMemberDescriptor nullValueKey = keyValueMap.Where(a => a.Value == null).Select(a => a.Key).FirstOrDefault(); if (nullValueKey != null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", nullValueKey.MemberInfo.Name)); } DbTable dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema); DbInsertExpression e = new DbInsertExpression(dbTable); foreach (var kv in insertColumns) { e.InsertColumns.Add(kv.Key.Column, kv.Value); } this.ExecuteSqlCommand(e); if (defineSequenceMemberDescriptor != null) { defineSequenceMemberDescriptor.SetValue(entity, sequenceValue); } return(entity); }
public override int Update <TEntity>(TEntity entity, string table) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); EnsureMappingTypeHasPrimaryKey(typeDescriptor); Dictionary <MappingMemberDescriptor, object> keyValueMap = CreateKeyValueMap(typeDescriptor); IEntityState entityState = this.TryGetTrackedEntityState(entity); Dictionary <MappingMemberDescriptor, DbExpression> updateColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { MappingMemberDescriptor memberDescriptor = kv.Value; if (keyValueMap.ContainsKey(memberDescriptor)) { keyValueMap[memberDescriptor] = memberDescriptor.GetValue(entity); continue; } SequenceAttribute attr = (SequenceAttribute)memberDescriptor.GetCustomAttribute(typeof(SequenceAttribute)); if (attr != null) { continue; } object val = memberDescriptor.GetValue(entity); if (entityState != null && !entityState.HasChanged(memberDescriptor, val)) { continue; } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); updateColumns.Add(memberDescriptor, valExp); } if (updateColumns.Count == 0) { return(0); } DbTable dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema); DbExpression conditionExp = MakeCondition(keyValueMap, dbTable); DbUpdateExpression e = new DbUpdateExpression(dbTable, conditionExp); foreach (var item in updateColumns) { e.UpdateColumns.Add(item.Key.Column, item.Value); } int ret = this.ExecuteSqlCommand(e); if (entityState != null) { entityState.Refresh(); } return(ret); }
public override void InsertRange <TEntity>(List <TEntity> entities, bool keepIdentity = false) { /* * 将 entities 分批插入数据库 * 每批生成 insert into TableName(...) select ... from dual union all select ... from dual... * 对于 oracle,貌似速度提升不了...- - * #期待各码友的优化建议# */ Utils.CheckNull(entities); if (entities.Count == 0) { return; } int maxParameters = 1000; int batchSize = 40; /* 每批实体大小,此值通过测试得出相对插入速度比较快的一个值 */ TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); var e = typeDescriptor.MappingMemberDescriptors.Select(a => a.Value); List <MappingMemberDescriptor> mappingMemberDescriptors = e.ToList(); int maxDbParamsCount = maxParameters - mappingMemberDescriptors.Count; /* 控制一个 sql 的参数个数 */ string sqlTemplate = AppendInsertRangeSqlTemplate(typeDescriptor, mappingMemberDescriptors, keepIdentity); Action insertAction = () => { int batchCount = 0; List <DbParam> dbParams = new List <DbParam>(); StringBuilder sqlBuilder = new StringBuilder(); for (int i = 0; i < entities.Count; i++) { var entity = entities[i]; if (batchCount > 0) { sqlBuilder.Append(" UNION ALL "); } sqlBuilder.Append(" SELECT "); for (int j = 0; j < mappingMemberDescriptors.Count; j++) { if (j > 0) { sqlBuilder.Append(","); } MappingMemberDescriptor mappingMemberDescriptor = mappingMemberDescriptors[j]; string sequenceName; if (keepIdentity == false && HasSequenceAttribute(mappingMemberDescriptor, out sequenceName)) { sqlBuilder.AppendFormat("1"); continue; } object val = mappingMemberDescriptor.GetValue(entity); if (val == null) { sqlBuilder.Append("NULL"); sqlBuilder.Append(" C").Append(j.ToString()); continue; } Type valType = val.GetType(); if (valType.IsEnum) { val = Convert.ChangeType(val, Enum.GetUnderlyingType(valType)); valType = val.GetType(); } if (ToStringableNumericTypes.ContainsKey(valType)) { sqlBuilder.Append(val.ToString()); } else if (val is bool) { if ((bool)val == true) { sqlBuilder.AppendFormat("1"); } else { sqlBuilder.AppendFormat("0"); } } else if (val is double) { double v = (double)val; if (v >= long.MinValue && v <= long.MaxValue) { sqlBuilder.Append(((long)v).ToString()); } } else if (val is float) { float v = (float)val; if (v >= long.MinValue && v <= long.MaxValue) { sqlBuilder.Append(((long)v).ToString()); } } else if (val is decimal) { decimal v = (decimal)val; if (v >= long.MinValue && v <= long.MaxValue) { sqlBuilder.Append(((long)v).ToString()); } } else { string paramName = UtilConstants.ParameterNamePrefix + dbParams.Count.ToString(); DbParam dbParam = new DbParam(paramName, val) { DbType = mappingMemberDescriptor.Column.DbType }; dbParams.Add(dbParam); sqlBuilder.Append(paramName); } sqlBuilder.Append(" C").Append(j.ToString()); } sqlBuilder.Append(" FROM DUAL"); batchCount++; if ((batchCount >= 20 && dbParams.Count >= 400 /*参数个数太多也会影响速度*/) || dbParams.Count >= maxDbParamsCount || batchCount >= batchSize || (i + 1) == entities.Count) { sqlBuilder.Insert(0, sqlTemplate); if (keepIdentity == false) { sqlBuilder.Append(") T"); } string sql = sqlBuilder.ToString(); this.Session.ExecuteNonQuery(sql, dbParams.ToArray()); sqlBuilder.Clear(); dbParams.Clear(); batchCount = 0; } } }; Action fAction = insertAction; if (this.Session.IsInTransaction) { fAction(); } else { /* 因为分批插入,所以需要开启事务保证数据一致性 */ this.Session.BeginTransaction(); try { fAction(); this.Session.CommitTransaction(); } catch { if (this.Session.IsInTransaction) { this.Session.RollbackTransaction(); } throw; } } }
public override T Insert <T>(T entity) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); EnsureMappingTypeHasPrimaryKey(typeDescriptor); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; var keyMember = typeDescriptor.PrimaryKey.MemberInfo; object keyValue = null; MappingMemberDescriptor autoIncrementMemberDescriptor = GetAutoIncrementMemberDescriptor(typeDescriptor); Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { var member = kv.Key; var memberDescriptor = kv.Value; if (memberDescriptor == autoIncrementMemberDescriptor) { continue; } var val = memberDescriptor.GetValue(entity); if (memberDescriptor == keyMemberDescriptor) { keyValue = val; } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); insertColumns.Add(memberDescriptor, valExp); } //主键为空并且主键又不是自增列 if (keyValue == null && keyMemberDescriptor != autoIncrementMemberDescriptor) { throw new Exception(string.Format("主键 {0} 值为 null", keyMemberDescriptor.MemberInfo.Name)); } DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table); foreach (var kv in insertColumns) { e.InsertColumns.Add(kv.Key.Column, kv.Value); } if (autoIncrementMemberDescriptor == null) { this.ExecuteSqlCommand(e); return(entity); } IDbExpressionTranslator translator = this.DbContextServiceProvider.CreateDbExpressionTranslator(); List <DbParam> parameters; string sql = translator.Translate(e, out parameters); sql += ";SELECT @@IDENTITY"; //SELECT @@IDENTITY 返回的是 decimal 类型 object retIdentity = this.CurrentSession.ExecuteScalar(sql, parameters.ToArray()); if (retIdentity == null || retIdentity == DBNull.Value) { throw new Exception("无法获取自增标识"); } retIdentity = ConvertIdentityType(retIdentity, autoIncrementMemberDescriptor.MemberInfoType); autoIncrementMemberDescriptor.SetValue(entity, retIdentity); return(entity); }
public override int Update <T>(T entity) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); EnsureMappingTypeHasPrimaryKey(typeDescriptor); object keyVal = null; MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; MemberInfo keyMember = keyMemberDescriptor.MemberInfo; IEntityState entityState = this.TryGetTrackedEntityState(entity); Dictionary <MappingMemberDescriptor, DbExpression> updateColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { var member = kv.Key; var memberDescriptor = kv.Value; if (member == keyMember) { keyVal = memberDescriptor.GetValue(entity); keyMemberDescriptor = memberDescriptor; continue; } AutoIncrementAttribute attr = (AutoIncrementAttribute)memberDescriptor.GetCustomAttribute(typeof(AutoIncrementAttribute)); if (attr != null) { continue; } var val = memberDescriptor.GetValue(entity); if (entityState != null && !entityState.IsChanged(member, val)) { continue; } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); updateColumns.Add(memberDescriptor, valExp); } if (keyVal == null) { throw new Exception(string.Format("实体主键 {0} 值为 null", keyMember.Name)); } if (updateColumns.Count == 0) { return(0); } DbExpression left = new DbColumnAccessExpression(typeDescriptor.Table, keyMemberDescriptor.Column); DbExpression right = DbExpression.Parameter(keyVal, keyMemberDescriptor.MemberInfoType); DbExpression conditionExp = new DbEqualExpression(left, right); DbUpdateExpression e = new DbUpdateExpression(typeDescriptor.Table, conditionExp); foreach (var item in updateColumns) { e.UpdateColumns.Add(item.Key.Column, item.Value); } int ret = this.ExecuteSqlCommand(e); if (entityState != null) { entityState.Refresh(); } return(ret); }
public override object Insert <T>(Expression <Func <T> > body) { Utils.CheckNull(body); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(T)); EnsureMappingTypeHasPrimaryKey(typeDescriptor); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; MappingMemberDescriptor autoIncrementMemberDescriptor = GetAutoIncrementMemberDescriptor(typeDescriptor); Dictionary <MemberInfo, Expression> insertColumns = InitMemberExtractor.Extract(body); DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table); object keyVal = null; foreach (var kv in insertColumns) { MemberInfo key = kv.Key; MappingMemberDescriptor memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(key); if (memberDescriptor == null) { throw new Exception(string.Format("成员 {0} 未映射任何列", key.Name)); } if (memberDescriptor == autoIncrementMemberDescriptor) { throw new Exception(string.Format("不能将值插入自增长列 '{0}'", memberDescriptor.Column.Name)); } if (memberDescriptor.IsPrimaryKey) { object val = ExpressionEvaluator.Evaluate(kv.Value); if (val == null) { throw new Exception(string.Format("主键 {0} 值为 null", memberDescriptor.MemberInfo.Name)); } else { keyVal = val; e.InsertColumns.Add(memberDescriptor.Column, DbExpression.Parameter(keyVal)); continue; } } e.InsertColumns.Add(memberDescriptor.Column, typeDescriptor.Visitor.Visit(kv.Value)); } //主键为空并且主键又不是自增列 if (keyVal == null && keyMemberDescriptor != autoIncrementMemberDescriptor) { throw new Exception(string.Format("主键 {0} 值为 null", keyMemberDescriptor.MemberInfo.Name)); } if (autoIncrementMemberDescriptor == null) { this.ExecuteSqlCommand(e); return(keyVal); } IDbExpressionTranslator translator = this.DbContextServiceProvider.CreateDbExpressionTranslator(); List <DbParam> parameters; string sql = translator.Translate(e, out parameters); sql += ";SELECT @@IDENTITY"; //SELECT @@IDENTITY 返回的是 decimal 类型 object retIdentity = this.CurrentSession.ExecuteScalar(sql, parameters.ToArray()); if (retIdentity == null || retIdentity == DBNull.Value) { throw new Exception("无法获取自增标识"); } retIdentity = ConvertIdentityType(retIdentity, autoIncrementMemberDescriptor.MemberInfoType); return(retIdentity); }
public override object Insert <TEntity>(Expression <Func <TEntity> > content, string table) { Utils.CheckNull(content); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); if (typeDescriptor.PrimaryKeys.Count > 1) { /* 对于多主键的实体,暂时不支持调用这个方法进行插入 */ throw new NotSupportedException(string.Format("Can not call this method because entity '{0}' has multiple keys.", typeDescriptor.EntityType.FullName)); } MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKeys.FirstOrDefault(); string sequenceName; object sequenceValue = null; MappingMemberDescriptor defineSequenceMemberDescriptor = GetDefineSequenceMemberDescriptor(typeDescriptor, out sequenceName); Dictionary <MemberInfo, Expression> insertColumns = InitMemberExtractor.Extract(content); DbTable explicitDbTable = null; if (table != null) { explicitDbTable = new DbTable(table, typeDescriptor.Table.Schema); } DefaultExpressionParser expressionParser = typeDescriptor.GetExpressionParser(explicitDbTable); DbInsertExpression e = new DbInsertExpression(explicitDbTable ?? typeDescriptor.Table); object keyVal = null; foreach (var kv in insertColumns) { MemberInfo key = kv.Key; MappingMemberDescriptor memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(key); if (memberDescriptor == null) { throw new ChloeException(string.Format("The member '{0}' does not map any column.", key.Name)); } if (memberDescriptor == defineSequenceMemberDescriptor) { throw new ChloeException(string.Format("Can not insert value into the column '{0}', because it's mapping member has define a sequence.", memberDescriptor.Column.Name)); } if (memberDescriptor.IsPrimaryKey) { object val = ExpressionEvaluator.Evaluate(kv.Value); if (val == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", memberDescriptor.MemberInfo.Name)); } else { keyVal = val; e.InsertColumns.Add(memberDescriptor.Column, DbExpression.Parameter(keyVal)); continue; } } e.InsertColumns.Add(memberDescriptor.Column, expressionParser.Parse(kv.Value)); } if (keyMemberDescriptor == defineSequenceMemberDescriptor) { sequenceValue = ConvertIdentityType(this.GetSequenceNextValue(sequenceName), defineSequenceMemberDescriptor.MemberInfoType); keyVal = sequenceValue; e.InsertColumns.Add(keyMemberDescriptor.Column, DbExpression.Parameter(keyVal)); } if (keyMemberDescriptor != null && keyVal == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name)); } this.ExecuteSqlCommand(e); return(keyVal); /* It will return null if an entity does not define primary key. */ }
static Expression <Func <TEntity, bool> > BuildCondition <TEntity>(object key) { /* * key: * 如果实体是单一主键,可以传入的 key 与主键属性类型相同的值,亦可以传一个包含了与实体主键类型相同的属性的对象,如:new { Id = 1 } * 如果实体是多主键,则传入的 key 须是包含了与实体主键类型相同的属性的对象,如:new { Key1 = "1", Key2 = "2" } */ Utils.CheckNull(key); Type entityType = typeof(TEntity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); EnsureEntityHasPrimaryKey(typeDescriptor); ParameterExpression parameter = Expression.Parameter(entityType, "a"); Expression conditionBody = null; Type keyType = key.GetType(); if (typeDescriptor.PrimaryKeys.Count == 1 && MappingTypeSystem.IsMappingType(keyType)) { /* a => a.Key == key */ MappingMemberDescriptor keyDescriptor = typeDescriptor.PrimaryKeys[0]; Expression propOrField = Expression.PropertyOrField(parameter, keyDescriptor.MemberInfo.Name); Expression wrappedValue = ExpressionExtension.MakeWrapperAccess(key, keyDescriptor.MemberInfoType); conditionBody = Expression.Equal(propOrField, wrappedValue); } else { /* * key: new { Key1 = "1", Key2 = "2" } */ /* a => a.Key1 == key.Key1 && a.Key2 == key.Key2 */ Type keyObjectType = keyType; ConstantExpression keyConstantExp = Expression.Constant(key); if (keyObjectType == entityType) { foreach (MappingMemberDescriptor primaryKey in typeDescriptor.PrimaryKeys) { Expression propOrField = Expression.PropertyOrField(parameter, primaryKey.MemberInfo.Name); Expression keyValue = Expression.MakeMemberAccess(keyConstantExp, primaryKey.MemberInfo); Expression e = Expression.Equal(propOrField, keyValue); conditionBody = conditionBody == null ? e : Expression.AndAlso(conditionBody, e); } } else { for (int i = 0; i < typeDescriptor.PrimaryKeys.Count; i++) { MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKeys[i]; MemberInfo keyMember = keyMemberDescriptor.MemberInfo; MemberInfo inputKeyMember = keyObjectType.GetMember(keyMember.Name).FirstOrDefault(); if (inputKeyMember == null) { throw new ArgumentException(string.Format("The input object does not define property for key '{0}'.", keyMember.Name)); } Expression propOrField = Expression.PropertyOrField(parameter, keyMember.Name); Expression keyValueExp = Expression.MakeMemberAccess(keyConstantExp, inputKeyMember); Type keyMemberType = keyMember.GetMemberType(); if (inputKeyMember.GetMemberType() != keyMemberType) { keyValueExp = Expression.Convert(keyValueExp, keyMemberType); } Expression e = Expression.Equal(propOrField, keyValueExp); conditionBody = conditionBody == null ? e : Expression.AndAlso(conditionBody, e); } } } Expression <Func <TEntity, bool> > condition = Expression.Lambda <Func <TEntity, bool> >(conditionBody, parameter); return(condition); }
public override object Insert <TEntity>(Expression <Func <TEntity> > body) { Utils.CheckNull(body); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); EnsureMappingTypeHasPrimaryKey(typeDescriptor); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; string sequenceName; object sequenceValue = null; MappingMemberDescriptor defineSequenceMemberDescriptor = GetDefineSequenceMemberDescriptor(typeDescriptor, out sequenceName); Dictionary <MemberInfo, Expression> insertColumns = InitMemberExtractor.Extract(body); DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table); object keyVal = null; foreach (var kv in insertColumns) { MemberInfo key = kv.Key; MappingMemberDescriptor memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(key); if (memberDescriptor == null) { throw new ChloeException(string.Format("The member '{0}' does not map any column.", key.Name)); } if (memberDescriptor == defineSequenceMemberDescriptor) { throw new ChloeException(string.Format("Can not insert value into the column '{0}',because it's mapping member has define a sequence.", memberDescriptor.Column.Name)); } if (memberDescriptor.IsPrimaryKey) { object val = ExpressionEvaluator.Evaluate(kv.Value); if (val == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", memberDescriptor.MemberInfo.Name)); } else { keyVal = val; e.InsertColumns.Add(memberDescriptor.Column, DbExpression.Parameter(keyVal)); continue; } } e.InsertColumns.Add(memberDescriptor.Column, typeDescriptor.Visitor.Visit(kv.Value)); } if (keyMemberDescriptor == defineSequenceMemberDescriptor) { sequenceValue = ConvertIdentityType(this.GetSequenceNextValue(sequenceName), defineSequenceMemberDescriptor.MemberInfoType); keyVal = sequenceValue; e.InsertColumns.Add(keyMemberDescriptor.Column, DbExpression.Parameter(keyVal)); } if (keyVal == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name)); } this.ExecuteSqlCommand(e); return(keyVal); }