/// <summary> /// 使用主键和外键对应构造一对多的关系。 /// </summary> /// <param name="thisType"></param> /// <param name="otherType"></param> /// <returns></returns> private static RelationshipMetadata MakeOne2ManyMetadata(Type thisType, Type otherType) { var pks = PropertyUnity.GetPrimaryProperties(thisType).ToList(); if (pks.Count > 0) { var fks = pks.Select(s => PropertyUnity.GetProperty(otherType, s.Name)).ToList(); var keys = new RelationshipKey[pks.Count]; for (var i = 0; i < pks.Count; i++) { if (fks[i] == null) { throw new Exception(); } keys[i] = new RelationshipKey { ThisKey = pks[i].Name, ThisProperty = pks[i], OtherKey = fks[i].Name, OtherProperty = fks[i] }; } return(new RelationshipMetadata(thisType, otherType, RelationshipStyle.One2Many, keys)); } return(null); }
/// <summary> /// 检查有没有关联属性被修改. /// </summary> /// <param name="entity"></param> /// <returns></returns> private bool CheckRelationHasModified(IEntity entity) { //判断实体类型有是不是编译的代理类型,如果不是,取非null的属性,否则使用IsModified判断 var isNotCompiled = entity.GetType().IsNotCompiled(); return(PropertyUnity.GetRelatedProperties(entity.EntityType).Any(s => isNotCompiled ? !PropertyValue.IsEmpty(entity.GetValue(s)) : entity.IsModified(s.Name))); }
/// <summary> /// 通过主键值使对象正常化。 /// </summary> /// <param name="entity"></param> /// <param name="keyValues">主键值数组。</param> /// <returns></returns> public static T Normalize <T>(this T entity, params object[] keyValues) where T : IEntity { var primaryKeys = PropertyUnity.GetPrimaryProperties(entity.EntityType).ToArray(); if (primaryKeys.Length != 0 && keyValues == null || primaryKeys.Length != keyValues.Length) { throw new Exception(SR.GetString(SRKind.DisaccordArgument, primaryKeys.Length, keyValues.Length)); } var extend = entity as IEntityStatefulExtension; if (extend == null) { return(entity); } for (var i = 0; i < primaryKeys.Length; i++) { extend.InitializateValue(primaryKeys[i], PropertyValue.New(keyValues[i], primaryKeys[i].Type)); } extend.SetState(EntityState.Modified); return(entity); }
/// <summary> /// 解析键对表达式。 /// </summary> /// <param name="thisType"></param> /// <param name="otherType"></param> /// <param name="keyExpression">键对表达式,如 "父键1=>子键1,父键2=>子键2"。</param> private static IEnumerable <RelationshipKey> ParseRelationshipKeys(Type thisType, Type otherType, string keyExpression) { Guard.ArgumentNull(keyExpression, "keyExpression"); var keys = keyExpression.Split(','); var list = new List <RelationshipKey>(); foreach (var pair in keys.Where(pair => !string.IsNullOrEmpty(pair))) { string thisKey, otherKey; if (!ParseRelationKey(pair, out thisKey, out otherKey)) { continue; } list.Add(new RelationshipKey { ThisKey = thisKey, ThisProperty = PropertyUnity.GetProperty(thisType, thisKey), OtherKey = otherKey, OtherProperty = PropertyUnity.GetProperty(otherType, otherKey) }); } return(list); }
/// <summary> /// 获取可以组织到查询里的属性。 /// </summary> /// <returns></returns> private IEnumerable <IProperty> GetUseableProperties() { foreach (var pkProperty in PropertyUnity.GetPrimaryProperties(entityType)) { if (pkProperty != metaTree.InnerSign) { yield return(pkProperty); } } yield return(metaTree.InnerSign); if (metaTree.Name != null) { yield return(metaTree.Name); } if (metaTree.FullName != null) { yield return(metaTree.FullName); } if (metaTree.Order != null) { yield return(metaTree.Order); } if (metaTree.Level != null) { yield return(metaTree.Level); } }
/// <summary> /// 将一个实体序列转换为 <see cref="DataTable"/> 对象。 /// </summary> /// <typeparam name="TEntity">实体的类型。</typeparam> /// <param name="source">一个包含实体对象的序列。</param> /// <param name="tableName">指定 <see cref="DataTable"/> 的表名,如果忽略该参数,则根据实体的类型进行获取。</param> /// <param name="changedOnly">仅仅转换状态改变的实体。</param> /// <returns></returns> public static DataTable ToDataTable <TEntity>(this IEnumerable <TEntity> source, string tableName = null, bool changedOnly = false) where TEntity : IEntity { if (source.IsNullOrEmpty()) { return(null); } var entityType = source.FirstOrDefault().GetType(); var properties = new List <IProperty>(PropertyUnity.GetPersistentProperties(entityType)); if (string.IsNullOrEmpty(tableName)) { var metadata = EntityMetadataUnity.GetEntityMetadata(entityType); tableName = metadata.TableName; } var table = new DataTable(tableName); var keys = CreateTableColumns(table, properties); var extendList = source.As <IEntitySetInternalExtension>(); if (extendList != null && changedOnly) { FillDataTableRows(table, extendList, properties, keys.Length > 0); } else { FillDataTableRows(table, source, properties, keys.Length > 0); } if (keys.Length > 0) { var con = new UniqueConstraint(keys, true); table.Constraints.Add(con); } return(table); }
string[] IEntity.GetModifiedProperties() { return((from s in valueEntry.GetModifiedProperties() let p = PropertyUnity.GetProperty(entityType, s) where p != null && (!p.Info.IsPrimaryKey || (p.Info.IsPrimaryKey && p.Info.GenerateType == IdentityGenerateType.None)) select s).ToArray()); }
/// <summary> /// 检查实体的关联属性。 /// </summary> /// <param name="entity"></param> private void HandleRelationProperties(IEntity entity) { //判断实体类型有是不是编译的代理类型,如果不是,取非null的属性,否则使用IsModified判断 var isNotCompiled = entity.GetType().IsNotCompiled(); var properties = PropertyUnity.GetRelatedProperties(entity.EntityType).Where(m => isNotCompiled ? !PropertyValue.IsEmpty(entity.GetValue(m)) : entity.IsModified(m.Name)); HandleRelationProperties(entity, properties); }
/// <summary> /// 检查实体的关联属性。 /// </summary> /// <param name="entity"></param> private async Task HandleRelationPropertiesAsync(IEntity entity, CancellationToken cancellationToken = default) { //判断实体类型有是不是编译的代理类型,如果不是,取非null的属性,否则使用IsModified判断 var isNotCompiled = entity.GetType().IsNotCompiled(); var properties = PropertyUnity.GetRelatedProperties(entity.EntityType).Where(m => isNotCompiled ? !PropertyValue.IsEmpty(entity.GetValue(m)) : entity.IsModified(m.Name)); await HandleRelationPropertiesAsync(entity, properties, cancellationToken); }
internal static IEnumerable <PropertyFieldMapping> GetDbMapping(Type entityType) { return(from s in PropertyUnity.GetLoadedProperties(entityType, true) let name = string.IsNullOrEmpty(s.Info.FieldName) ? s.Name : s.Info.FieldName let dbType = s.Info.DataType == null ? DbType.String : s.Info.DataType.Value select new PropertyFieldMapping(s.Name, s.Info.FieldName, s.Type, dbType) { ValueFunc = e => PropertyValueHelper.GetValueSafely(((IEntity)e).InternalGetValue(s)) }); }
/// <summary> /// 判断指定名称的属性的值是否已经创建。 /// </summary> /// <param name="propertyName">属性名称</param> /// <returns></returns> internal bool IsValueCreated(string propertyName) { var property = PropertyUnity.GetProperty(entityType, propertyName); if (property is RelationProperty) { return(status.Contains(propertyName)); } return(true); }
/// <summary> /// 获取指定属性的值。 /// </summary> /// <param name="propertyName">实体属性。</param> /// <returns></returns> PropertyValue IEntity.GetValue(string propertyName) { var property = PropertyUnity.GetProperty(_entityType, propertyName); if (property == null) { throw new PropertyNotFoundException(propertyName); } return(GetValue(property)); }
internal static IEnumerable <PropertyFieldMapping> GetDbMapping(Type entityType) { return(from s in PropertyUnity.GetLoadedProperties(entityType) where (!s.Info.IsPrimaryKey || (s.Info.IsPrimaryKey && s.Info.GenerateType != IdentityGenerateType.AutoIncrement)) let name = string.IsNullOrEmpty(s.Info.FieldName) ? s.Name : s.Info.FieldName let dbType = s.Info.DataType == null ? DbType.String : s.Info.DataType.Value select new PropertyFieldMapping(s.Name, s.Info.FieldName, s.Type, dbType) { ValueFunc = e => PropertyValue.GetValueSafely(((IEntity)e).GetValue(s)) }); }
private void InitMapping(string[] fields) { mapping = from s in PropertyUnity.GetProperties(typeof(T)) let index = IndexOf(fields, s) where index != -1 && s is ILoadedProperty select new PropertyMapping { Property = s, Index = index }; alwaysProperties = PropertyUnity.GetRelatedProperties(typeof(T), LoadBehavior.Always); }
/// <summary> /// 设置指定属性的值。 /// </summary> /// <param name="propertyName">实体属性。</param> /// <param name="value">要设置的值。</param> void IEntity.SetValue(string propertyName, PropertyValue value) { var property = PropertyUnity.GetProperty(_entityType, propertyName); if (property == null) { throw new PropertyNotFoundException(propertyName); } SetValue(property, value); }
/// <summary> /// 为实体对象应用默认值。 /// </summary> /// <param name="entity"></param> /// <returns></returns> public static IEntity ApplyDefaultValue(this IEntity entity) { foreach (var property in PropertyUnity.GetPersistentProperties(entity.EntityType)) { if (!PropertyValue.IsEmpty(property.Info.DefaultValue)) { entity.InitializeValue(property, property.Info.DefaultValue); } } return(entity); }
/// <summary> /// 获取指定属性的值。 /// </summary> /// <param name="instance">要读取的实体实例。</param> /// <param name="propertyName">要读取的属性的名称。</param> /// <returns>指定属性的值。</returns> public override object ReadValue(TEntity instance, string propertyName) { var property = PropertyUnity.GetProperty(typeof(TEntity), propertyName, true); if (property != null && property is ILoadedProperty) { var value = instance.InternalGetValue(property); return(PropertyValue.IsNullOrEmpty(value) ? null : value.GetStorageValue()); } return(null); }
/// <summary> /// 使用指定的实体的属性集来构造一个 <see cref="DataTable"/>,<see cref="DataTable"/> 里的列与实体属性一一对应。 /// </summary> /// <param name="entityType">实体的类型。</param> /// <returns></returns> private static DataTable Construct(Type entityType) { Guard.ArgumentNull(entityType, "entityType"); var metadata = EntityMetadataUnity.GetEntityMetadata(entityType); var table = new DataTable(metadata.TableName); foreach (var property in PropertyUnity.GetPersistentProperties(entityType)) { table.Columns.Add(property.ToDataColumn()); } return(table); }
/// <summary> /// 设置默认值。 /// </summary> /// <param name="entity"></param> protected virtual void SetDefaultValue(TEntity entity) { var isNotCompiled = entity.EntityType.IsNotCompiled(); foreach (var property in PropertyUnity.GetPersistentProperties(EntityType)) { var isModify = isNotCompiled ? !PropertyValue.IsEmpty(entity.GetValue(property)) : entity.IsModified(property.Name); if (!isModify && !PropertyValue.IsEmpty(property.Info.DefaultValue)) { entity.SetValue(property, property.Info.DefaultValue.TryAllotValue(property.Type, property.Info.DefaultValueFormatter)); } } }
private bool InternalCreate(IEntity entity) { var parameters = new ParameterCollection(); var context = CreateContext(parameters); var sql = EntityPersistentQueryBuilder.BuidCreateQuery(context, entity); if (!sql.IsNullOrEmpty()) { var rootType = entity.EntityType.GetRootType(); //找出自增长序列的属性 var incProperty = PropertyUnity.GetPersistentProperties(rootType).FirstOrDefault(s => s.Info.GenerateType == IdentityGenerateType.AutoIncrement); if (incProperty != null) { if (!string.IsNullOrEmpty(context.Syntax.IdentitySelect)) { //获得当前插入的自增长序列值 var identitySelect = context.Syntax.IdentitySelect; if (!identitySelect.StartsWith(";")) { identitySelect = ";" + identitySelect; } var incValue = PropertyValueHelper.NewValue(context.Database.ExecuteScalar <int>(sql + identitySelect, context.Parameters)); entity.InternalSetValue(incProperty, incValue); return(!incValue.IsNullOrEmpty()); } else { //使用生成器生成值 var generator = context.Database.Provider.GetService <IGeneratorProvider>(); if (generator != null) { var metadata = EntityMetadataUnity.GetEntityMetadata(entityType); var inc = generator.GenerateValue(context.Database, context.Environment == null ? metadata.TableName : context.Environment.GetVariableTableName(metadata), incProperty.Info.FieldName); entity.InternalSetValue(incProperty, inc); parameters.Clear(); sql = EntityPersistentQueryBuilder.BuidCreateQuery(context, entity); return(context.Database.ExecuteNonQuery(sql, context.Parameters) > 0); } } } return(database.ExecuteNonQuery(sql, parameters) > 0); } return(false); }
protected override Expression VisitMember(MemberExpression memberExp) { var ex = Visit(memberExp.Expression); var member = memberExp.Member; var p = PropertyUnity.GetProperty(member.DeclaringType, member.Name); if (p != null && p is IPropertyLazy) { members.Add(member); } return(memberExp); }
/// <summary> /// 获取实体指定属性修改前的值。 /// </summary> /// <param name="entity">当前的实体对象。</param> /// <param name="propertyName">属性名称。</param> /// <returns></returns> public static PropertyValue GetOldValue(this IEntity entity, string propertyName) { if (entity.EntityState == EntityState.Attached || entity.EntityState == EntityState.Modified) { var property = PropertyUnity.GetProperty(entity.EntityType, propertyName); if (property != null) { return(entity.GetOldValue(property)); } } return(PropertyValue.Empty); }
/// <summary> /// 获取实体指定属性修改前的值。 /// </summary> /// <param name="entity">当前的实体对象。</param> /// <param name="propertyName">属性名称。</param> /// <returns></returns> public static PropertyValue GetOldValue(this IEntity entity, string propertyName) { if (entity.EntityState == EntityState.Attached || entity.EntityState == EntityState.Modified) { var property = PropertyUnity.GetProperty(entity.EntityType, propertyName); var ext = entity as IEntityStatefulExtension; if (property != null && ext != null) { return(ext.GetOldValue(property)); } } return(null); }
bool IDeserializeProcessor.SetValue(string name, object value) { if (EntityDeserializeProcessorScope.Current == null) { return(false); } var property = PropertyUnity.GetProperty(_entityType, name); if (property != null) { InitializeValue(property, PropertyValue.NewValue(value, property.Type)); return(true); } return(false); }
/// <summary> /// 异步的,根据实体的状态,插入或更新实体对象。 /// </summary> /// <param name="entity">要保存的实体对象。</param> /// <param name="cancellationToken">取消操作的通知。</param> /// <returns>影响的实体数。</returns> public async Task <int> InsertOrUpdateAsync(TEntity entity, CancellationToken cancellationToken = default) { Guard.ArgumentNull(entity, nameof(entity)); var properties = PropertyUnity.GetPrimaryProperties(typeof(TEntity)); var isNew = entity.EntityState == EntityState.Attached; if (isNew && properties.Any(s => !PropertyValue.IsEmptyOrDefault(entity.GetValue(s)))) { var parExp = Expression.Parameter(typeof(TEntity), "s"); var equalExp = properties.Select(s => Expression.Equal(Expression.MakeMemberAccess(parExp, s.Info.ReflectionInfo), Expression.Constant(entity.GetValue(s)))).Aggregate(Expression.And); var lambdaExp = Expression.Lambda <Func <TEntity, bool> >(equalExp, parExp); isNew = !this.Any(lambdaExp); } return(await(isNew ? InsertAsync(entity, cancellationToken) : UpdateAsync(entity, cancellationToken))); }
/// <summary> /// 将一个实体对象添加到 <see cref="DataTable"/> 对象里,该 <see cref="DataTable"/> 的结构必须保证与实体结构相符。 /// </summary> /// <param name="entity">当前的实体对象。</param> /// <param name="table">一个使用 <see cref="Construct"/> 构造的 <see cref="DataTable"/>。</param> public static void Putin(this IEntity entity, DataTable table) { Guard.ArgumentNull(entity, "entity"); Guard.ArgumentNull(table, "table"); var properties = PropertyUnity.GetPersistentProperties(entity.EntityType) .Where(s => table.Columns.Contains(s.Name)).ToList(); var count = properties.Count; var data = new object[count]; for (var i = 0; i < count; i++) { var value = entity.InternalGetValue(properties[i]); data[i] = PropertyValue.IsNullOrEmpty(value) ? DBNull.Value : value.GetStorageValue(); } table.Rows.Add(data); }
/// <summary> /// 通过主键值使对象正常化。 /// </summary> /// <param name="entity"></param> /// <param name="keyValues">主键值数组。</param> /// <returns></returns> public static T Normalize <T>(this T entity, params PropertyValue[] keyValues) where T : IEntity { var primaryKeys = PropertyUnity.GetPrimaryProperties(entity.EntityType).ToArray(); if (primaryKeys.Length != 0 && keyValues == null || primaryKeys.Length != keyValues.Length) { throw new Exception(SR.GetString(SRKind.DisaccordArgument, primaryKeys.Length, keyValues.Length)); } for (var i = 0; i < primaryKeys.Length; i++) { entity.InitializeValue(primaryKeys[i], keyValues[i]); } entity.SetState(EntityState.Modified); return(entity); }
/// <summary> /// 使用主键和外键对应构造一对多的关系。 /// </summary> /// <param name="relProperty"></param> /// <param name="thisType"></param> /// <param name="otherType"></param> /// <returns></returns> private static RelationshipMetadata MakeRelationshipMetadata(RelationProperty relProperty, Type thisType, Type otherType) { //是否使用了 ForeignKeyAttribute 来指定对应的外键 var assignAttr = relProperty.Info.ReflectionInfo.GetCustomAttributes <RelationshipAssignAttribute>().FirstOrDefault(); if (assignAttr != null) { var fkPro = PropertyUnity.GetProperty(otherType, assignAttr.ForeignKey); var pkPro = PropertyUnity.GetProperty(thisType, assignAttr.PrimaryKey); if (fkPro != null && pkPro != null) { var key = new RelationshipKey { ThisKey = pkPro.Name, ThisProperty = pkPro, OtherKey = fkPro.Name, OtherProperty = fkPro }; return(new RelationshipMetadata(thisType, otherType, RelationshipStyle.One2Many, RelationshipSource.AutomaticallyAssign, new[] { key })); } } //使用名称相同的主键进行匹配 var pks = PropertyUnity.GetPrimaryProperties(thisType).ToList(); if (pks.Count > 0) { var fks = pks.Select(s => PropertyUnity.GetProperty(otherType, s.Name)).ToList(); var keys = new RelationshipKey[pks.Count]; for (var i = 0; i < pks.Count; i++) { if (fks[i] == null) { throw new Exception(); } keys[i] = new RelationshipKey { ThisKey = pks[i].Name, ThisProperty = pks[i], OtherKey = fks[i].Name, OtherProperty = fks[i] }; } return(new RelationshipMetadata(thisType, otherType, RelationshipStyle.One2Many, RelationshipSource.AutomaticallyAssign, keys)); } return(null); }
private void AttachRequiredProperties(TEntity entity) { var pkValues = new List <PropertyValue>(); foreach (var pkProperty in PropertyUnity.GetPrimaryProperties(typeof(TEntity))) { pkValues.Add(entity.GetValue(pkProperty)); } var oldEntity = repository.Get(pkValues.ToArray()); if (oldEntity == null) { return; } if (metaTree.InnerSign != null && !entity.IsModified(metaTree.InnerSign.Name)) { entity.InitializeValue(metaTree.InnerSign, oldEntity.GetValue(metaTree.InnerSign)); } if (metaTree.Name != null && !entity.IsModified(metaTree.Name.Name)) { entity.InitializeValue(metaTree.Name, oldEntity.GetValue(metaTree.Name)); } if (metaTree.FullName != null && !entity.IsModified(metaTree.FullName.Name)) { entity.InitializeValue(metaTree.FullName, oldEntity.GetValue(metaTree.FullName)); } if (metaTree.Order != null && !entity.IsModified(metaTree.Order.Name)) { entity.InitializeValue(metaTree.Order, oldEntity.GetValue(metaTree.Order)); } if (metaTree.Level != null && !entity.IsModified(metaTree.Level.Name)) { entity.InitializeValue(metaTree.Level, oldEntity.GetValue(metaTree.Level)); } }
/// <summary> /// 获取可以组织到查询里的属性。 /// </summary> /// <param name="metadata"></param> /// <param name="source"></param> /// <returns></returns> internal static Expression AddUseableSelectExpression <T>(EntityTreeMetadata metadata, Expression source) { var parExp = Expression.Parameter(typeof(T), "s"); var members = new List <MemberBinding>(); foreach (var pkProperty in PropertyUnity.GetPrimaryProperties(typeof(T))) { if (pkProperty != metadata.InnerSign) { members.Add(Expression.Bind(pkProperty.Info.ReflectionInfo, Expression.MakeMemberAccess(parExp, pkProperty.Info.ReflectionInfo))); } } members.Add(Expression.Bind(metadata.InnerSign.Info.ReflectionInfo, Expression.MakeMemberAccess(parExp, metadata.InnerSign.Info.ReflectionInfo))); if (metadata.Name != null) { members.Add(Expression.Bind(metadata.Name.Info.ReflectionInfo, Expression.MakeMemberAccess(parExp, metadata.Name.Info.ReflectionInfo))); } if (metadata.FullName != null) { members.Add(Expression.Bind(metadata.FullName.Info.ReflectionInfo, Expression.MakeMemberAccess(parExp, metadata.FullName.Info.ReflectionInfo))); } if (metadata.Order != null) { members.Add(Expression.Bind(metadata.Order.Info.ReflectionInfo, Expression.MakeMemberAccess(parExp, metadata.Order.Info.ReflectionInfo))); } if (metadata.Level != null) { members.Add(Expression.Bind(metadata.Level.Info.ReflectionInfo, Expression.MakeMemberAccess(parExp, metadata.Level.Info.ReflectionInfo))); } var mbrInit = Expression.MemberInit(Expression.New(typeof(T)), members); var lambdaExp = Expression.Lambda(mbrInit, parExp); return(Expression.Call(typeof(Queryable), "Select", new[] { typeof(T), typeof(T) }, new[] { source, lambdaExp })); }