EF 4.1 DBContext 和导航属性
我们已经使用 EF STE 一段时间了,但是我们的应用程序已经增长了很多,我们决定起诉新的 4.1 DbContext,这样我们就可以在数据层之上“发展”一个单独的业务层,而不必使用不同的类型为了它。
在对 DbContext 做事方式的基本评估中,我遇到了一个小问题。
我习惯于查询和预加载所需的相关数据,例如:
return context.Orders.Include("Detail").SingleOrDefault(ord => ord.ID == ID);
然后将返回的对象发送到 UI 进行修改,并在从 UI 返回时将更改保存到数据库。
从我到目前为止所读到的内容来看,在 DbContext 中执行“更改保存”可以使用如下代码轻松完成:
context.Entry(order).State = EntityState.Modified;
此代码的问题在于,它实际上将对象中的所有属性标记为已修改,这是不允许的某些属性我的模型(业务规则)。
我求助于以下解决方案(这似乎需要大量代码才能满足相对较小的要求!顺便说一句,不支持将修改后的属性状态更改为“未更改”):
context.Orders.Attach(order);
DbEntityEntry<Order> ordEntity = context.Entry(order);
string[] arr =
{
ordEntity.Property(ord => ord.ID).Name,
ordEntity.Property(ord => ord.ClientID).Name,
};
foreach (string prop in ordEntity.OriginalValues.PropertyNames)
{
if (!arr.Contains(prop))
{
ordEntity.Property(prop).IsModified = true;
}
}
context.SaveChanges();
我使用此代码面临的问题是“Attach”语句抛出异常,表明附加对象中的导航属性存在某种冲突,即使根本没有对任何内容进行任何更改! (与从数据库中检索到的对象完全相同地保存对象)。 错误消息类似于: “已检测到关系‘OrdersDatamodel.FK_Order_Detail’的角色‘详细信息’的更改发生冲突。”
问题是:
- 是否有更“优雅”的方法来防止某些对象属性被修改?
- 有谁知道将对象附加到上下文时引发的异常是怎么回事?
谢谢。
We've been using EF STEs for a while, but our application has grown quite a bit and we decided to sue the new 4.1 DbContext so we can "evolve" a separate business layer on top of our data layer without having to use different types for it.
In the elementary evaluation for the DbContext way of doing things, I am facing a little problem.
I am used to query and preload required related data like:
return context.Orders.Include("Detail").SingleOrDefault(ord => ord.ID == ID);
And then send the returned object to the UI for modification, and when returned from the UI save the changes to the database.
From what I read so far, doing the "change saving" in DbContext is easily done using code like this:
context.Entry(order).State = EntityState.Modified;
The problem with this code is that it actually marks all properties in the object as modified, a thing that's not allowed for some properties in my model (a business rule).
I resorted to the following solution (which seems to require a lot of code for a relatively small requirement! BTW, changing a modified property state to Unchanged is not supported):
context.Orders.Attach(order);
DbEntityEntry<Order> ordEntity = context.Entry(order);
string[] arr =
{
ordEntity.Property(ord => ord.ID).Name,
ordEntity.Property(ord => ord.ClientID).Name,
};
foreach (string prop in ordEntity.OriginalValues.PropertyNames)
{
if (!arr.Contains(prop))
{
ordEntity.Property(prop).IsModified = true;
}
}
context.SaveChanges();
The problem I am facing with this code is that the "Attach" statement is throwing an exception saying that there is some sort of conflict in the navigation properties in the attached object, even if no changes were made to anything at all! (saving the object exactly as it was retrieved from the database).
The error message is something like:
"Conflicting changes to the role 'Detail' of the relationship 'OrdersDatamodel.FK_Order_Detail' have been detected."
The questions are:
- Is there a more "elegant" way for preventing the modification of certain object properties?
- Does anybody know what's going on with the exception raised when attaching the object to the context?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您很少需要显式设置状态。当您修改属性时,假设它们是虚拟的,状态将自动更改为已修改,而无需您进行设置。否则,
DetectChanges
将在您调用SaveChanges
期间获取此信息。You rarely need to explicitly set the state. When you modify properties, assuming they are
virtual
, the state will automatically change toModified
without you having to set it. Otherwise,DetectChanges
will pick this up during your call toSaveChanges
.