/// <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> public int InsertOrUpdate(TEntity entity) { 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); } if (options.NotifyEvents) { if (isNew) { return(EntityPersistentSubscribeManager.OnCreate(entity, () => repositoryProxy.Insert(entity))); } else { return(EntityPersistentSubscribeManager.OnUpdate(entity, () => repositoryProxy.Update(entity))); } } return(isNew ? repositoryProxy.Insert(entity) : repositoryProxy.Update(entity)); }
/// <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> /// 通过主键值使对象正常化。 /// </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="primaryValues">主键的值。数组的长度必须与实体所定义的主键相匹配。</param> /// <exception cref="ArgumentNullException"><paramref name="primaryValues"/> 参数为 null。</exception> /// <returns>一个实体对象。</returns> public virtual TEntity First(params object[] primaryValues) { Guard.ArgumentNull(primaryValues, "primaryValues"); var pkProperties = PropertyUnity.GetPrimaryProperties(GetEntityType()).ToList(); var realLength = primaryValues == null ? 0 : primaryValues.Length; if (realLength != pkProperties.Count) { throw new EntityPersistentException(SR.GetString(SRKind.DisaccordArgument, pkProperties.Count, realLength), null); } var parExp = Expression.Parameter(GetEntityType(), "s"); Expression binExp = null; var i = 0; foreach (var property in pkProperties) { var proExp = Expression.Property(parExp, property.Info.ReflectionInfo); var rightExp = proExp.Equal(Expression.Constant(primaryValues[i].ToType(property.Type))); binExp = binExp == null ? rightExp : Expression.And(binExp, rightExp); i++; } var lambda = Expression.Lambda <Func <TEntity, bool> >(binExp, parExp); return(Query(lambda).FirstOrDefault()); }
/// <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> /// 通过主键值使对象正常化。 /// </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 })); }
/// <summary> /// 返回当前对象的哈希值。 /// </summary> /// <returns></returns> public override int GetHashCode() { var pkProperties = PropertyUnity.GetPrimaryProperties(entityType); return(pkProperties.Select(GetValue).Aggregate(0, (current, value) => current ^ (value == null ? 0 : value.GetHashCode()))); }
/// <summary> /// 构造创建表的语句。 /// </summary> /// <param name="entityType">实体类型。</param> /// <param name="syntax">语法服务。</param> /// <param name="tableName">数据表名称。</param> /// <returns></returns> private static string BuildTableScript(Type entityType, ISyntaxProvider syntax, string tableName) { var sb = new StringBuilder(); sb.AppendFormat("create table {0}\n(\n", tableName); //获取实体类型中所有可持久化的属性,不包含引用类型的属性 var properties = PropertyUnity.GetPersistentProperties(entityType).ToArray(); var primaryPeoperties = PropertyUnity.GetPrimaryProperties(entityType).ToArray(); var count = properties.Length; for (var i = 0; i < count; i++) { var property = properties[i]; sb.AppendFormat(" {0}", property.Info.FieldName); //数据类型及长度精度等 sb.AppendFormat(" {0}", syntax.Column((DbType)property.Info.DataType, property.Info.Length, property.Info.Precision, property.Info.Scale)); //自增 if (property.Info.GenerateType == IdentityGenerateType.AutoIncrement && !string.IsNullOrEmpty(syntax.IdentityColumn)) { sb.AppendFormat(" {0}", syntax.IdentityColumn); } //不可空 if (!property.Info.IsNullable) { sb.AppendFormat(" not null"); } //默认值 if (!PropertyValue.IsEmpty(property.Info.DefaultValue)) { if (property.Type == typeof(string)) { sb.AppendFormat(" default '{0}'", property.Info.DefaultValue); } else if (property.Type.IsEnum) { sb.AppendFormat(" default {0}", (int)property.Info.DefaultValue); } else if (property.Type == typeof(bool) || property.Type == typeof(bool?)) { sb.AppendFormat(" default {0}", (bool)property.Info.DefaultValue ? 1 : 0); } else { sb.AppendFormat(" default {0}", property.Info.DefaultValue); } } if (i != count - 1) { sb.Append(","); } sb.AppendLine(); } //主键 if (primaryPeoperties.Length > 0) { sb.Append(","); sb.AppendFormat("constraint PK_{0} primary key (", tableName); for (var i = 0; i < primaryPeoperties.Length; i++) { if (i != 0) { sb.Append(","); } sb.Append(primaryPeoperties[i].Info.FieldName); } sb.Append(")"); } sb.Append(")\n"); return(sb.ToString()); }