2015-01-23 3 views
0

У меня есть объекты Exhibit и Exhibition, которые находятся во многих отношениях. Exhibit также может иметь много категорий.Исключение при подключении объекта с навигационными свойствами

public class ExhibitionModel 
{ 
    public ExhibitionModel() 
    { 
     this.Exhibits = new List<ExhibitModel>(); 
    } 

    [Key] 
    public int ExhibitionId { get; set; } 

    //some props 

    public virtual IList<ExhibitModel> Exhibits { get; set; } 
} 

public class ExhibitModel 
{ 
    [Key] 
    public int ExhibitId { get; set; } 

    //some props 

    public virtual IList<CategoryModel> Categories { get; set; } 
    public virtual IList<ExhibitionModel> Exhibitions { get; set; } 
} 

public class CategoryModel 
{ 
    [Key] 
    public int CategoryId { get; set; } 

    public virtual IList<ExhibitModel> Exhibits { get; set; } 
} 

Когда я создаю новую выставку, на моем ViewModel У меня есть все параметры выставки и строка, которая содержит отдельные экспонаты идентификаторы.

public ActionResult Create(CreateExhibitionViewModel model) 
    { 
     try 
     { 
      if (ModelState.IsValid) 
      { 
       if (!String.IsNullOrEmpty(model.ExhibitsString)) 
       { 
        model.Exhibition.AddExhibitsToModel(model.ExhibitsString, exhibitsRepo); 
       } 

       var result = exhibitionsRepo.Create(model.Exhibition); 
       if (result != null) 
       { 
        return RedirectToAction("Index"); 
       } 
      } 
      return View(model); 
     } 
     catch 
     { 
      return View(); 
     } 
    } 

    public static void AddExhibitsToModel(this ExhibitionModel model, string exhibitsString, ExhibitsRepository exhibitsRepo) 
    { 
     if (!String.IsNullOrEmpty(exhibitsString)) 
     { 
      string[] ids = exhibitsString.Split(','); 
      foreach (string stringId in ids) 
      { 
       int id; 
       ExhibitModel exhibit = new ExhibitModel(); 
       if (int.TryParse(stringId, out id)) 
       { 
        exhibit = exhibitsRepo.Read(id); 
       } 

       model.Exhibits.Add(exhibit); 
      } 
     } 
    } 

И Create метод из ExhibitionRepository

public ExhibitionModel Create(ExhibitionModel exhibition) 
    { 
     try 
     { 
      using (var dbContext = new MuseumContext()) 
      { 
       foreach (var exhibit in exhibition.Exhibits) 
       { 
        if (exhibit.ExhibitId != 0 && dbContext.Entry(exhibit).State == EntityState.Detached) 
        { 
         dbContext.Exhibits.Attach(exhibit); 
        } 
       } 

       var result = dbContext.Exhibitions.Add(exhibition); 
       dbContext.SaveChanges(); 
       return result; 
      } 
     } 
     catch (Exception ex) 
     { 
      return null; 
     } 
    } 

Как вы можете видеть, я прикрепление каждый экспонат объект, чтобы избежать создания новых записей. И когда две выставки имеют ту же категорию, прикрепляя второй экспонат бросает исключение

Прикрепление объект типа «Project.Models.CategoryModel» не удалось, так как другой объект того же типа, уже имеет один и тот же значение первичного ключа. Это может произойти при использовании метода «Прикрепить» или установки состояния объекта в «Без изменений» или «Модифицировано», если любые объекты на графике имеют конфликтующие значения ключей. Это может быть связано с тем, что некоторые объекты являются новыми и еще не получили значения ключей базы данных. В этом случае используйте метод «Добавить» или «Добавленное» состояние объекта для отслеживания графика, а затем, если необходимо, установите состояние не новых объектов «Без изменений» или «Модифицировано».

Что мне делать, чтобы исправить эту проблему?

С уважением, Konrad

ответ

0

Эта ошибка обычно происходит, когда объект уже отслеживается EF. Я думаю, он может быть здесь:

exhibit = exhibitsRepo.Read(id); 

У вас есть два варианта.

  1. Вы можете установить метод чтения с помощью AsNoTracking(). Возможно db.Exhibits.AsNoTracking().Where(x => x.Id== id);

    Таким образом, вы явно укажете EF, чтобы не отслеживать объект.

  2. Если Экспонаты уже размещены в базе данных, просто добавив их в коллекцию выставки и сохранив изменения, EF должен сделать и сохранить ссылку для вас (в записях экспонатов). Нет необходимости повторно прикреплять объект.

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