Не удается обновить ссылку на внешний ключ (свойство навигации)

Я знаю, что это похоже на дублирующую запись, но я просмотрел все сообщения, связанные с моей проблемой, и не могу найти решение. Я застрял с этой проблемой около одной недели. Может быть, я сделал некоторые проблемы с дизайном или я не знаю. Проблема в том, что я не могу обновить свойство навигации, я пробовал несколько вариантов, каждый раз получая другую ошибку или дубликат. Хорошо, вот сценарий:

У меня есть объект "Список"
int ID
string Name
int SendType
Категория категории // это свойство навигации
Product product // это свойство навигации < бр />

Категория и Продукт не знают об отношении к Списку. Я использую классы POCO, сгенерированные шаблоном CTP5 DbContext Generator, и использую репозиторий для каждой сущности. В каждом репозитории есть ссылка на dbcontext.

А это контроллер:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, List list)
    {
        if (!ModelState.IsValid)
            return View(list);

        List originalList = this._listRepository.Get(id);
        TryUpdateModel(originalList, "List", new string[] { "Name", "SendType"});
        //Here's I tried to update manually like this
        if (list.category.id != originalList.category.id)
        {
           Category category = this._categoryRepository.GetNoTracking(list.category.id);
           originalList.Category = category; 
        }
        if (list.product.id != originalList.product.id)
        {
           Product product = this._productRepository.GetNoTracking(list.product.id);
           originalList.Product = product; 
        }
        this._listRepository.Save(); //Here's I call only the SubmitChanges()
        return RedirectToAction("Index");                               
    }

Если я попытаюсь напрямую, я получаю сообщение об ошибке

Тип сущности «DbEntityEntry» не является частью модели для текущего контекста.

потому что я изменяю состояние категории объекта или продукта (они из другого контекста)

Если я отправляю изменения без изменения ассоциации, я получаю сообщение об ошибке

«IDCategory» является справочным ключом и не может быть обновлен

И так далее ...... Любое предложение будет оценено, я также могу изменить модель представления, если я ошибаюсь. У меня нет идей! Спасибо

ОБНОВЛЕНИЕ

    //This is in List Repository
    public override void Save()
    {           
        checkReferencies();
        db.SaveChanges();            
    }

    private void checkReferencies()
    {          
         foreach (var entry in db.ChangeTracker.Entries()
                               .Where(e => e.State == EntityState.Modified || e.State == EntityState.Added))
         {
             if (ObjectContext.GetObjectType(entry.Entity.GetType()).Name.Equals("List"))
             {
                 /*In this case I tried to update my object directly with the object that comes form the form
                 if (entry.CurrentValues.GetValue<int>("IDList").ToString() != "0" )
                 {
                     db.Entry(entry.Entity).State = EntityState.Modified;
                 }    */                 
                 if (((List)entry.Entity).Product != null)
                 {
                     db.Entry(((List)entry.Entity).Product).State = EntityState.Unchanged;
                 }
                 if (((List)entry.Entity).Category != null)
                 {
                     db.Entry(((List)entry.Entity).Category).State = EntityState.Unchanged;
                 }
             }
             else if (ObjectContext.GetObjectType(entry.Entity.GetType()).Name.Equals("Product") 
                   || ObjectContext.GetObjectType(entry.Entity.GetType()).Name.Equals("Category"))
             {
                 //here I attach the entry that I added
                 db.Category.Attach((Category)db.Entry(entry).Entity.Entity);

             }
         }
    }

    //This is in categoryRepository
    public Category GetNoTracking(int id)
    {            
        return db.Category.AsNoTracking().Single(l => l.IDCategory == id);
    }

    //This is in productRepository
    public Product GetNoTracking(int id)
    {            
        return db.Product.AsNoTracking().Single(l => l.IDProduct == id);
    }

    //This is my DbContext
    namespace BusinessManagerEmail.Models
    {
         using System;
         using System.Data.Entity;

         public partial class DBMailMarketingEntities : DbContext
         {
             public DBMailMarketingEntities()
             : base("name=DBMailMarketingEntities")
             {
             }

             public DbSet<Category> Category { get; set; }
             public DbSet<Customer> Customer { get; set; }
             public DbSet<Subscription> Subscription { get; set; }
             public DbSet<List> List { get; set; }
             public DbSet<Product> Product { get; set; }
        }
   }

Это весь задействованный код. Спасибо!


person stuzzo    schedule 14.03.2011    source источник
comment
Почему вы не делитесь контекстом между репозиториями?   -  person Ladislav Mrnka    schedule 14.03.2011
comment
Потому что это мой первый проект в MVC, и я следовал рекомендациям NerdDinner. Мой следующий шаг — добавить UnitOfWork, который обертывает контекст. Но теперь я должен сделать то, что я написал :((очевидно, это не моя воля)!   -  person stuzzo    schedule 14.03.2011
comment
потому что я изменяю состояние объекта Категория или продукт: Где вы это делаете и до какого состояния вы меняете? Как уже указал Ладислав, если у вас разные контексты в _listRepository и _listCategory, то category не привязан к контексту _listRepository. Или какие-то важные фрагменты кода отсутствуют?   -  person Slauma    schedule 14.03.2011
comment
Да, они пришли из разных контекстов, но когда я должен их прикрепить? Я редактирую свой исходный пост и покажу вам код, который я пробовал.   -  person stuzzo    schedule 14.03.2011
comment
@stuzzo: На мой взгляд, фрагмент кода вашего ListFormViewModel и фрагмент кода HTML/Razor не имеют отношения к вашей проблеме. Удалите это из своего вопроса и вместо этого добавьте код, как выглядят _listRepository и _listCategory (особенно те методы Get). Возможно, также часть вашего производного DbContext. Я думаю, что это было бы более полезно, чтобы ответить на ваш вопрос.   -  person Slauma    schedule 14.03.2011
comment
@Slauma: спасибо, сейчас сделаю :)!   -  person stuzzo    schedule 15.03.2011


Ответы (1)


Удалите checkReferencies, потому что:

  • List в вашем примере не изменяется, поэтому первая часть метода выполняться не будет.
  • Product нельзя преобразовать в Category и присоединить к DbSet. Это вызовет исключение.
  • Category уже присоединен в состоянии Addes (что неправильно, потому что он снова вставит категорию). Повторное присоединение объекта вызовет исключение.

Просто присоедините Category и Product к контексту из listRepository, прежде чем устанавливать их в List.

Или лучше полностью перепишите свой код и поделитесь контекстом между репозиториями.

person Ladislav Mrnka    schedule 15.03.2011
comment
Спасибо за все предложения! Я пытаюсь изменить его, и я надеюсь решить его! Я почти уверен, что мне понадобится ваша помощь: P! - person stuzzo; 15.03.2011
comment
Вы совершенно правы! Я удалил весь свой код и переписал его с вашими предложениями! Спасибо за вашу помощь! Извините, если я разместил ужасный код! - person stuzzo; 16.03.2011