2010-10-28 4 views
1

Я использую EF4 с POCO, а приведенный ниже код - это то, что я должен обновить. Я только вставил здесь раздел кода, который имеет отношение к проблеме, которая добавляет LicenseDetails.EF4 - POCO - SaveChanges непредсказуемо дублирует элементы в таблице поиска

Проблема заключается в том, что для каждого вставленного элемента LicenseDetail EF также непредсказуемо добавляет строки в таблицу поиска «Item». Зачем?!

Взаимосвязь обеих таблиц, определенных в базе данных (SQLServer 2008), показана ниже, и я сначала использую базу данных, поэтому EF генерирует отношения сущностей на основе этого.

ALTER TABLE [dbo].[LicenseDetail] 
WITH CHECK ADD CONSTRAINT [FK_LicenseDetail_Item] FOREIGN KEY([ItemId]) 
REFERENCES [dbo].[Item] ([Id]) 
GO 

ALTER TABLE [dbo].[LicenseDetail] CHECK CONSTRAINT [FK_LicenseDetail_Item] 
GO 

метод обновления:

public static void UpdateLicense(License license) 
    { 
     using (ALISEntities context = new ALISEntities()) 
     { 
      context.ContextOptions.ProxyCreationEnabled = true; 

      var storedLicense = 
       context.Licenses.Include("LicenseDetails") 
       .Where(o => o.Id == license.Id).SingleOrDefault(); 

      ////////////////////////////////////////////////////////////// 
      // license details to add 
      List<LicenseDetail> toAdd = new List<LicenseDetail>(); 

      foreach (LicenseDetail ld in license.LicenseDetails) 
      { 
       if (storedLicense.LicenseDetails 
        .Where(d => d.ItemId == ld.ItemId).Count() == 0) 
       { 
        toAdd.Add(ld); 
       } 
      } 

      toAdd.ForEach(i => storedLicense.LicenseDetails.Add(i)); 

      context.SaveChanges(); 
     } 
    } 

ответ

0

При добавлении нового LicenseDetails в контексте вы также добавлять элементы, которые ссылаются на эти LicenseDetails. Поскольку контекст не знает, что Элементы уже существуют в базе данных, он добавляет их. Вам нужно указать, что элементы уже находятся в базе данных, вызывая context.Items.Attach (licenseDetail.Item).

Вы также можете попробовать использовать

context.Licenses.Include("LicenseDetails").Find(license.Id); 

вместо

context.Licenses.Include("LicenseDetails") 
       .Where(o => o.Id == license.Id).SingleOrDefault(); 

и нет необходимости использовать toAdd список на всех - просто продолжайте добавлять licenseDetails в первом цикле Еогеасп.

+0

Jakub, большое вам спасибо за помощь. Теперь я понимаю! И спасибо за дополнительные советы тоже! – Donald

+0

@ user428774 - Добро пожаловать! Я должен признать, что это немного неинтуитивно, особенно когда вы конусе из менее сугубо ориентированного мира –

+0

Якуб, вчера я был дома, когда я отвечал на ваш ответ и отмеченный ваш ответ в качестве принятого ответа, потому что я вам поверил. Однако, находясь в офисе и тестируя ваше решение, у меня все еще есть та же проблема. – Donald

0

я в конечном итоге того, чтобы выдать context.ObjectStateManager.ChangeObjectState (d.Item, EntityState.Unchanged) для каждого LicenseDetail добавлен. Это решило проблему.

Смежные вопросы