【问题标题】:Readonly properties in EF 4.1EF 4.1 中的只读属性
【发布时间】:2011-04-21 19:53:29
【问题描述】:

在“乐观更新”的情况下,我需要拥有 EF 只读属性(您不会从数据库加载域对象的当前状态来检查哪些属性真正更改了。您只需设置对象as 已修改并将其更新到数据库。在这种情况下,您可以避免多余的选择和合并操作)。

你不能写这样的东西:DataContext.Entry(entity).Property(propertyName).IsModified = false;,因为不支持'false'值的设置,你会得到一个异常。 (在 EF 4.1 中)

我创建了一个简单的结构,用于在存储库中注册只读属性。 因此,您可以轻松修改非只读属性。

您对此有何看法?

public abstract class RepositoryBase<T> where T : class
{   
 private const string MethodReferenceErrorFormat = "Expression '{0}' refers to a method, not a property.";
 private const string FieldReferenceErrorFormat = "Expression '{0}' refers to a field, not a property.";

 protected IList<PropertyInfo> _readOnlyProperties;
        /// <summary>
        /// This method is used to register readonly property for Entity.
        /// </summary>
        /// <param name="propertyLambda">Entity property as LambdaExpression</param>
        protected void RegisterReadOnlyProperty<TProperty>(Expression<Func<T, TProperty>> propertyLambda)
        {
            Guard.ArgumentNotNull(propertyLambda, "propertyLambda");

            var propertyMember = propertyLambda.Body as MemberExpression;
            if (propertyMember == null)
            {
                var exceptionMessage = string.Format(MethodReferenceErrorFormat, propertyLambda);
                throw new ArgumentException(exceptionMessage);
            }

            var propertyInfo = propertyMember.Member as PropertyInfo;
            if (propertyInfo == null)
            {
                var exceptionMessage = string.Format(FieldReferenceErrorFormat, propertyLambda);
                throw new ArgumentException(exceptionMessage);
            }

            _readOnlyProperties.Add(propertyInfo);
        }

         /// <summary>
         /// This method is used to attach domain object to DbContext and mark it as modified to save changes.
         /// </summary>
         /// <param name="entity">Detached entity</param>
        public void SetModified(T entity)
        {
            Guard.ArgumentNotNull(entity, "entity");

            //Mark whole entity as Modified, when collection of readonly properties is empty.
            if(_readOnlyProperties.Count == 0)
            {
                DataContext.Entry(entity).State = EntityState.Modified;
                return;
            }

             //Attach entity to DbContext.
             _dbSet.Attach(entity);

            //Mark all properties except readonly as Modified.
            var allProperties = entity.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var propertiesForUpdate = allProperties.Except(_readOnlyProperties);
            foreach (var propertyInfo in propertiesForUpdate)
            {
                DataContext.Entry(entity).Property(propertyInfo.Name).IsModified = true;
            }
        }

【问题讨论】:

    标签: entity-framework entity-framework-4 repository-pattern readonly entity-framework-4.1


    【解决方案1】:

    这可行,但我不喜欢直接在存储库中注册修改后的属性。您可能会忘记已注册的属性,并且代码会意外地不保存一些更改 - 这将是在复杂场景中重用存储库时很难发现的错误。每次您在存储库上调用诸如 Update 之类的东西时,我都喜欢明确定义更新的属性。我也不喜欢代码中的反射。除非您修改代码以在整个应用程序中仅获取一次有关每个实体的反映数据,否则您做错了。

    我写了answer for EFv4,但可以轻松修改为EFv4.1:

    public void Update(T entity, params Expression<Func<T, object>>[] properties)
    {
        _dbSet.Attach(entity);
        DbEntityEntry<T> entry = _context.Entry(entity);
        foreach (var selector in properties)
        {
            entry.Property(selector).IsModified = true;
        }
    }
    

    你会这样称呼它:

    repo.Update(entity, e => e.Name, e => e.Description);
    

    【讨论】:

    • 当我使用它时,它给了我以下错误,无法将 Lambda 表达式转换为类型 'Expression> []' 因为它不是委托类型
    • 喜欢它——超级简单。也适用于那些想知道的 EF6。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    相关资源
    最近更新 更多