static List <IMemberBinder> PrepareMemberBinders(Type type, IDataReader reader, ObjectMemberMapper mapper) { List <IMemberBinder> memberBinders = new List <IMemberBinder>(reader.FieldCount); MemberInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); MemberInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetField); List <MemberInfo> members = new List <MemberInfo>(properties.Length + fields.Length); members.AddRange(properties); members.AddRange(fields); TypeDescriptor typeDescriptor = EntityTypeContainer.TryGetDescriptor(type); for (int i = 0; i < reader.FieldCount; i++) { string name = reader.GetName(i); MemberInfo mapMember = TryGetMapMember(members, name, typeDescriptor); if (mapMember == null) { continue; } MRMTuple mMapperTuple = mapper.GetMappingMemberMapper(mapMember); if (mMapperTuple == null) { continue; } PrimitiveMemberBinder memberBinder = new PrimitiveMemberBinder(mapMember, mMapperTuple, i); memberBinders.Add(memberBinder); } return(memberBinders); }
string CreateTableScript(Type entityType) { TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entityType); string tableName = typeDescriptor.Table.Name; StringBuilder sb = new StringBuilder(); sb.AppendLine($"IF NOT EXISTS (select * from sysobjects where name='{tableName}' and xtype='U')"); sb.Append($"CREATE TABLE {this.QuoteName(tableName)}("); string c = ""; foreach (var propertyDescriptor in typeDescriptor.PrimitivePropertyDescriptors) { sb.AppendLine(c); sb.Append($" {this.BuildColumnPart(propertyDescriptor)}"); c = ","; } if (typeDescriptor.PrimaryKeys.Count > 0) { string key = typeDescriptor.PrimaryKeys.First().Column.Name; string constraintName = $"PK_{tableName}"; sb.AppendLine(c); sb.Append($"CONSTRAINT {this.QuoteName(constraintName)} PRIMARY KEY CLUSTERED ( {this.QuoteName(key)} ASC )"); } sb.AppendLine(); sb.Append(");"); return(sb.ToString()); }
public virtual void TrackEntity(object entity) { Utils.CheckNull(entity); Type entityType = entity.GetType(); if (ReflectionExtension.IsAnonymousType(entityType)) { return; } Dictionary <Type, TrackEntityCollection> entityContainer = this.TrackingEntityContainer; TrackEntityCollection collection; if (!entityContainer.TryGetValue(entityType, out collection)) { TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entityType); if (!typeDescriptor.HasPrimaryKey()) { return; } collection = new TrackEntityCollection(typeDescriptor); entityContainer.Add(entityType, collection); } collection.TryAddEntity(entity); }
async Task Save <TEntity>(TEntity entity, TypeDescriptor declaringTypeDescriptor, bool @async) { await this.Insert(entity, null, @async); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(typeof(TEntity)); for (int i = 0; i < typeDescriptor.ComplexPropertyDescriptors.Count; i++) { //entity.TOther ComplexPropertyDescriptor navPropertyDescriptor = typeDescriptor.ComplexPropertyDescriptors[i]; if (declaringTypeDescriptor != null && navPropertyDescriptor.PropertyType == declaringTypeDescriptor.Definition.Type) { continue; } await this.SaveOneToOne(navPropertyDescriptor, entity, typeDescriptor, @async); } for (int i = 0; i < typeDescriptor.CollectionPropertyDescriptors.Count; i++) { //entity.List CollectionPropertyDescriptor collectionPropertyDescriptor = typeDescriptor.CollectionPropertyDescriptors[i]; await this.SaveCollection(collectionPropertyDescriptor, entity, typeDescriptor, @async); } }
static async Task <int> Update <TEntity>(IDbContext dbContext, TEntity entity, Expression <Func <TEntity, bool> > condition, bool @async) { PublicHelper.CheckNull(dbContext); PublicHelper.CheckNull(entity); PublicHelper.CheckNull(condition); Type entityType = typeof(TEntity); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entityType); List <MemberBinding> bindings = new List <MemberBinding>(); ConstantExpression entityConstantExp = Expression.Constant(entity); foreach (PrimitivePropertyDescriptor propertyDescriptor in typeDescriptor.PrimitivePropertyDescriptors) { if (propertyDescriptor.CannotUpdate()) { continue; } Expression entityMemberAccess = Expression.MakeMemberAccess(entityConstantExp, propertyDescriptor.Property); MemberAssignment bind = Expression.Bind(propertyDescriptor.Property, entityMemberAccess); bindings.Add(bind); } return(await UpdateOnly(dbContext, condition, bindings, @async)); }
public IObjectActivator CreateObjectActivator(IDbContext dbContext) { InstanceCreator instanceCreator = this.ConstructorDescriptor.GetInstanceCreator(); List <IObjectActivator> argumentActivators = this.CreateArgumentActivators(dbContext); List <IMemberBinder> memberBinders = this.CreateMemberBinders(dbContext); IObjectActivator objectActivator; if (dbContext != null) { objectActivator = new ObjectActivatorWithTracking(instanceCreator, argumentActivators, memberBinders, this.CheckNullOrdinal, dbContext); } else { objectActivator = new ComplexObjectActivator(instanceCreator, argumentActivators, memberBinders, this.CheckNullOrdinal); } if (this.IsRoot && this.HasMany()) { TypeDescriptor entityTypeDescriptor = EntityTypeContainer.GetDescriptor(this.ObjectType); List <Tuple <PropertyDescriptor, int> > keys = new List <Tuple <PropertyDescriptor, int> >(entityTypeDescriptor.PrimaryKeys.Count); foreach (PrimitivePropertyDescriptor primaryKey in entityTypeDescriptor.PrimaryKeys) { keys.Add(new Tuple <PropertyDescriptor, int>(primaryKey, this.PrimitiveMembers[primaryKey.Definition.Property])); } IEntityRowComparer entityRowComparer = new EntityRowComparer(keys); objectActivator = new RootEntityActivator(objectActivator, this.CreateFitter(dbContext), entityRowComparer); } return(objectActivator); }
public override int Update <TEntity>(TEntity entity, string table) { PublicHelper.CheckNull(entity); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entity.GetType()); PublicHelper.EnsureHasPrimaryKey(typeDescriptor); Dictionary <PropertyDescriptor, object> keyValueMap = CreateKeyValueMap(typeDescriptor); IEntityState entityState = this.TryGetTrackedEntityState(entity); Dictionary <PropertyDescriptor, DbExpression> updateColumns = new Dictionary <PropertyDescriptor, DbExpression>(); foreach (PropertyDescriptor propertyDescriptor in typeDescriptor.PropertyDescriptors) { if (keyValueMap.ContainsKey(propertyDescriptor)) { keyValueMap[propertyDescriptor] = propertyDescriptor.GetValue(entity); continue; } bool hasSequence = propertyDescriptor.HasSequence(); if (hasSequence) { continue; } object val = propertyDescriptor.GetValue(entity); if (entityState != null && !entityState.HasChanged(propertyDescriptor, val)) { continue; } DbExpression valExp = DbExpression.Parameter(val, propertyDescriptor.PropertyType, propertyDescriptor.Column.DbType); updateColumns.Add(propertyDescriptor, 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); }
ComplexObjectModel GenComplexObjectModel(ComplexPropertyDescriptor navigationDescriptor, NavigationNode navigationNode, QueryModel queryModel) { TypeDescriptor navigationTypeDescriptor = EntityTypeContainer.GetDescriptor(navigationDescriptor.PropertyType); DbTable dbTable = navigationTypeDescriptor.Table; DbTableExpression tableExp = new DbTableExpression(dbTable); string alias = queryModel.GenerateUniqueTableAlias(dbTable.Name); DbTableSegment joinTableSeg = new DbTableSegment(tableExp, alias, queryModel.FromTable.Table.Lock); DbTable aliasTable = new DbTable(alias); ComplexObjectModel navigationObjectModel = navigationTypeDescriptor.GenObjectModel(aliasTable); navigationObjectModel.NullChecking = navigationObjectModel.PrimaryKey; PrimitivePropertyDescriptor foreignKeyPropertyDescriptor = navigationDescriptor.ForeignKeyProperty; DbExpression foreignKeyColumn = this.GetPrimitiveMember(foreignKeyPropertyDescriptor.Property); DbExpression joinCondition = DbExpression.Equal(foreignKeyColumn, navigationObjectModel.PrimaryKey); DbJoinTableExpression joinTableExp = new DbJoinTableExpression(foreignKeyPropertyDescriptor.IsNullable ? DbJoinType.LeftJoin : DbJoinType.InnerJoin, joinTableSeg, joinCondition); this.DependentTable.JoinTables.Add(joinTableExp); navigationObjectModel.DependentTable = joinTableExp; DbExpression condition = this.ParseCondition(navigationNode.Condition, navigationObjectModel, queryModel.ScopeTables); //AndWhere的条件放到join条件里去 joinTableExp.AppendCondition(condition); navigationObjectModel.Filter = this.ParseCondition(navigationNode.Filter, navigationObjectModel, queryModel.ScopeTables); //queryModel.Filters.Add(navigationObjectModel.Filter); return(navigationObjectModel); }
public override int Delete <TEntity>(TEntity entity, string table) { PublicHelper.CheckNull(entity); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(typeof(TEntity)); PublicHelper.EnsureHasPrimaryKey(typeDescriptor); Dictionary <PropertyDescriptor, object> keyValueMap = new Dictionary <PropertyDescriptor, object>(typeDescriptor.PrimaryKeys.Count); foreach (PropertyDescriptor keyPropertyDescriptor in typeDescriptor.PrimaryKeys) { object keyVal = keyPropertyDescriptor.GetValue(entity); keyValueMap.Add(keyPropertyDescriptor, keyVal); } DbTable dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema); PropertyDescriptor timestampProperty = typeDescriptor.PropertyDescriptors.Where(a => a.IsTimestamp()).FirstOrDefault(); if (timestampProperty != null) { object timestampValue = timestampProperty.GetValue(entity); if (timestampValue != null) { keyValueMap[timestampProperty] = timestampValue; } } DbExpression conditionExp = PrimaryKeyHelper.MakeCondition(keyValueMap, dbTable); DbDeleteExpression e = new DbDeleteExpression(dbTable, conditionExp); return(this.ExecuteNonQuery(e)); }
/// <summary> /// dbContext.Update<User>(user, a => a.Id == 1) /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="dbContext"></param> /// <param name="entity"></param> /// <param name="condition"></param> /// <returns></returns> public static int Update <TEntity>(this IDbContext dbContext, TEntity entity, Expression <Func <TEntity, bool> > condition) { PublicHelper.CheckNull(dbContext); PublicHelper.CheckNull(entity); PublicHelper.CheckNull(condition); Type entityType = typeof(TEntity); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entityType); List <MemberBinding> bindings = new List <MemberBinding>(); ConstantExpression entityConstantExp = Expression.Constant(entity); foreach (PrimitivePropertyDescriptor propertyDescriptor in typeDescriptor.PrimitivePropertyDescriptors) { if (propertyDescriptor.IsPrimaryKey || propertyDescriptor.IsAutoIncrement) { continue; } Expression entityMemberAccess = Expression.MakeMemberAccess(entityConstantExp, propertyDescriptor.Property); MemberAssignment bind = Expression.Bind(propertyDescriptor.Property, entityMemberAccess); bindings.Add(bind); } return(UpdateOnly(dbContext, condition, bindings)); }
string CreateTableScript(Type entityType) { TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entityType); string tableName = typeDescriptor.Table.Name; StringBuilder sb = new StringBuilder(); sb.Append($"CREATE TABLE IF NOT EXISTS {this.QuoteName(tableName)}("); string c = ""; foreach (var propertyDescriptor in typeDescriptor.PrimitivePropertyDescriptors) { sb.AppendLine(c); sb.Append($" {this.BuildColumnPart(propertyDescriptor)}"); c = ","; } if (typeDescriptor.PrimaryKeys.Count > 0) { string key = typeDescriptor.PrimaryKeys.First().Column.Name; sb.AppendLine(c); sb.Append($" PRIMARY KEY ({this.QuoteName(key)}) USING BTREE"); } sb.AppendLine(); sb.Append(");"); return(sb.ToString()); }
public override TEntity Insert <TEntity>(TEntity entity, string table) { PublicHelper.CheckNull(entity); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(typeof(TEntity)); List <PropertyDescriptor> outputColumns = new List <PropertyDescriptor>(); Dictionary <PropertyDescriptor, DbExpression> insertColumns = new Dictionary <PropertyDescriptor, DbExpression>(); foreach (PropertyDescriptor propertyDescriptor in typeDescriptor.PropertyDescriptors) { if (propertyDescriptor.IsAutoIncrement) { outputColumns.Add(propertyDescriptor); continue; } if (propertyDescriptor.HasSequence()) { DbMethodCallExpression getNextValueForSequenceExp = PublicHelper.MakeNextValueForSequenceDbExpression(propertyDescriptor); insertColumns.Add(propertyDescriptor, getNextValueForSequenceExp); outputColumns.Add(propertyDescriptor); continue; } object val = propertyDescriptor.GetValue(entity); DbExpression valExp = DbExpression.Parameter(val, propertyDescriptor.PropertyType, propertyDescriptor.Column.DbType); insertColumns.Add(propertyDescriptor, valExp); } 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); } e.Returns.AddRange(outputColumns.Select(a => a.Column)); List <DbParam> parameters; this.ExecuteNonQuery(e, out parameters); List <DbParam> outputParams = parameters.Where(a => a.Direction == ParamDirection.Output).ToList(); for (int i = 0; i < outputColumns.Count; i++) { PropertyDescriptor propertyDescriptor = outputColumns[i]; string putputColumnName = Utils.GenOutputColumnParameterName(propertyDescriptor.Column.Name); DbParam outputParam = outputParams.Where(a => a.Name == putputColumnName).First(); var outputValue = PublicHelper.ConvertObjType(outputParam.Value, propertyDescriptor.PropertyType); outputColumns[i].SetValue(entity, outputValue); } return(entity); }
public override TEntity Insert <TEntity>(TEntity entity, string table) { PublicHelper.CheckNull(entity); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entity.GetType()); Dictionary <PropertyDescriptor, object> keyValueMap = CreateKeyValueMap(typeDescriptor); Dictionary <PropertyDescriptor, object> sequenceValues = this.GetSequenceValues(typeDescriptor.PropertyDescriptors.Where(a => a.HasSequence()).ToList()); Dictionary <PropertyDescriptor, DbExpression> insertColumns = new Dictionary <PropertyDescriptor, DbExpression>(); foreach (PropertyDescriptor propertyDescriptor in typeDescriptor.PropertyDescriptors) { object val = null; if (propertyDescriptor.HasSequence()) { val = sequenceValues[propertyDescriptor]; } else { val = propertyDescriptor.GetValue(entity); } if (propertyDescriptor.IsPrimaryKey) { keyValueMap[propertyDescriptor] = val; } DbExpression valExp = DbExpression.Parameter(val, propertyDescriptor.PropertyType, propertyDescriptor.Column.DbType); insertColumns.Add(propertyDescriptor, valExp); } PropertyDescriptor 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.Property.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); foreach (var kv in sequenceValues) { kv.Key.SetValue(entity, kv.Value); } return(entity); }
/// <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: 只支持简单的映射,不支持复杂的对应关系 */ PublicHelper.CheckNull(source); List <MemberBinding> bindings = new List <MemberBinding>(); Type entityType = source.ElementType; Type modelType = typeof(TModel); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entityType); var mappingPropertyDescriptors = typeDescriptor.PrimitivePropertyDescriptors.ToDictionary(a => a.Property.Name, a => a); var props = modelType.GetProperties(); ParameterExpression parameter = Expression.Parameter(typeDescriptor.Definition.Type, "a"); foreach (var prop in props) { if (prop.GetSetMethod() == null) { continue; } PrimitivePropertyDescriptor mapPropertyDescriptor; if (mappingPropertyDescriptors.TryGetValue(prop.Name, out mapPropertyDescriptor) == false) { continue; } Expression sourceMemberAccess = Expression.MakeMemberAccess(parameter, mapPropertyDescriptor.Property); if (prop.PropertyType != mapPropertyDescriptor.PropertyType) { 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 Update <TEntity>(Expression <Func <TEntity, bool> > condition, Expression <Func <TEntity, TEntity> > content, string table, int limits) { Utils.CheckNull(condition); Utils.CheckNull(content); TypeDescriptor typeDescriptor = EntityTypeContainer.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); MySqlDbUpdateExpression e = new MySqlDbUpdateExpression(explicitDbTable ?? typeDescriptor.Table, conditionExp); foreach (var kv in updateColumns) { MemberInfo key = kv.Key; PropertyDescriptor propertyDescriptor = typeDescriptor.TryGetPropertyDescriptor(key); if (propertyDescriptor == null) { throw new ChloeException(string.Format("The member '{0}' does not map any column.", key.Name)); } if (propertyDescriptor.IsPrimaryKey) { throw new ChloeException(string.Format("Could not update the primary key '{0}'.", propertyDescriptor.Column.Name)); } if (propertyDescriptor.IsAutoIncrement) { throw new ChloeException(string.Format("Could not update the identity column '{0}'.", propertyDescriptor.Column.Name)); } e.UpdateColumns.Add(propertyDescriptor.Column, expressionParser.Parse(kv.Value)); } e.Limits = limits; if (e.UpdateColumns.Count == 0) { return(0); } return(this.ExecuteSqlCommand(e)); }
static async Task <int> UpdateOnly <TEntity>(IDbContext dbContext, TEntity entity, string[] fields, bool @async) { PublicHelper.CheckNull(dbContext); PublicHelper.CheckNull(entity); PublicHelper.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 = typeof(TEntity); TypeDescriptor typeDescriptor = EntityTypeContainer.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 propertyDescriptor = typeDescriptor.FindPrimitivePropertyDescriptor(memberInfo); if (propertyDescriptor == null) { throw new ArgumentException(string.Format("Could not find the member '{0}' from entity.", propertyDescriptor.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 (PrimitivePropertyDescriptor primaryKey in typeDescriptor.PrimaryKeys) { Expression propOrField = Expression.PropertyOrField(parameter, primaryKey.Property.Name); Expression keyValue = Expression.MakeMemberAccess(entityConstantExp, primaryKey.Property); 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(await UpdateOnly(dbContext, condition, bindings, @async)); }
public override int Update <TEntity>(Expression <Func <TEntity, bool> > condition, Expression <Func <TEntity, TEntity> > content, string table) { PublicHelper.CheckNull(condition); PublicHelper.CheckNull(content); TypeDescriptor typeDescriptor = EntityTypeContainer.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; PropertyDescriptor propertyDescriptor = typeDescriptor.TryGetPropertyDescriptor(key); if (propertyDescriptor == null) { throw new ChloeException(string.Format("The member '{0}' does not map any column.", key.Name)); } if (propertyDescriptor.IsPrimaryKey) { throw new ChloeException(string.Format("Could not update the primary key '{0}'.", propertyDescriptor.Column.Name)); } bool hasSequence = propertyDescriptor.HasSequence(); if (hasSequence) { throw new ChloeException(string.Format("Could not update the column '{0}', because it's mapping member has define a sequence.", propertyDescriptor.Column.Name)); } e.UpdateColumns.Add(propertyDescriptor.Column, expressionParser.Parse(kv.Value)); } if (e.UpdateColumns.Count == 0) { return(0); } return(this.ExecuteNonQuery(e)); }
public IQuery <T> IncludeAll() { TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(typeof(T)); object lastQuery = this; for (int i = 0; i < typeDescriptor.NavigationPropertyDescriptors.Count; i++) { PropertyDescriptor propertyDescriptor = typeDescriptor.NavigationPropertyDescriptors[i]; lastQuery = this.Include(typeDescriptor, lastQuery, propertyDescriptor); } return((IQuery <T>)lastQuery); }
protected virtual async Task <int> Delete <TEntity>(Expression <Func <TEntity, bool> > condition, string table, bool @async) { PublicHelper.CheckNull(condition); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(typeof(TEntity)); DbTable dbTable = typeDescriptor.GenDbTable(table); DefaultExpressionParser expressionParser = typeDescriptor.GetExpressionParser(dbTable); DbExpression conditionExp = expressionParser.ParseFilterPredicate(condition); DbDeleteExpression e = new DbDeleteExpression(dbTable, conditionExp); return(await this.ExecuteNonQuery(e, @async)); }
/// <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) { PublicHelper.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 = EntityTypeContainer.GetDescriptor(entityType); var mappingPropertyDescriptors = typeDescriptor.PrimitivePropertyDescriptors.ToList(); ParameterExpression parameter = Expression.Parameter(entityType, "a"); foreach (var mappingPropertyDescriptor in mappingPropertyDescriptors) { if (fields.Any(a => a == mappingPropertyDescriptor.Property.Name)) { continue; } Expression sourceMemberAccess = Expression.MakeMemberAccess(parameter, mappingPropertyDescriptor.Property); MemberAssignment bind = Expression.Bind(mappingPropertyDescriptor.Property, 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)); }
static ResultElement CreateResultElement(Type type, string explicitTableName, LockType lockType, ScopeParameterDictionary scopeParameters, KeyDictionary <string> scopeTables) { 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(scopeParameters, scopeTables); TypeDescriptor typeDescriptor = EntityTypeContainer.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, lockType); ConstructorInfo constructor = typeDescriptor.Definition.Type.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 (PropertyDescriptor item in typeDescriptor.PropertyDescriptors) { DbColumnAccessExpression columnAccessExpression = new DbColumnAccessExpression(table, item.Column); moe.AddMappingMemberExpression(item.Property, columnAccessExpression); if (item.IsPrimaryKey) { moe.PrimaryKey = columnAccessExpression; } } resultElement.MappingObjectExpression = moe; return(resultElement); }
/// <summary> /// Gets the name of the data table used by this type. /// </summary> /// <param name="typeId">The id.</param> /// <returns> /// The name of the data table used by this entity type. /// </returns> public static string GetDataTableName(long typeId) { EntityTypeContainer container; ///// // Hit the cache. ///// Instance.TryGetValue(typeId, out container); if (container == null || (container.DataTableNameMember == null && !container.DataTableNameResolvedMember)) { ///// // Initialize the dataTable to be a relationship. ///// string dataTableName = "Relationship"; long dbFieldTableId = WellKnownAliases.CurrentTenant.DbFieldTable; using (DatabaseContext ctx = DatabaseContext.GetContext()) { using (IDbCommand command = ctx.CreateCommand()) { command.CommandText = "dbo.spData_NVarCharRead"; command.CommandType = CommandType.StoredProcedure; ctx.AddParameter(command, "@entityId", DbType.Int64, typeId); ctx.AddParameter(command, "@tenantId", DbType.Int64, RequestContext.TenantId); ctx.AddParameter(command, "@fieldId", DbType.Int64, dbFieldTableId); using (IDataReader reader = command.ExecuteReader()) { if (reader.Read() && !reader.IsDBNull(3)) { dataTableName = reader.GetString(3); } } } } if (container == null) { container = new EntityTypeContainer(typeId); Instance[typeId] = container; } container.DataTableName = dataTableName; } return(container.DataTableName); }
public IFitter CreateFitter(IDbContext dbContext) { List <Tuple <PropertyDescriptor, IFitter> > includings = new List <Tuple <PropertyDescriptor, IFitter> >(); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(this.ConstructorDescriptor.ConstructorInfo.DeclaringType); foreach (var item in this.ComplexMembers.Concat(this.CollectionMembers)) { IFitter propFitter = item.Value.CreateFitter(dbContext); includings.Add(new Tuple <PropertyDescriptor, IFitter>(typeDescriptor.GetPropertyDescriptor(item.Key), propFitter)); } ComplexObjectFitter fitter = new ComplexObjectFitter(includings); return(fitter); }
async Task SaveOneToOne(ComplexPropertyDescriptor navPropertyDescriptor, object owner, TypeDescriptor ownerTypeDescriptor, bool @async) { /* * 1:1 * T <1:1> TOther * T.TOther <--> TOther.T * T.Id <--> TOther.Id */ //owner is T //navPropertyDescriptor is T.TOther //TypeDescriptor of T.TOther TypeDescriptor navTypeDescriptor = EntityTypeContainer.GetDescriptor(navPropertyDescriptor.PropertyType); //TOther.T ComplexPropertyDescriptor TOtherDotT = navTypeDescriptor.ComplexPropertyDescriptors.Where(a => a.PropertyType == ownerTypeDescriptor.Definition.Type).FirstOrDefault(); bool isOneToOne = TOtherDotT != null; if (!isOneToOne) { return; } //instance of T.TOther object navValue = navPropertyDescriptor.GetValue(owner); if (navValue == null) { return; } //T.Id PrimitivePropertyDescriptor foreignKeyProperty = navPropertyDescriptor.ForeignKeyProperty; if (foreignKeyProperty.IsAutoIncrement || foreignKeyProperty.HasSequence()) { //value of T.Id object foreignKeyValue = foreignKeyProperty.GetValue(owner); //T.TOther.Id = T.Id TOtherDotT.ForeignKeyProperty.SetValue(navValue, foreignKeyValue); } MethodInfo saveMethod = GetSaveMethod(navPropertyDescriptor.PropertyType); //DbContext.Save(navValue, ownerTypeDescriptor, @async); Task task = (Task)saveMethod.Invoke(this, navValue, ownerTypeDescriptor, @async); await task; }
/// <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 = EntityTypeContainer.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 int Delete <TEntity>(Expression <Func <TEntity, bool> > condition, string table, int limits) { PublicHelper.CheckNull(condition); TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(typeof(TEntity)); DbTable dbTable = PublicHelper.CreateDbTable(typeDescriptor, table); DefaultExpressionParser expressionParser = typeDescriptor.GetExpressionParser(dbTable); DbExpression conditionExp = expressionParser.ParseFilterPredicate(condition); MySqlDbDeleteExpression e = new MySqlDbDeleteExpression(dbTable, conditionExp); e.Limits = limits; return(this.ExecuteNonQuery(e)); }
/// <summary> /// Determines whether the specified type id is literal. /// </summary> /// <param name="typeId">The type id.</param> /// <returns> /// <c>true</c> if the specified type id is literal; otherwise, <c>false</c>. /// </returns> public static bool IsLiteral(long typeId) { EntityTypeContainer container; ///// // Hit the cache. ///// Instance.TryGetValue(typeId, out container); if (container == null) { container = new EntityTypeContainer(typeId); Instance[typeId] = container; } return(container.IsLiteralInner); }
/// <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 = EntityTypeContainer.GetDescriptor(entityType); /* 设置 主键=guid */ if (typeDescriptor.PrimaryKeys.Count < 2) /* 只有无主键或单一主键的时候 */ { var primaryKeyDescriptor = typeDescriptor.PrimaryKeys.FirstOrDefault(); if (primaryKeyDescriptor != null && primaryKeyDescriptor.IsAutoIncrement == false) { var keyValue = primaryKeyDescriptor.GetValue(entity); if (keyValue.IsDefaultValueOfType(primaryKeyDescriptor.PropertyType) || string.Empty.Equals(keyValue)) { /* 如果未设置主键值,则自动设置为 guid */ if (primaryKeyDescriptor.PropertyType == typeof(string)) { primaryKeyDescriptor.SetValue(entity, IdHelper.CreateSnowflakeId().ToString()); } else if (primaryKeyDescriptor.PropertyType.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)); }
public static TypeDescriptor GetPropertyTypeDescriptor(this PropertyDescriptor propertyDescriptor) { ComplexPropertyDescriptor complexPropertyDescriptor = propertyDescriptor as ComplexPropertyDescriptor; Type type; if (complexPropertyDescriptor != null) { type = propertyDescriptor.PropertyType; } else { type = (propertyDescriptor as CollectionPropertyDescriptor).ElementType; } return(EntityTypeContainer.GetDescriptor(type)); }
/// <summary> /// Gets the assignable types for the specified type name. /// </summary> /// <param name="typeId">The type id.</param> /// <returns> /// A set of type identifiers that represent the assignable types for the specified type. /// </returns> public static HashSet <long> GetAssignableTypes(long typeId) { EntityTypeContainer container; ///// // Hit the cache. ///// Instance.TryGetValue(typeId, out container); if (container == null || container.AssignableTypesMember == null) { var assignableTypes = new HashSet <long> { typeId }; ///// // Add the current type. ///// IEntity entityType = Entity.Get(new EntityRef(typeId)); if (entityType != null) { long inheritsId = WellKnownAliases.CurrentTenant.Inherits; var inheritsEntityRef = new EntityRef(inheritsId); ///// // Add the 'inherits' types (base types). ///// AggregateTypes(entityType, inheritsEntityRef, Direction.Forward, assignableTypes); } if (container == null) { container = new EntityTypeContainer(typeId); Instance[typeId] = container; } container.AssignableTypes = assignableTypes; } return(container.AssignableTypes); }