Exemplo n.º 1
0
 private static void ThrowRefPropertyChangingConflict(IRefIdProperty property)
 {
     throw new InvalidOperationException(
               string.Format(@"{0} 属性的变更前事件与引用实体属性 {1} 的变更前事件设置的值冲突!",
                             property.Name, property.RefEntityProperty.Name)
               );
 }
Exemplo n.º 2
0
        /// <summary>
        /// 根据冗余路径从当前对象开始搜索,获取真实的属性值。
        /// </summary>
        /// <param name="path"></param>
        /// <param name="from">
        /// 本对象在路径中拥有的引用属性。
        /// 在 D->C->B->A.Name 场景中,当前对象(this)可能是 C,那么 from 就是 C.BRefProperty.
        /// 如果没有指定此属性,则表示从第一个开始。
        /// </param>
        /// <returns></returns>
        internal object GetRedundancyValue(RedundantPath path, IRefIdProperty from = null)
        {
            Entity refEntity = this;

            foreach (var refP in path.RefPathes)
            {
                if (from != null && refP.Property != from)
                {
                    continue;
                }

                refEntity = refEntity.GetRefEntity((refP.Property as IRefProperty).RefEntityProperty);
                if (refEntity == null)
                {
                    break;
                }
            }

            object value = null;

            if (refEntity != this && refEntity != null)
            {
                value = refEntity.GetProperty(path.ValueProperty.Property);
            }

            return(value);
        }
Exemplo n.º 3
0
        /// <summary>
        /// 设置指定引用 id 属性对应的 id 的可空类型值。
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value">本方法为兼容值类型而使用。不论外键是否为值类型,都可以传入 null。</param>
        /// <param name="source"></param>
        /// <returns></returns>
        public object SetRefNullableId(IRefIdProperty property, object value, ManagedPropertyChangedSource source = ManagedPropertyChangedSource.FromProperty)
        {
            if (value == null)
            {
                value = GetEmptyIdForRefIdProperty(property);
            }
            var finalValue = this.SetRefId(property, value, source);

            return(property.KeyProvider.ToNullableValue(finalValue));
        }
Exemplo n.º 4
0
        public RefTableProperty(IRefIdProperty refProperty, Type propertyOwner)
        {
            this.PropertyOwner = propertyOwner;
            this.RefProperty = refProperty;
            var mainTable = RdbTableFinder.TableFor(propertyOwner);
            var refTable = RdbTableFinder.TableFor(refProperty.RefEntityType);

            this.OwnerTable = mainTable;
            this.RefTable = refTable;
            this.FKName = mainTable.Translate(refProperty);
        }
Exemplo n.º 5
0
        public RefTableProperty(IRefIdProperty refProperty, Type propertyOwner)
        {
            this.PropertyOwner = propertyOwner;
            this.RefProperty   = refProperty;
            var mainTable = RdbTableFinder.TableFor(propertyOwner);
            var refTable  = RdbTableFinder.TableFor(refProperty.RefEntityType);

            this.OwnerTable = mainTable;
            this.RefTable   = refTable;
            this.FKName     = mainTable.Translate(refProperty);
        }
Exemplo n.º 6
0
        /// <summary>
        /// 根据冗余路径从当前对象开始搜索,获取真实的属性值。
        /// </summary>
        /// <param name="path"></param>
        /// <param name="from">
        /// 本对象在路径中拥有的引用属性。
        /// 在 D->C->B->A.Name 场景中,当前对象(this)可能是 C,那么 from 就是 C.BRefProperty.
        /// 如果没有指定此属性,则表示从第一个开始。
        /// </param>
        /// <returns></returns>
        internal object GetRedundancyValue(RedundantPath path, IRefIdProperty from = null)
        {
            Entity refEntity = this;
            foreach (var refP in path.RefPathes)
            {
                if (from != null && refP.Property != from) continue;

                refEntity = refEntity.GetRefEntity((refP.Property as IRefProperty).RefEntityProperty);
                if (refEntity == null) break;
            }

            object value = null;
            if (refEntity != this && refEntity != null) value = refEntity.GetProperty(path.ValueProperty.Property);

            return value;
        }
Exemplo n.º 7
0
 private static bool HasRefId(IRefIdProperty refIdProperty, object id)
 {
     return(refIdProperty.KeyProvider.IsAvailable(id));
 }
Exemplo n.º 8
0
 private static object GetEmptyIdForRefIdProperty(IRefIdProperty refIdProperty)
 {
     return(refIdProperty.KeyProvider.GetEmptyIdForRefIdProperty());
 }
Exemplo n.º 9
0
        /// <summary>
        /// 设置指定引用 id 属性对应的 id 的值。
        ///
        /// 在引用 id 变化时,会同步相应的引用实体属性。
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value">外键如果是值类型,则不能传入 null。</param>
        /// <param name="source"></param>
        /// <returns></returns>
        public object SetRefId(IRefIdProperty property, object value, ManagedPropertyChangedSource source = ManagedPropertyChangedSource.FromProperty)
        {
            //引用属性的托管属性类型是 object,这里需要强制为指定的主键类型。
            value = TypeHelper.CoerceValue(property.KeyProvider.KeyType, value);

            var id = this.GetRefId(property);

            //设置 id 完成后的值。
            object finalId = id;

            //确实需要改变 Id 时,才进行以下逻辑。
            if (!object.Equals(id, value))
            {
                var entityProperty = property.RefEntityProperty;

                //在设置 RefId 前先清空实体值,这样在回调 RefId 的外部 Changed 事件处理函数时,
                //外部看到的 RefEntity 也已经改变了,外部可以获得一致的 Entity 和 Id 值。
                var entity = base.GetProperty(entityProperty) as Entity;
                if (entity != null && !object.Equals(entity.Id, value))
                {
                    base.ResetProperty(entityProperty);
                }
                try
                {
                    //此时发生 OnIdChanged 事件。
                    finalId = base.SetProperty(property, value, source);
                }
                finally
                {
                    //还原实体的值。
                    if (entity != null)
                    {
                        base.LoadProperty(entityProperty, entity);
                    }
                }

                //如果二者相等,表示 Id 成功设置,没有被 cancel。
                if (object.Equals(finalId, value))
                {
                    //如果之前的实体已经存在值,则需要设置为 null,并引发外部事件。
                    if (entity != null)
                    {
                        //重新设置 Entity 的值,此时发生 OnEntityChanged 事件。
                        var finalEntity = base.SetProperty(entityProperty, null, source) as Entity;

                        //如果外部事件取消了属性的设置,那么实际使用的实体将不会为 null,
                        if (finalEntity != null)
                        {
                            //此时,需要重设 Id 的值。
                            finalId = base.SetProperty(property, finalEntity.Id, source);
                            if (!object.Equals(finalId, finalEntity.Id))
                            {
                                ThrowRefPropertyChangingConflict(property);
                            }
                        }
                    }
                }
            }

            return(finalId);
        }
Exemplo n.º 10
0
        /// <summary>
        /// 冗余路径中非首位的引用属的值作为值属性进行冗余,那么同样要进行值属性更新操作。
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="path">The path.</param>
        /// <param name="refChanged">该引用属性值变化了</param>
        private void UpdateRedundancyByRefValue(Entity entity, RedundantPath path, IRefIdProperty refChanged)
        {
            var newValue = entity.GetProperty(refChanged);

            this.UpdateRedundancy(entity, path.Redundancy, newValue, path.RefPathes, entity.Id);
        }
Exemplo n.º 11
0
 /// <summary>
 /// 获取指定引用 id 属性对应的 id 的可空类型返回值。
 /// </summary>
 /// <param name="property"></param>
 /// <returns></returns>
 public new int?GetRefNullableId(IRefIdProperty property)
 {
     return((int?)base.GetRefNullableId(property));
 }
Exemplo n.º 12
0
        /// <summary>
        /// 获取指定引用 id 属性对应的 id 的可空类型返回值。
        /// </summary>
        /// <param name="property"></param>
        /// <returns>本方法为兼容值类型而使用。不论 Id 是值类型、还是引用类型,都可能返回 null。</returns>
        public object GetRefNullableId(IRefIdProperty property)
        {
            var value = this.GetProperty(property);

            return(property.KeyProvider.ToNullableValue(value));
        }
Exemplo n.º 13
0
Arquivo: P.cs Projeto: zhuwansu/Rafy
        /// <summary>
        /// 扩展一个引用实体属性。
        /// </summary>
        /// <typeparam name="TRefEntity"></typeparam>
        /// <param name="propertyName">实体属性的名称。</param>
        /// <param name="declareType">声明此属性的类型。</param>
        /// <param name="refIdProperty">对应的引用 Id 属性,将为其建立关联。</param>
        /// <returns></returns>
        public static RefEntityProperty <TRefEntity> RegisterRefExtension <TRefEntity>(string propertyName, Type declareType, IRefIdProperty refIdProperty)
            where TRefEntity : Entity
        {
            if (refIdProperty == null)
            {
                throw new ArgumentNullException("refIdProperty", "必须指定引用 Id 属性,将为其建立关联。");
            }

            var defaultMeta = new PropertyMetadata <Entity>();

            var property = new RefEntityProperty <TRefEntity>(typeof(TEntity), declareType, propertyName, defaultMeta)
            {
                RefIdProperty = refIdProperty
            };

            //默认只从服务端序列化到客户端。
            defaultMeta.Serializable = RafyEnvironment.IsOnServer();

            ManagedPropertyRepository.Instance.RegisterProperty(property);

            return(property);
        }
Exemplo n.º 14
0
        /// <summary>
        /// 声明一个引用实体属性。
        /// </summary>
        /// <typeparam name="TRefEntity"></typeparam>
        /// <param name="propertyExp">指向引用实体属性的表达式。</param>
        /// <param name="refIdProperty">对应的引用 Id 属性,将为其建立关联。</param>
        /// <returns></returns>
        public static RefEntityProperty <TRefEntity> RegisterRef <TRefEntity>(Expression <Func <TEntity, TRefEntity> > propertyExp, IRefIdProperty refIdProperty)
            where TRefEntity : Entity
        {
            if (refIdProperty == null)
            {
                throw new ArgumentNullException("refIdProperty", "必须指定引用 Id 属性,将为其建立关联。");
            }

            var defaultMeta = new PropertyMetadata <Entity>();

            defaultMeta.AffectStatus = false;

            var property = new RefEntityProperty <TRefEntity>(typeof(TEntity), GetPropertyName(propertyExp), defaultMeta)
            {
                RefIdProperty = refIdProperty
            };

            //默认只从服务端序列化到客户端。
            defaultMeta.Serializable = RafyEnvironment.IsOnServer();

            ManagedPropertyRepository.Instance.RegisterProperty(property);

            return(property);
        }
Exemplo n.º 15
0
        /// <summary>
        /// 冗余路径中非首位的引用属性变化时引发的冗余值更新操作。
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="path">The path.</param>
        /// <param name="refChanged">该引用属性值变化了</param>
        private void UpdateRedundancyByIntermidateRef(Entity entity, RedundantPath path, IRefIdProperty refChanged)
        {
            var newValue = entity.GetRedundancyValue(path, refChanged);

            //只要从开始到 refChanged 前一个
            var refPathes = new List <ConcreteProperty>(5);

            foreach (var refProperty in path.RefPathes)
            {
                if (refProperty.Property == refChanged)
                {
                    break;
                }
                refPathes.Add(refProperty);
            }

            this.UpdateRedundancy(entity, path.Redundancy, newValue, refPathes, entity.Id);
        }
Exemplo n.º 16
0
        /// <summary>
        /// 冗余路径中非首位的引用属的值作为值属性进行冗余,那么同样要进行值属性更新操作。
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="path">The path.</param>
        /// <param name="refChanged">该引用属性值变化了</param>
        private void UpdateRedundancyByRefValue(Entity entity, RedundantPath path, IRefIdProperty refChanged)
        {
            var newValue = entity.GetProperty(refChanged);

            this.UpdateRedundancy(entity, path.Redundancy, newValue, path.RefPathes, entity.Id);
        }
Exemplo n.º 17
0
 /// <summary>
 /// 获取指定引用 id 属性对应的 id 的返回值。
 /// </summary>
 /// <param name="property"></param>
 /// <returns>如果 Id 是值类型,则这个函数的返回值不会是 null;如果是引用类型,则可能返回 null。</returns>
 public object GetRefId(IRefIdProperty property)
 {
     return(this.GetProperty(property));
 }
Exemplo n.º 18
0
 /// <summary>
 /// 获取指定引用 id 属性对应的 id 的返回值。
 /// </summary>
 /// <param name="property"></param>
 /// <returns></returns>
 public new int GetRefId(IRefIdProperty property)
 {
     return((int)base.GetRefId(property));
 }
Exemplo n.º 19
0
        /// <summary>
        /// 冗余路径中非首位的引用属性变化时引发的冗余值更新操作。
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="path">The path.</param>
        /// <param name="refChanged">该引用属性值变化了</param>
        private void UpdateRedundancyByIntermidateRef(Entity entity, RedundantPath path, IRefIdProperty refChanged)
        {
            var newValue = entity.GetRedundancyValue(path, refChanged);

            //只要从开始到 refChanged 前一个
            var refPathes = new List<ConcreteProperty>(5);
            foreach (var refProperty in path.RefPathes)
            {
                if (refProperty.Property == refChanged) break;
                refPathes.Add(refProperty);
            }

            this.UpdateRedundancy(entity, path.Redundancy, newValue, refPathes, entity.Id);
        }