EF 4.1中只读属性 [英] Readonly properties in EF 4.1

本文介绍了EF 4.1中只读属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我需要具有EF readonly属性(乐观更新)时,我遇到了这种情况(您不要从数据库加载您的域对象的当前状态,以检查哪些属性真正改变,您只需设置对象作为修改并将其更新为数据库,您可以避免冗余选择和合并操作)

I've faced with situation when I need to have EF readonly property in case of 'optimistic update'(you do not load current state of your domain object from database to check what properties are really changed. You just set your object as Modified and update it to database. You avoid redundant select and merge operations in this case).

您不能写这样的东西: DataContext.Entry(entity).Property(propertyName).IsModified = false; ,因为不支持设置'false'值,而是会出现异常。 (在EF 4.1中)

You can't write something like this : DataContext.Entry(entity).Property(propertyName).IsModified = false;, because setting of 'false' value is not supported and you will get an exception. (in EF 4.1)

我已经创建了一个简单的结构,用于在存储库中注册只读属性。
所以,你可以轻松地修改只是非公开的属性。

I've created a simple structure for registering readonly properties in repository. So, you can easy Modify just nonreadonly properties.

你觉得怎么样?

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;
            }
        }


推荐答案

将工作,但我不喜欢直接在存储库中注册修改的属性。您可以忘记注册的属性,代码将意外不会保存一些更改 - 这将是在复杂场景中重用存储库时难以找到的错误。每当您在存储库中调用更新时,我都喜欢显式定义更新的属性。我也不喜欢反思在代码中。除非您修改代码以获取有关每个实体的反映数据,只需一次整个应用程序就会出错。

This would work but I don't like the need to register modified properties directly in repository. You can forget about registered properties and code will accidentaly not save some changes - that will be bug which will be hard to find when reusing repository in complex scenarios. I like explicit definition of updated properties each time you call something like Update on your repository. Also I don't like reflection in the code. Unless you modify your code to get reflected data about each entity only once for whole application you are doing it wrong.

我写了 EFv4的答案,但可以轻松修改为EFv4.1:

I wrote the answer for EFv4 but it can be easily modified to 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);

这篇关于EF 4.1中只读属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆