实体框架验证与部分更新 [英] Entity Framework validation with partial updates

查看:91
本文介绍了实体框架验证与部分更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用具有DbContext和POCO实体的Entity Framework 5.0。有一个包含3个属性的简单实体:

  public class Record 
{
public int Id {get;组; }
public string标题{get;组; }
public bool IsActive {get;组; }
}

标题字段始终未被修改,UI简单地显示它,而不提供任何输入框进行修改。这就是为什么表单发送到服务器时标题字段设置为 null



这是我如何告诉EF执行实体的部分更新( IsActive 字段):

  public class EFRepository< TEntity> 
{
...
public void PartialUpdate(TEntity entity,params Expression< Func< TEntity,object>> [] propsToUpdate)
{
dbSet.Attach (实体);
var entry = _dbContext.Entry(entity);
foreach(在propsToUpdate中为var prop)
contextEntry.Property(prop).IsModified = true;
}
}

和通话:

  repository.PartialUpdate(updatedRecord,r => r.IsActive); 

调用 SaveChanges 方法, code> DbEntityValidationException ,告诉我,标题是必需的。当我设置 dbContext.Configuration.ValidateOnSaveEnabled = false ,一切都OK。
有没有办法避免在整个上下文中禁用验证,并告诉EF不验证尚未更新的属性?
提前感谢

解决方案

如果您使用部分更新或存根实体(两种方法都非常有效!)不能使用全球EF验证,因为它不尊重您的部分更改 - 它总是验证整个实体。使用默认验证逻辑,您必须通过调用以下方法来关闭它:

  dbContext.Configuration.ValidateOnSaveEnabled = false 

并分别验证每个更新的属性。这应该是有希望的魔法,但我没有尝试,因为我根本不使用EF验证:

  foreach( var prop in propsToUpdate){
var errors = contextEntry.Property(prop).GetValidationErrors();
if(erros.Count == 0){
contextEntry.Property(prop).IsModified = true;
} else {
...
}
}

如果您想要进一步,您可以尝试在您的上下文中覆盖 ValidateEntity ,并以验证整个实体的方式重新实施验证,或仅基于实体和 IsModified 属性状态 - 这将允许您使用EF验证部分更新和存根实体。



EF中的验证是IMHO错误的概念 - 它将逻辑不属于的数据访问层引入附加逻辑。它主要是基于这样的想法:如果您在导航属性上放置了所需的验证规则,则您始终可以使用整个实体,甚至使用整个实体图。一旦你违反了这种方法,你总是会发现硬固定到你的实体的一套固定的验证规则是不够的。



我在很长的积压中有一件事是调查验证如何影响 SaveChanges 操作的速度 - 我以前在EF4(EF4.1之前)基于DataAnnotations拥有自己的验证API,而且它们的验证器类,我很快就停止使用它,因为性能非常差。



使用本机SQL的解决方法与使用存根实体相同或部分更新关闭验证=您的实体仍未验证,但另外您的更改不是同一工作单位的一部分。


I'm using Entity Framework 5.0 with DbContext and POCO entities. There's a simple entity containing 3 properties:

public class Record
{
    public int Id { get; set; }
    public string Title { get; set; }
    public bool IsActive { get; set; }
}

The Title field is always unmodified, and the UI simply displays it without providing any input box to modify it. That's why the Title field is set to null when the form is sent to the server.

Here's how I tell EF to perform partial update of the entity (IsActive field only):

public class EFRepository<TEntity>
{
   ...
   public void PartialUpdate(TEntity entity, params Expression<Func<TEntity, object>>[] propsToUpdate)
   {
       dbSet.Attach(entity);
       var entry = _dbContext.Entry(entity);
       foreach(var prop in propsToUpdate)
           contextEntry.Property(prop).IsModified = true;
   }
}

and the call:

repository.PartialUpdate(updatedRecord, r => r.IsActive);

Calling SaveChanges method, I get the DbEntityValidationException, that tells me, Title is required. When I set dbContext.Configuration.ValidateOnSaveEnabled = false, everything is OK. Is there any way to avoid disabling validation on the whole context and to tell EF not to validate properties that are not being updated? Thanks in advance.

解决方案

If you use partial updates or stub entities (both approaches are pretty valid!) you cannot use global EF validation because it doesn't respect your partial changes - it always validates whole entity. With default validation logic you must turn it off by calling mentioned:

dbContext.Configuration.ValidateOnSaveEnabled = false

And validate every updated property separately. This should hopefully do the magic but I didn't try it because I don't use EF validation at all:

foreach(var prop in propsToUpdate) {
    var errors = contextEntry.Property(prop).GetValidationErrors();
    if (erros.Count == 0) {
        contextEntry.Property(prop).IsModified = true;
    } else {
        ...
    }
}

If you want to go step further you can try overriding ValidateEntity in your context and reimplement validation in the way that it validates whole entity or only selected properties based on state of the entity and IsModified state of properties - that will allow you using EF validation with partial updates and stub entities.

Validation in EF is IMHO wrong concept - it introduces additional logic into data access layer where the logic doesn't belong to. It is mostly based on the idea that you always work with whole entity or even with whole entity graph if you place required validation rules on navigation properties. Once you violate this approach you will always find that single fixed set of validation rules hardcoded to your entities is not sufficient.

One of things I have in my very long backlog is to investigate how validation affects speed of SaveChanges operation - I used to have my own validation API in EF4 (prior to EF4.1) based on DataAnnotations and their Validator class and I stopped using it quite soon due to very poor performance.

Workaround with using native SQL has same effect as using stub entities or partial updates with turned off validation = your entities are still not validated but in addition your changes are not part of same unit of work.

这篇关于实体框架验证与部分更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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