Как сохранить связанные новые объекты, полученные из разных файлов DBContext CTP5 - PullRequest
0 голосов
/ 04 марта 2011

Я работаю над приложением MVC3, и я создал свои классы POCO из своей базы данных с помощью генератора кода DbContext.Все идет хорошо, пока я не застрял в этой ситуации.Обратите внимание, что я использую шаблон репозитория и использую для каждой сущности выделенный репозиторий, независимо от того, получаю ли он новый экземпляр 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();
}

А вот метод добавления и сохранения в хранилище клиента:


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 в коллекции объектов для обновления имеет нулевое значение свойства EntityKey или не присоединен к этому ObjectStateManager.

Я заметил, что в CTP5 была добавлена ​​опция AsNoTracking (), я пытался ее использовать, но ничего!Я также проверил режим параллелизма для каждого свойства, участвующего в операции, и для всех установлено значение Нет.Я закончил идеи: (!

Любая помощь будет оценена! Спасибо!

1 Ответ

0 голосов
/ 04 марта 2011

На самом деле я решил сам, используя при загрузке метод AsNoTracking (), и перед сохранением сущностей я изменяю состояние на Без изменений.

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

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

Надеюсь, это кому-нибудь поможет.

...