public virtual int Delete <TEntity>(TEntity entity) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); EnsureEntityHasPrimaryKey(typeDescriptor); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo; var keyVal = keyMemberDescriptor.GetValue(entity); if (keyVal == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMember.Name)); } DbExpression left = new DbColumnAccessExpression(typeDescriptor.Table, keyMemberDescriptor.Column); DbExpression right = new DbParameterExpression(keyVal); DbExpression conditionExp = new DbEqualExpression(left, right); DbDeleteExpression e = new DbDeleteExpression(typeDescriptor.Table, conditionExp); return(this.ExecuteSqlCommand(e)); }
public virtual void TrackEntity(object entity) { Utils.CheckNull(entity); Type entityType = entity.GetType(); if (Utils.IsAnonymousType(entityType)) { return; } Dictionary <Type, TrackEntityCollection> entityContainer = this.TrackingEntityContainer; TrackEntityCollection collection; if (!entityContainer.TryGetValue(entityType, out collection)) { TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); if (!typeDescriptor.HasPrimaryKey()) { return; } collection = new TrackEntityCollection(typeDescriptor); entityContainer.Add(entityType, collection); } collection.TryAddEntity(entity); }
/// <summary> /// /// </summary> /// <param name="fieldsLambdaExpression">a => new object[] { a.Name, a.Age }</param> /// <returns></returns> public static List <string> Pick(LambdaExpression fieldsLambdaExpression) { ParameterExpression parameterExpression = fieldsLambdaExpression.Parameters[0]; NewArrayExpression newArrayExpression = fieldsLambdaExpression.Body as NewArrayExpression; if (newArrayExpression == null) { throw new NotSupportedException(fieldsLambdaExpression.ToString()); } Type entityType = parameterExpression.Type; TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); List <string> fields = new List <string>(newArrayExpression.Expressions.Count); foreach (var item in newArrayExpression.Expressions) { MemberExpression memberExp = ExpressionExtension.StripConvert(item) as MemberExpression; if (memberExp == null) { throw new NotSupportedException(item.ToString()); } if (memberExp.Expression != parameterExpression) { throw new NotSupportedException(item.ToString()); } fields.Add(memberExp.Member.Name); } return(fields); }
/// <summary> /// 修改 /// </summary> /// <param name="entity"></param> /// <returns></returns> public TEntity Edit(TEntity entity) { Checks.NotNull(entity, "entity"); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); object keyVal = null; MappingMemberDescriptor keyMemberDescriptor = null; Dictionary <MappingMemberDescriptor, DbExpression> updateColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { MemberInfo member = kv.Key; MappingMemberDescriptor memberDescriptor = kv.Value; object val = memberDescriptor.GetValue(entity); if (memberDescriptor.SZColumnAttribute.IsKey) { if (val == null) { throw new SZORMException("主键值不允许为空."); } keyVal = val; keyMemberDescriptor = memberDescriptor; continue; } if (memberDescriptor.SZColumnAttribute.IsEditTime) { val = DateTime.Now; memberDescriptor.SetValue(entity, val); } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); updateColumns.Add(memberDescriptor, valExp); } 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); } IDbExpressionTranslator translator = this.DbContext.DatabaseProvider.CreateDbExpressionTranslator(); List <DbParam> parameters; string sql = translator.Translate(e, out parameters); this.DbContext.ExecuteNoQuery(sql, parameters.ToArray()); return(entity); }
/// <summary> /// 利用 SqlBulkCopy 批量插入数据。 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="entities"></param> /// <param name="batchSize">设置 SqlBulkCopy.BatchSize 的值</param> /// <param name="bulkCopyTimeout">设置 SqlBulkCopy.BulkCopyTimeout 的值</param> /// <param name="keepIdentity">是否保留源标识值。false 由数据库分配标识值。</param> public virtual void BulkInsert <TEntity>(List <TEntity> entities, int?batchSize = null, int?bulkCopyTimeout = null, bool keepIdentity = false) { Utils.CheckNull(entities); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); DataTable dtToWrite = ToSqlBulkCopyDataTable(entities, typeDescriptor); SqlBulkCopy sbc = null; bool shouldCloseConnection = false; SqlConnection conn = this.Session.CurrentConnection as SqlConnection; try { SqlTransaction externalTransaction = null; if (this.Session.IsInTransaction) { externalTransaction = this.Session.CurrentTransaction as SqlTransaction; } SqlBulkCopyOptions sqlBulkCopyOptions = keepIdentity ? (SqlBulkCopyOptions.KeepNulls | SqlBulkCopyOptions.KeepIdentity) : SqlBulkCopyOptions.KeepNulls; sbc = new SqlBulkCopy(conn, sqlBulkCopyOptions, externalTransaction); using (sbc) { if (batchSize != null) { sbc.BatchSize = batchSize.Value; } sbc.DestinationTableName = AppendTableName(typeDescriptor.Table); if (bulkCopyTimeout != null) { sbc.BulkCopyTimeout = bulkCopyTimeout.Value; } if (conn.State != ConnectionState.Open) { conn.Open(); shouldCloseConnection = true; } sbc.WriteToServer(dtToWrite); } } finally { if (conn != null) { if (shouldCloseConnection && conn.State == ConnectionState.Open) { conn.Close(); } } } }
/// <summary> /// dbContext.Query<User>().MapTo<UserModel>() /// <para>该方法调用者的 IQuery.ElementType 必须是实体类型</para> /// </summary> /// <typeparam name="TModel"></typeparam> /// <param name="source"></param> /// <returns></returns> public static IQuery <TModel> MapTo <TModel>(this IQuery source) { /* * 根据 TEntity 与 TModel 属性对应关系构建 selector 表达式树,最后调用 Select() 方法 * dbContext.Query<User>().Select(a => new UserModel() { Id = a.Id, Name = a.Name }); * ps: 只支持简单的映射,不支持复杂的对应关系 */ Utils.CheckNull(source); List <MemberBinding> bindings = new List <MemberBinding>(); Type entityType = source.ElementType; Type modelType = typeof(TModel); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); var mappingMemberDescriptors = typeDescriptor.MappingMemberDescriptors.Select(a => a.Value).ToDictionary(a => a.MemberInfo.Name, a => a); var props = modelType.GetProperties(); ParameterExpression parameter = Expression.Parameter(typeDescriptor.EntityType, "a"); foreach (var prop in props) { if (prop.GetSetMethod() == null) { continue; } MappingMemberDescriptor mapMemberDescriptor; if (mappingMemberDescriptors.TryGetValue(prop.Name, out mapMemberDescriptor) == false) { continue; } Expression sourceMemberAccess = Expression.MakeMemberAccess(parameter, mapMemberDescriptor.MemberInfo); if (prop.PropertyType != mapMemberDescriptor.MemberInfoType) { sourceMemberAccess = Expression.Convert(sourceMemberAccess, prop.PropertyType); } MemberAssignment bind = Expression.Bind(prop, sourceMemberAccess); bindings.Add(bind); } NewExpression newExp = Expression.New(modelType); Expression selectorBody = Expression.MemberInit(newExp, bindings); Type funcType = typeof(Func <,>).MakeGenericType(entityType, modelType); LambdaExpression selector = Expression.Lambda(funcType, selectorBody, parameter); MethodInfo methodInfo_Select = source.GetType().GetMethod("Select").MakeGenericMethod(modelType); var obj = methodInfo_Select.Invoke(source, new object[] { selector }); return((IQuery <TModel>)obj); }
public virtual int Delete <TEntity>(Expression <Func <TEntity, bool> > condition) { Utils.CheckNull(condition); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); DbExpression conditionExp = typeDescriptor.Visitor.VisitFilterPredicate(condition); DbDeleteExpression e = new DbDeleteExpression(typeDescriptor.Table, conditionExp); return(this.ExecuteSqlCommand(e)); }
public virtual object Insert <T>(Expression <Func <T> > body) { Utils.CheckNull(body); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(T)); EnsureMappingTypeHasPrimaryKey(typeDescriptor); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; 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.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 (keyVal == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name)); } this.ExecuteSqlCommand(e); return(keyVal); }
/// <summary> /// dbContext.UpdateOnly<User>(user, "Name,Age", "NickName") /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="dbContext"></param> /// <param name="entity"></param> /// <param name="fields"></param> /// <returns></returns> public static int UpdateOnly <TEntity>(this IDbContext dbContext, TEntity entity, params string[] fields) { Utils.CheckNull(dbContext); Utils.CheckNull(entity); Utils.CheckNull(fields); /* 支持 context.UpdateOnly<User>(user, "Name,Age", "NickName"); */ fields = fields.SelectMany(a => a.Split(',')).Select(a => a.Trim()).ToArray(); if (fields.Length == 0) { throw new ArgumentException("fields"); } Type entityType = entity.GetType(); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); List <MemberBinding> bindings = new List <MemberBinding>(); ConstantExpression entityConstantExp = Expression.Constant(entity); foreach (string field in fields) { MemberInfo memberInfo = entityType.GetMember(field)[0]; var memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(memberInfo); if (memberDescriptor == null) { throw new ArgumentException(string.Format("Could not find the member '{0}' from entity.", memberDescriptor.Column.Name)); } Expression entityMemberAccess = Expression.MakeMemberAccess(entityConstantExp, memberInfo); MemberAssignment bind = Expression.Bind(memberInfo, entityMemberAccess); bindings.Add(bind); } ParameterExpression parameter = Expression.Parameter(entityType, "a"); Expression conditionBody = null; foreach (MappingMemberDescriptor primaryKey in typeDescriptor.PrimaryKeys) { Expression propOrField = Expression.PropertyOrField(parameter, primaryKey.MemberInfo.Name); Expression keyValue = Expression.MakeMemberAccess(entityConstantExp, primaryKey.MemberInfo); Expression e = Expression.Equal(propOrField, keyValue); conditionBody = conditionBody == null ? e : Expression.AndAlso(conditionBody, e); } Expression <Func <TEntity, bool> > condition = Expression.Lambda <Func <TEntity, bool> >(conditionBody, parameter); return(UpdateOnly(dbContext, condition, bindings)); }
public override int Update <TEntity>(Expression <Func <TEntity, bool> > condition, Expression <Func <TEntity, TEntity> > content, string table) { Utils.CheckNull(condition); Utils.CheckNull(content); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); Dictionary <MemberInfo, Expression> updateColumns = InitMemberExtractor.Extract(content); DbTable explicitDbTable = null; if (table != null) { explicitDbTable = new DbTable(table, typeDescriptor.Table.Schema); } DefaultExpressionParser expressionParser = typeDescriptor.GetExpressionParser(explicitDbTable); DbExpression conditionExp = expressionParser.ParseFilterPredicate(condition); DbUpdateExpression e = new DbUpdateExpression(explicitDbTable ?? typeDescriptor.Table, conditionExp); foreach (var kv in updateColumns) { 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.IsPrimaryKey) { throw new ChloeException(string.Format("Could not update the primary key '{0}'.", memberDescriptor.Column.Name)); } SequenceAttribute attr = (SequenceAttribute)memberDescriptor.GetCustomAttribute(typeof(SequenceAttribute)); if (attr != null) { throw new ChloeException(string.Format("Could not update the column '{0}',because it's mapping member has define a sequence.", memberDescriptor.Column.Name)); } e.UpdateColumns.Add(memberDescriptor.Column, expressionParser.Parse(kv.Value)); } if (e.UpdateColumns.Count == 0) { return(0); } return(this.ExecuteSqlCommand(e)); }
/// <summary> /// dbContext.Query<User>().MapTo<User, UserModel>().ToList(); /// </summary> /// <typeparam name="TEntity"></typeparam> /// <typeparam name="TModel"></typeparam> /// <param name="source"></param> /// <returns></returns> public static IQuery <TModel> MapTo <TEntity, TModel>(this IQuery <TEntity> source) { /* * Usage: * dbContext.Query<User>().MapTo<User, UserModel>().ToList(); */ /* * 根据 TEntity 与 TModel 属性对应关系构建 selector 表达式树,最后调用 Select() 方法 * dbContext.Query<User>().Select(a => new UserModel() { Id = a.Id, Name = a.Name }); * ps: 只支持简单的映射,不支持复杂的对应关系 */ List <MemberBinding> bindings = new List <MemberBinding>(); Type modelType = typeof(TModel); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); var mappingMemberDescriptors = typeDescriptor.MappingMemberDescriptors.Select(a => a.Value).ToDictionary(a => a.MemberInfo.Name, a => a); var props = modelType.GetProperties(); ParameterExpression parameter = Expression.Parameter(typeDescriptor.EntityType, "a"); foreach (var prop in props) { if (prop.GetSetMethod() == null) { continue; } MappingMemberDescriptor mapMemberDescriptor; if (mappingMemberDescriptors.TryGetValue(prop.Name, out mapMemberDescriptor) == false) { continue; } Expression sourceMemberAccess = Expression.MakeMemberAccess(parameter, mapMemberDescriptor.MemberInfo); if (prop.PropertyType != mapMemberDescriptor.MemberInfoType) { sourceMemberAccess = Expression.Convert(sourceMemberAccess, prop.PropertyType); } MemberAssignment bind = Expression.Bind(prop, sourceMemberAccess); bindings.Add(bind); } NewExpression newExp = Expression.New(modelType); Expression selectorBody = Expression.MemberInit(newExp, bindings); Expression <Func <TEntity, TModel> > selector = Expression.Lambda <Func <TEntity, TModel> >(selectorBody, parameter); return(source.Select(selector)); }
/// <summary> /// 增加 /// </summary> /// <param name="body">() => new User() { Name = "lu", Age = 18, Gender = Gender.Man, CityId = 1, OpTime = DateTime.Now }</param> /// <returns></returns> public string Add(Expression <Func <TEntity> > body) { Checks.NotNull(body, "body"); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); Dictionary <MemberInfo, Expression> insertColumns = InitMemberExtractor.Extract(body); DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table); string keyVal = null; foreach (var kv in insertColumns) { MemberInfo key = kv.Key; MappingMemberDescriptor memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(key); //如果是主键 if (memberDescriptor.SZColumnAttribute.IsKey) { object val = ExpressionEvaluator.Evaluate(kv.Value); if (val == null || string.IsNullOrEmpty(val.ToString())) { val = GetNewKey(); keyVal = val.ToString(); e.InsertColumns.Add(memberDescriptor.Column, DbExpression.Parameter(keyVal)); continue; } } //如果是添加或修改时间 if (memberDescriptor.SZColumnAttribute.IsAddTime || memberDescriptor.SZColumnAttribute.IsEditTime) { object val = ExpressionEvaluator.Evaluate(kv.Value); val = DateTime.Now; e.InsertColumns.Add(memberDescriptor.Column, DbExpression.Parameter(keyVal)); continue; } e.InsertColumns.Add(memberDescriptor.Column, typeDescriptor.Visitor.Visit(kv.Value)); } IDbExpressionTranslator translator = this.DbContext._dbContextServiceProvider.CreateDbExpressionTranslator(); List <DbParam> parameters; string sql = translator.Translate(e, out parameters); this.DbContext.ExecuteNoQuery(sql, parameters.ToArray()); return(keyVal); }
/// <summary> /// dbContext.Query<User>().Ignore<User>("Name,Age", "NickName") /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="source"></param> /// <param name="fields"></param> /// <returns></returns> public static IQuery <TEntity> Ignore <TEntity>(this IQuery <TEntity> source, params string[] fields) { Utils.CheckNull(source); if (fields == null) { return(source); } /* 支持 source.Ignore<User>("Name,Age", "NickName"); */ fields = fields.SelectMany(a => a.Split(',')).Select(a => a.Trim()).ToArray(); if (fields.Length == 0) { return(source); } List <MemberBinding> bindings = new List <MemberBinding>(); Type entityType = source.ElementType; TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); var mappingMemberDescriptors = typeDescriptor.MappingMemberDescriptors.Select(a => a.Value).ToList(); ParameterExpression parameter = Expression.Parameter(entityType, "a"); foreach (var mappingMemberDescriptor in mappingMemberDescriptors) { if (fields.Any(a => a == mappingMemberDescriptor.MemberInfo.Name)) { continue; } Expression sourceMemberAccess = Expression.MakeMemberAccess(parameter, mappingMemberDescriptor.MemberInfo); MemberAssignment bind = Expression.Bind(mappingMemberDescriptor.MemberInfo, sourceMemberAccess); bindings.Add(bind); } if (bindings.Count == 0) { throw new Exception("There are no fields to map after ignore."); } NewExpression newExp = Expression.New(entityType); Expression selectorBody = Expression.MemberInit(newExp, bindings); Expression <Func <TEntity, TEntity> > selector = Expression.Lambda <Func <TEntity, TEntity> >(selectorBody, parameter); return(source.Select(selector)); }
/// <summary> /// 序列化对象为键值对 /// </summary> /// <param name="name">对象名称</param> /// <param name="obj">对象实例</param> /// <param name="options">选项</param> /// <exception cref="ArgumentNullException"></exception> /// <returns></returns> protected virtual IEnumerable <KeyValuePair <string, string> > Serialize( string name, object obj, FormatOptions options) { if (options == null) { options = new FormatOptions(); } var type = obj == null ? null : obj.GetType(); var descriptor = TypeDescriptor.GetDescriptor(type); if (descriptor == null || descriptor.IsSimpleType == true) { return(new[] { this.SerializeAsSimple(name, obj, options) }); } if (type == typeof(KeyValuePair <string, string>)) { var kv = (KeyValuePair <string, string>)obj; return(new[] { this.SerializeAsSimple(kv.Key, kv.Value, options) }); } if (type == typeof(KeyValuePair <string, object>)) { var kv = (KeyValuePair <string, object>)obj; return(new[] { this.SerializeAsSimple(kv.Key, kv.Value, options) }); } if (descriptor.IsEnumerableKeyValueOfString == true) { var dic = obj as IEnumerable <KeyValuePair <string, string> >; return(this.SerializeAsDictionary <string>(dic, options)); } if (descriptor.IsEnumerableKeyValueOfObject == true) { var dic = obj as IEnumerable <KeyValuePair <string, object> >; return(this.SerializeAsDictionary <object>(dic, options)); } if (descriptor.IsEnumerable == true) { var enumerable = obj as IEnumerable; return(this.SerializeAsEnumerable(name, enumerable, options)); } return(this.SerializeAsComplex(obj, options)); }
static ResultElement CreateResultElement(Type type, string explicitTableName) { if (type.IsAbstract || type.IsInterface) { throw new ArgumentException("The type of input can not be abstract class or interface."); } //TODO init _resultElement ResultElement resultElement = new ResultElement(); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(type); DbTable dbTable = typeDescriptor.Table; if (explicitTableName != null) { dbTable = new DbTable(explicitTableName, dbTable.Schema); } string alias = resultElement.GenerateUniqueTableAlias(dbTable.Name); resultElement.FromTable = CreateRootTable(dbTable, alias); ConstructorInfo constructor = typeDescriptor.EntityType.GetConstructor(Type.EmptyTypes); if (constructor == null) { throw new ArgumentException(string.Format("The type of '{0}' does't define a none parameter constructor.", type.FullName)); } MappingObjectExpression moe = new MappingObjectExpression(constructor); DbTableSegment tableExp = resultElement.FromTable.Table; DbTable table = new DbTable(alias); foreach (MappingMemberDescriptor item in typeDescriptor.MappingMemberDescriptors.Values) { DbColumnAccessExpression columnAccessExpression = new DbColumnAccessExpression(table, item.Column); moe.AddMappingMemberExpression(item.MemberInfo, columnAccessExpression); if (item.IsPrimaryKey) { moe.PrimaryKey = columnAccessExpression; } } resultElement.MappingObjectExpression = moe; return(resultElement); }
/// <summary> /// 条件删除 /// </summary> /// <param name="condition"></param> /// <returns></returns> public int Remove(Expression <Func <TEntity, bool> > condition) { Checks.NotNull(condition, "condition"); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); DbExpression conditionExp = typeDescriptor.Visitor.VisitFilterPredicate(condition); DbDeleteExpression e = new DbDeleteExpression(typeDescriptor.Table, conditionExp); IDbExpressionTranslator translator = this.DbContext._dbContextServiceProvider.CreateDbExpressionTranslator(); List <DbParam> parameters; string sql = translator.Translate(e, out parameters); return(this.DbContext.ExecuteNoQuery(sql, parameters.ToArray())); }
/// <summary> /// /// </summary> /// <param name="fieldsLambdaExpression">a => new { a.Name, a.Age } or a => new object[] { a.Name, a.Age }</param> /// <returns></returns> public static List <string> Resolve(LambdaExpression fieldsLambdaExpression) { ParameterExpression parameterExpression = fieldsLambdaExpression.Parameters[0]; var body = ExpressionExtension.StripConvert(fieldsLambdaExpression.Body); ReadOnlyCollection <Expression> fieldExps = null; NewExpression newExpression = body as NewExpression; if (newExpression != null && newExpression.Type.IsAnonymousType()) { fieldExps = newExpression.Arguments; } else { NewArrayExpression newArrayExpression = body as NewArrayExpression; if (newArrayExpression == null) { throw new NotSupportedException(fieldsLambdaExpression.ToString()); } fieldExps = newArrayExpression.Expressions; } Type entityType = parameterExpression.Type; TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); List <string> fields = new List <string>(fieldExps.Count); foreach (var item in fieldExps) { MemberExpression memberExp = ExpressionExtension.StripConvert(item) as MemberExpression; if (memberExp == null) { throw new NotSupportedException(item.ToString()); } if (memberExp.Expression != parameterExpression) { throw new NotSupportedException(item.ToString()); } fields.Add(memberExp.Member.Name); } return(fields); }
public virtual T Insert <T>(T entity) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); EnsureMappingTypeHasPrimaryKey(typeDescriptor); MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey; MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo; object keyValue = null; Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { MemberInfo member = kv.Key; MappingMemberDescriptor memberDescriptor = kv.Value; var val = memberDescriptor.GetValue(entity); if (memberDescriptor == keyMemberDescriptor) { keyValue = val; } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); insertColumns.Add(memberDescriptor, valExp); } //主键为空并且主键又不是自增列 if (keyValue == null) { throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name)); } DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table); foreach (var kv in insertColumns) { e.InsertColumns.Add(kv.Key.Column, kv.Value); } this.ExecuteSqlCommand(e); return(entity); }
public override JoinQueryResult Visit(RootQueryExpression exp) { Type type = exp.ElementType; TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(type); string explicitTableName = exp.ExplicitTable; DbTable dbTable = typeDescriptor.Table; if (explicitTableName != null) { dbTable = new DbTable(explicitTableName, dbTable.Schema); } string alias = this._resultElement.GenerateUniqueTableAlias(dbTable.Name); DbTableSegment tableSeg = CreateTableExpression(dbTable, alias); MappingObjectExpression moe = new MappingObjectExpression(typeDescriptor.EntityType.GetConstructor(Type.EmptyTypes)); DbTable table = new DbTable(alias); foreach (MappingMemberDescriptor item in typeDescriptor.MappingMemberDescriptors.Values) { DbColumnAccessExpression columnAccessExpression = new DbColumnAccessExpression(table, item.Column); moe.AddMemberExpression(item.MemberInfo, columnAccessExpression); if (item.IsPrimaryKey) { moe.PrimaryKey = columnAccessExpression; } } //TODO 解析 on 条件表达式 DbExpression condition = null; List <IMappingObjectExpression> moeList = new List <IMappingObjectExpression>(this._moeList.Count + 1); moeList.AddRange(this._moeList); moeList.Add(moe); condition = GeneralExpressionVisitor.ParseLambda(this._conditionExpression, moeList); DbJoinTableExpression joinTable = new DbJoinTableExpression(this._joinType, tableSeg, condition); JoinQueryResult result = new JoinQueryResult(); result.MappingObjectExpression = moe; result.JoinTable = joinTable; return(result); }
/// <summary> /// 添加 /// </summary> /// <param name="entity"></param> /// <returns></returns> public TEntity Add(TEntity entity) { Checks.NotNull(entity, "entity"); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>(); foreach (var kv in typeDescriptor.MappingMemberDescriptors) { MemberInfo member = kv.Key; MappingMemberDescriptor memberDescriptor = kv.Value; object val = memberDescriptor.GetValue(entity); if (memberDescriptor.SZColumnAttribute.IsKey) { if (val == null || string.IsNullOrEmpty(val.ToString())) { val = GetNewKey(); memberDescriptor.SetValue(entity, val); } } if (memberDescriptor.SZColumnAttribute.IsAddTime || memberDescriptor.SZColumnAttribute.IsEditTime) { val = DateTime.Now; memberDescriptor.SetValue(entity, val); } DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType); insertColumns.Add(memberDescriptor, valExp); } DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table); foreach (var kv in insertColumns) { e.InsertColumns.Add(kv.Key.Column, kv.Value); } IDbExpressionTranslator translator = this.DbContext.DatabaseProvider.CreateDbExpressionTranslator(); List <DbParam> parameters; string sql = translator.Translate(e, out parameters); this.DbContext.ExecuteNoQuery(sql, parameters.ToArray()); return(entity); }
/// <summary> /// 传入一个 dto 对象插入数据。dto 需要与实体建立映射关系,否则会报错 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <typeparam name="TDto"></typeparam> /// <param name="dbContext"></param> /// <param name="dto"></param> /// <returns></returns> public static TEntity InsertFromDto <TEntity, TDto>(this IDbContext dbContext, TDto dto) { /* * 支持自动设置 主键=guid * 支持自动设置 CreationTime=DateTime.Now * 支持自动设置 IsDeleted=false */ Utils.CheckNull(dto); TEntity entity = AceMapper.Map <TEntity>(dto); Type entityType = typeof(TEntity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); /* 设置 主键=guid */ if (typeDescriptor.PrimaryKeys.Count < 2) /* 只有无主键或单一主键的时候 */ { MappingMemberDescriptor primaryKeyDescriptor = typeDescriptor.PrimaryKeys.FirstOrDefault(); if (primaryKeyDescriptor != null && primaryKeyDescriptor.IsAutoIncrement == false) { var keyValue = primaryKeyDescriptor.GetValue(entity); if (keyValue.IsDefaultValueOfType(primaryKeyDescriptor.MemberInfoType) || string.Empty.Equals(keyValue)) { /* 如果未设置主键值,则自动设置为 guid */ if (primaryKeyDescriptor.MemberInfoType == typeof(string)) { primaryKeyDescriptor.SetValue(entity, IdHelper.CreateGuid()); } else if (primaryKeyDescriptor.MemberInfoType.GetUnderlyingType() == typeof(Guid)) { primaryKeyDescriptor.SetValue(entity, Guid.NewGuid()); } } } } /* 设置 CreationTime=DateTime.Now */ SetValueIfNeeded(entity, typeDescriptor, "CreationTime", DateTime.Now); /* 设置 IsDeleted=false */ SetValueIfNeeded(entity, typeDescriptor, "IsDeleted", false); return(dbContext.Insert(entity)); }
static Expression <Func <TEntity, bool> > BuildPredicate <TEntity>(object key) { Utils.CheckNull(key); Type entityType = typeof(TEntity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); EnsureEntityHasPrimaryKey(typeDescriptor); ParameterExpression parameter = Expression.Parameter(entityType, "a"); Expression propOrField = Expression.PropertyOrField(parameter, typeDescriptor.PrimaryKey.MemberInfo.Name); Expression keyValue = Chloe.Extensions.ExpressionExtension.MakeWrapperAccess(key, typeDescriptor.PrimaryKey.MemberInfoType); Expression lambdaBody = Expression.Equal(propOrField, keyValue); Expression <Func <TEntity, bool> > predicate = Expression.Lambda <Func <TEntity, bool> >(lambdaBody, parameter); return(predicate); }
public virtual int Delete <TEntity>(Expression <Func <TEntity, bool> > condition, string table) { Utils.CheckNull(condition); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); DbTable explicitDbTable = null; if (table != null) { explicitDbTable = new DbTable(table, typeDescriptor.Table.Schema); } DefaultExpressionParser expressionParser = typeDescriptor.GetExpressionParser(explicitDbTable); DbExpression conditionExp = expressionParser.ParseFilterPredicate(condition); DbDeleteExpression e = new DbDeleteExpression(explicitDbTable ?? typeDescriptor.Table, conditionExp); return(this.ExecuteSqlCommand(e)); }
public static Expression <Func <TEntity, bool> > BuildPredicate <TEntity>(object key) { Checks.NotNull(key, "key"); Type entityType = typeof(TEntity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); if (typeDescriptor.PrimaryKey == null) { throw new SZORMException("表没有定义主键."); } ParameterExpression parameter = Expression.Parameter(entityType, "a"); Expression propOrField = Expression.PropertyOrField(parameter, typeDescriptor.PrimaryKey.MemberInfo.Name); Expression keyValue = ExpressionExtension.MakeWrapperAccess(key, typeDescriptor.PrimaryKey.MemberInfoType); Expression lambdaBody = Expression.Equal(propOrField, keyValue); Expression <Func <TEntity, bool> > predicate = Expression.Lambda <Func <TEntity, bool> >(lambdaBody, parameter); return(predicate); }
public virtual int Update <TEntity>(Expression <Func <TEntity, bool> > condition, Expression <Func <TEntity, TEntity> > body) { Utils.CheckNull(condition); Utils.CheckNull(body); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity)); Dictionary <MemberInfo, Expression> updateColumns = InitMemberExtractor.Extract(body); DbExpression conditionExp = typeDescriptor.Visitor.VisitFilterPredicate(condition); DbUpdateExpression e = new DbUpdateExpression(typeDescriptor.Table, conditionExp); foreach (var kv in updateColumns) { 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.IsPrimaryKey) { throw new ChloeException(string.Format("Could not update the primary key '{0}'.", memberDescriptor.Column.Name)); } if (memberDescriptor.IsAutoIncrement) { throw new ChloeException(string.Format("Could not update the identity column '{0}'.", memberDescriptor.Column.Name)); } e.UpdateColumns.Add(memberDescriptor.Column, typeDescriptor.Visitor.Visit(kv.Value)); } if (e.UpdateColumns.Count == 0) { return(0); } return(this.ExecuteSqlCommand(e)); }
/// <summary> /// 序列化对象为键值对 /// </summary> /// <param name="name">对象名称</param> /// <param name="obj">对象实例</param> /// <param name="options">选项</param> /// <exception cref="ArgumentNullException"></exception> /// <returns></returns> protected virtual IEnumerable <KeyValuePair <string, string> > Serialize( string name, object obj, FormatOptions options) { if (options == null) { options = new FormatOptions(); } var type = obj == null ? null : obj.GetType(); var context = new ConvertContext { Name = name, Value = obj, Options = options, Descriptor = TypeDescriptor.GetDescriptor(type) }; return(this.linkedList.First.Value.Invoke(context)); }
static Expression <Func <TEntity, bool> > BuildPredicate <TEntity>(object key) { Utils.CheckNull(key); Type entityType = typeof(TEntity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType); if (!typeDescriptor.HasPrimaryKey()) { throw new ChloeException(string.Format("The entity type '{0}' does not define a primary key.", typeDescriptor.EntityType.FullName)); } ParameterExpression parameter = Expression.Parameter(entityType, "a"); Expression propOrField = Expression.PropertyOrField(parameter, typeDescriptor.PrimaryKey.MemberInfo.Name); Expression keyValue = Utils.MakeWrapperAccess(key, typeDescriptor.PrimaryKey.MemberInfoType); Expression lambdaBody = Expression.Equal(propOrField, keyValue); Expression <Func <TEntity, bool> > predicate = Expression.Lambda <Func <TEntity, bool> >(lambdaBody, parameter); return(predicate); }
public virtual int Delete <TEntity>(TEntity entity, string table) { Utils.CheckNull(entity); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType()); EnsureEntityHasPrimaryKey(typeDescriptor); Dictionary <MappingMemberDescriptor, object> keyValueMap = new Dictionary <MappingMemberDescriptor, object>(); foreach (MappingMemberDescriptor keyMemberDescriptor in typeDescriptor.PrimaryKeys) { object keyVal = keyMemberDescriptor.GetValue(entity); keyValueMap.Add(keyMemberDescriptor, keyVal); } DbTable dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema); DbExpression conditionExp = MakeCondition(keyValueMap, dbTable); DbDeleteExpression e = new DbDeleteExpression(dbTable, conditionExp); return(this.ExecuteSqlCommand(e)); }
public override int Update <T>(Expression <Func <T, T> > body, Expression <Func <T, bool> > condition) { Utils.CheckNull(body); Utils.CheckNull(condition); TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(T)); Dictionary <MemberInfo, Expression> updateColumns = InitMemberExtractor.Extract(body); var conditionExp = typeDescriptor.Visitor.VisitFilterPredicate(condition); DbUpdateExpression e = new DbUpdateExpression(typeDescriptor.Table, conditionExp); foreach (var kv in updateColumns) { MemberInfo key = kv.Key; MappingMemberDescriptor memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(key); if (memberDescriptor == null) { throw new Exception(string.Format("成员 {0} 未映射任何列", key.Name)); } if (memberDescriptor.IsPrimaryKey) { throw new Exception(string.Format("无法对主键 '{0}' 进行更新", memberDescriptor.Column.Name)); } AutoIncrementAttribute attr = (AutoIncrementAttribute)memberDescriptor.GetCustomAttribute(typeof(AutoIncrementAttribute)); if (attr != null) { throw new Exception(string.Format("无法对自增长列 '{0}' 进行更新", memberDescriptor.Column.Name)); } e.UpdateColumns.Add(memberDescriptor.Column, typeDescriptor.Visitor.Visit(kv.Value)); } return(this.ExecuteSqlCommand(e)); }
/// <summary> /// 序列化对象为键值对 /// </summary> /// <param name="name">对象名称</param> /// <param name="obj">对象实例</param> /// <param name="options">选项</param> /// <exception cref="ArgumentNullException"></exception> /// <returns></returns> public IEnumerable <KeyValuePair <string, string> > Serialize(string name, object obj, FormatOptions options) { if (options == null) { options = new FormatOptions(); } var type = obj == null ? null : obj.GetType(); var descriptor = TypeDescriptor.GetDescriptor(type); if (descriptor == null || descriptor.IsSimpleType == true) { var kv = this.FormatAsSimple(name, obj, options); return(new[] { kv }); } if (descriptor.IsDictionaryOfString == true) { var dic = obj as IDictionary <string, string>; return(this.FormatAsDictionary <string>(dic, options)); } if (descriptor.IsDictionaryOfObject == true) { var dic = obj as IDictionary <string, object>; return(this.FormatAsDictionary <object>(dic, options)); } if (descriptor.IsEnumerable == true) { var enumerable = obj as IEnumerable; return(this.ForamtAsEnumerable(name, enumerable, options)); } return(this.FormatAsComplex(obj, options)); }