Example #1
0
        /// <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);
        }
Example #2
0
        /// <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));
        }
Example #3
0
        /// <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);
            }
        }
Example #4
0
        /// <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);
        }
Example #5
0
        /// <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());
        }
Example #6
0
        /// <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)));
        }
Example #7
0
        /// <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);
        }
Example #8
0
        /// <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));
            }
        }
Example #10
0
        /// <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 }));
        }
Example #11
0
        /// <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())));
        }
Example #12
0
        /// <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());
        }