2017-05-07 43 views
0

我正在使用实体框架5.0。我正在修改我的应用程序从ObjectContext到DbContext模型。 DbContext应该按照微软推荐的方法。我使用数据库福斯特方法,并且我生成了模型表单数据库。 但是,在第一个简单的任务中就存在一个问题。即记录的简单更新被破坏。如何将部分更新操作从ObjectContext转换为DbContext

让我们有一个简单的表项,只有ilustration:

Item 
(
    ItemId int NOT NULL, -- Primary key 
    Name nvarchar(50) NOT NULL, 
    Description NVARCHAR(50) 
) 

我注意到,使用的DbContext不支持更新不作为的ObjectContext做了记录。 在我的应用程序中,我有一个简单的更新方法。

public void UpdateItem() 
{ 
     MyContext context = new MyContext(); 
     Item item = new Item(); 
     item.ItemId = 666; 
     context.Items.Attach(item); 
     // From this point onward EF tracks the changes I make to Item 
     Item.Description = "Some description"; 
     context.SaveChanges(); 
} 

使用ObjectContext此方法正确更新记录。使用SQL事件探查我可以看到,它产生这样的事情(大大简化了!!!)

UPDATE Item 
SET Description = 'Some description' 
WHERE ItemId = 666 

但如果我尝试做的DbContext同样的事情,我得到异常:

System.Exception: Items.aspx.cs - logged from CustomError() ---> System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. 
    at System.Data.Entity.Internal.InternalContext.SaveChanges() 
    at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() 
    at System.Data.Entity.DbContext.SaveChanges() 

并没有数据库更新发布到Sql服务器。 我想DbContext验证所有的属性和属性名称为null。这是通过设计。我不打算修改它,我甚至不知道它是什么,我不需要知道它是什么。 只有属性“说明”已更改。很明显,ObjectContext不能正确跟踪更改。 如何解决这个问题?

我研究了这个问题,并找到更新记录的东西。 例如此链接:https://stackoverflow.com/a/15339512/4601078

db.Users.Attach(updatedUser); 
var entry = db.Entry(updatedUser); 
entry.Property(e => e.Email).IsModified = true; 
// other changed properties 
db.SaveChanges(); 

但是,这是可怕的代码。对于每一个属性上应该添加一行:

entry.Property(e => e.Email).IsModified = true; 

这会产生难看的不可读的代码,我怀疑LAMDA表达不在性能中柱。

更糟糕的是,那些打算往返数据库以获取所有已填写属性的现有记录,更新它和保存更改的人。在表演方面这是不合适的。

那么,如何处理简单的实体更新,或者这个DbContext只是微型收集死角的另一个项目,它们不是真正的目的?

回答

1

DbContext并未真正通过观察属性来跟踪更改,它将这些值与先前已知的值进行比较。而验证总是在整个实体上运行,所以如果你想这样做,唯一真正的选择就是在这个操作中禁用验证。见Entity Framework validation with partial updates

+0

我知道这是一个验证异常。验证本身(或跟踪)是错误的。 – f470071

+0

对不起,更新答案。 –

+0

嗯。您提供的链接可能与建议使用dbContext.Configuration.ValidateOnSaveEnabled = false的答案一致。虽然不是解决方案,但它至少是一种解决方法。我相信修改后的属性应该仍然有效。但这是一种解决方法,我在代码中进行更新前的验证。 Upvoted提供一半有用的链接和搜索短语“部分更新”。 – f470071

0

如果你知道肯定您应用是有效的,或者你有自定义代码来验证他们的变化,您可以通过EF完全关闭验证:

db.Configuration.ValidateOnSaveEnabled = false; 

这可以作为确定只要您按照自己的方式操作即可:使用已知Id(又名存根实体)附加一个新实体,然后修改其属性。 EF只会更新它检测为已被修改的属性(实际上通过比较原始值和当前值,而不是像ObjectContext那样通过更改通知)。您不应将实体本身标记为已修改。

如果你不想关闭EF的验证,但既不希望标记个别属性被修改,我认为this可能是一个有用的替代品(引起我的注意,亚历克斯的答案)。

相关问题