EF4保存复杂的分离对象图

发布于 2024-11-27 13:26:24 字数 2180 浏览 1 评论 0原文

我有以下基于 EntityObject 的 EF 模型(此处编写的属性作为字段以保持代码简洁):

Booking 
{
   int BookingID;
   EntityCollection<BookingCustomer> BookingCustomers;
   string Notes;
}

BookingCustomer 
{
   Customer Customer;
   Booking Booking;
   int CustomerID;
   int BookingID;
   string Notes;
}

Customer 
{
   int CustomerID;
   string Name;
}

我以分离的方式加载对象图:

Booking existingBooking;
using(MyContext ctx = new MyContext())
{
    ctx.Bookings.MergeOption = MergeOption.NoTracking;
    ctx.BookingCustomers.MergeOption = MergeOption.NoTracking;
    ctx.Customers.MergeOption = MergeOption.NoTracking;
    existingBooking = ctx.Bookings
       .Include("BookingCustomers")
       .Include("BookingCustomers.Customer")
       .First();
}

修改预订和客户数据:

existingBooking.Notes = "Modified";
existingBooking.BookingCustomers.First().Name += " Edited";

保存它:

using(MyContext ctx = new MyContext())
{
        ctx.Bookings.Attach(existingBooking);
        ctx.ObjectStateManager.GetObjectStateEntry(existingBooking ).SetModified();
        ctx.Refresh(RefreshMode.ClientWins, existingBooking);    
        ctx.SaveChanges();
} 

我得到一个 创建新的客户记录(而不是更新现有记录)。

我也尝试过这个:

using(MyContext ctx = new MyContext())
{
    ctx.Customers.Attach(existingBooking.BookingCustomers.First());
    ctx.ObjectStateManager.GetObjectStateEntry(existingBooking.BookingCustomers.First()).SetModified();
    ctx.Refresh(RefreshMode.ClientWins, existingBooking.BookingCustomers.First());

    ctx.Bookings.Attach(existingBooking);
    ctx.ObjectStateManager.GetObjectStateEntry(existingBooking ).SetModified();
    ctx.Refresh(RefreshMode.ClientWins, existingBooking);    
    ctx.SaveChanges();
} 

但是在 ctx.Customers.Attach(existingBooking.BookingCustomers.First()); 线上出现异常:

System.InvalidOperationException: A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.

我怎样才能让它工作?

I've got the following EntityObject-based EF model (properties written here as fields for keeping code cleaner):

Booking 
{
   int BookingID;
   EntityCollection<BookingCustomer> BookingCustomers;
   string Notes;
}

BookingCustomer 
{
   Customer Customer;
   Booking Booking;
   int CustomerID;
   int BookingID;
   string Notes;
}

Customer 
{
   int CustomerID;
   string Name;
}

I'm loading the object graph in a detached manner:

Booking existingBooking;
using(MyContext ctx = new MyContext())
{
    ctx.Bookings.MergeOption = MergeOption.NoTracking;
    ctx.BookingCustomers.MergeOption = MergeOption.NoTracking;
    ctx.Customers.MergeOption = MergeOption.NoTracking;
    existingBooking = ctx.Bookings
       .Include("BookingCustomers")
       .Include("BookingCustomers.Customer")
       .First();
}

Modifying booking and customer data:

existingBooking.Notes = "Modified";
existingBooking.BookingCustomers.First().Name += " Edited";

Saving it:

using(MyContext ctx = new MyContext())
{
        ctx.Bookings.Attach(existingBooking);
        ctx.ObjectStateManager.GetObjectStateEntry(existingBooking ).SetModified();
        ctx.Refresh(RefreshMode.ClientWins, existingBooking);    
        ctx.SaveChanges();
} 

I get a new Customer record created (instead of existing record updated).

I've also tried this:

using(MyContext ctx = new MyContext())
{
    ctx.Customers.Attach(existingBooking.BookingCustomers.First());
    ctx.ObjectStateManager.GetObjectStateEntry(existingBooking.BookingCustomers.First()).SetModified();
    ctx.Refresh(RefreshMode.ClientWins, existingBooking.BookingCustomers.First());

    ctx.Bookings.Attach(existingBooking);
    ctx.ObjectStateManager.GetObjectStateEntry(existingBooking ).SetModified();
    ctx.Refresh(RefreshMode.ClientWins, existingBooking);    
    ctx.SaveChanges();
} 

but getting exception on line ctx.Customers.Attach(existingBooking.BookingCustomers.First());:

System.InvalidOperationException: A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.

How can i make it work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

木槿暧夏七纪年 2024-12-04 13:26:24

这与刷新无关。如果您在分离状态下修改图表,EF 将无法找到您所做的更改。您必须手动设置每个已修改实体的状态或关系Attach 会将整个图置于 Unchanged 状态,而 ChangeObjectState 仅影响图中的单个实体。

您发现最简单的方法是在保存期间再次加载整个图表,并手动将更改合并到附加图表中。特别是如果您想删除一些关系/实体或对多对多关系进行复杂的操作,这会很方便。

It is not about refreshing. If you modify the graph in detached state EF is not able to find what changes you did. You must manually set the state of each modified entity or relation. Attach will put whole graph in Unchanged state and ChangeObjectState affects only single entity in the graph.

You found that the easiest way is to load the whole graph again during saving and manually merge your changes to attached graph. Especially if you want to delete some relations / entities or do complex operations with many to many relation this would be handy.

往事随风而去 2024-12-04 13:26:24

拉迪斯拉夫是正确的。但是,您还应该考虑另一个选项,它可以解决此问题,并且仍然允许您保留分离模型 - 自跟踪 POCO。有一个 T4 模板(它要么与 VS2010 捆绑在一起,要么可以下载),它允许对象图跟踪其状态(这包括在图中添加/删除对象以及对象的哪些属性已更改),以便您可以重新附加进行修改的图表; EF4 将找出更改并将这些更改应用于对象状态管理器。

Ladislav is correct. However, there is one more option that you should consider which would solve this problem and still allow you to retain the detatched model - self tracking POCOs. There's a T4 template (it's either bundled with VS2010 or is available as a download) which allows an object graph to track its state (this includes adding / removing objects into the graph as well as what properties with an object have changed) so that you can reattach the graph having made modifications; EF4 will figure out the changes and apply those to object state manager for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文