如何保存来自不同DBContext CTP5的相关新对象

发布于 2024-10-20 10:23:01 字数 2571 浏览 5 评论 0原文

我正在开发 MVC3 应用程序,并使用 DbContext 代码生成器从数据库创建了 POCO 类。一切都很顺利,直到我陷入这种境地。请注意,我使用存储库模式,并且为每个实体使用专用存储库,无论是否获取 DbContext 的新实例。

现在,我处于这种情况:

对象 A 与 B 具有一对多关系(A 可以有一个或多个 B) 对象 B 与 C 具有多对一关系(C 可以有一个或多个 B) 对象 B 与 D 存在多对一关系(D 可以有一个或多个 B)

我应该添加一个新对象 B,考虑到对象 C 和 D 还存在,所以我必须只做与对象 A 的关系可以创建或更新。具体来说,A 是客户,B 是订阅(C 和 D 是 B 中的虚拟对象属性)。

现在,如果我尝试保存,我会在 C 和 D 表中得到重复项,而对象的管理似乎有效。 所以,我认为我应该在建立关系之前分离实体,但是当我调用 SaveChanges() 时,我收到此错误:

存储更新、插入或删除语句影响了意外数量的行 (0)。自加载实体以来,实体可能已被修改或删除。刷新 ObjectStateManager 条目。

这是代码:


Customer customer = customerRepository.Get(ID);                  
if (customer == null)
{
     customer = new Customer();
     customer.Email = Request.Form["Email"].ToString();
}

Subscription subscription = new Subscription();
subscription.Active = true;
subscription.DateSubscription = DateTime.Today;

Object C = objectCRepository.Get(Request.Form["IDObjectC"]);//Get C object from database
Object D = objectDRepository.Get(Request.Form["IDObjectD"]);//Get D object from database

if (C != null)
{
    //I tried also to detach the objects before adding to subscription
    subscription.C = C;
    subscription.D = D;
    customer.Subscriptions.Add(subscription);

     if (customer.IDCustomer == 0)
         customerRepository.Add(customer);
     else
         UpdateModel(customer);

    customerRepository.Save();
}

这里是客户存储库的 add 和 save 方法:


public override void Add(Cliente cliente)
{
   db.Cliente.Add(cliente);
}

public override void Save()
{
  foreach (var entry in db.ChangeTracker.Entries()
               .Where(e => e.State == EntityState.Modified || e.State == EntityState.Added            || e.State == EntityState.Unchanged || e.State == EntityState.Detached))
  {
     string state = ObjectContext.GetObjectType(entry.Entity.GetType()).Name + " " + entry.State.ToString();

  if (ObjectContext.GetObjectType(entry.Entity.GetType()).Name.Equals("C") ||  ObjectContext.GetObjectType(entry.Entity.GetType()).Name.Equals("D"))
  {
     entry.State = EntityState.Unchanged;
  }
  dbContext.SaveChanges();
}

我也尝试将其用于对象 C 和 D。


((System.Data.Entity.Infrastructure.IObjectContextAdapter)dbContext).ObjectContext.Refresh(System.Data.Objects.RefreshMode.StoreWins, entry);

收到的错误是

要刷新的对象集合中索引 0 处的元素具有 null EntityKey 属性值或未附加到此 ObjectStateManager。

我注意到在CTP5中添加了选项AsNoTracking(),我尝试使用它,但没有任何结果! 我还检查了操作中涉及的每个属性的并发模式,所有属性都设置为“无”。 我完成了想法:(!

任何帮助将不胜感激!谢谢!

I'm working on a MVC3 application and I created my POCO classes from my database with the DbContext Code Generator. All goes fine until I got stuck in this situation. Note that I use the repository pattern and I use for every entity a dedicated repository whether get a new instance of the DbContext.

Now, I'm in this situation:

object A has a relation one-to-many with B (A can have one or many B)
object B has a relation many-to-one with C (C can have one or many B)
object B has a relation many-to-one with D (D can have one or many B)

I should add a new object B, consider that object C and D are yet existing, so I must only do the relation and the object A can be created or updated. In the specific consider that A is customer and B is subscriptions (C and D are virtual objects properties in B).

Now If I try to save I got duplicates in C and D tables, while the management of the object seems to work.
So, I thinked that I should detach the entities before do the relation, but when I call the SaveChanges() I got this error:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

Here's the code:


Customer customer = customerRepository.Get(ID);                  
if (customer == null)
{
     customer = new Customer();
     customer.Email = Request.Form["Email"].ToString();
}

Subscription subscription = new Subscription();
subscription.Active = true;
subscription.DateSubscription = DateTime.Today;

Object C = objectCRepository.Get(Request.Form["IDObjectC"]);//Get C object from database
Object D = objectDRepository.Get(Request.Form["IDObjectD"]);//Get D object from database

if (C != null)
{
    //I tried also to detach the objects before adding to subscription
    subscription.C = C;
    subscription.D = D;
    customer.Subscriptions.Add(subscription);

     if (customer.IDCustomer == 0)
         customerRepository.Add(customer);
     else
         UpdateModel(customer);

    customerRepository.Save();
}

And here the add and the save method of the customer repository:


public override void Add(Cliente cliente)
{
   db.Cliente.Add(cliente);
}

public override void Save()
{
  foreach (var entry in db.ChangeTracker.Entries()
               .Where(e => e.State == EntityState.Modified || e.State == EntityState.Added            || e.State == EntityState.Unchanged || e.State == EntityState.Detached))
  {
     string state = ObjectContext.GetObjectType(entry.Entity.GetType()).Name + " " + entry.State.ToString();

  if (ObjectContext.GetObjectType(entry.Entity.GetType()).Name.Equals("C") ||  ObjectContext.GetObjectType(entry.Entity.GetType()).Name.Equals("D"))
  {
     entry.State = EntityState.Unchanged;
  }
  dbContext.SaveChanges();
}

I tried also to use this for objects C and D.


((System.Data.Entity.Infrastructure.IObjectContextAdapter)dbContext).ObjectContext.Refresh(System.Data.Objects.RefreshMode.StoreWins, entry);

And the error received is

The element at index 0 in the collection of objects to refresh has a null EntityKey property value or is not attached to this ObjectStateManager.

I noticed that in CTP5 was added the option AsNoTracking(), I tried to use it, but nothing!
I checked also the Concurrency mode for every properties involved in the operation and all are set to None.
I finished ideas :(!

Any help would appreciated! Thanks!

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

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

发布评论

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

评论(1

一梦浮鱼 2024-10-27 10:23:01

实际上,我使用加载 AsNoTracking() 方法解决了自己的问题,并在保存实体之前将状态更改为“未更改”。

//On loading
Context.Object.AsNoTracking().SingleOrDefault(l => l.Property == Property);

//On saving
Object.State = EntityState.Unchanged;
Object.SaveChanges();

希望这对某人有帮助。

Actually I solved myself using on loading the AsNoTracking() method and before saving the entities I change the state to Unchanged.

//On loading
Context.Object.AsNoTracking().SingleOrDefault(l => l.Property == Property);

//On saving
Object.State = EntityState.Unchanged;
Object.SaveChanges();

Hope this helps someone.

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