开发者

Can't update foreign key reference(navigation property)

开发者 https://www.devze.com 2023-02-16 13:19 出处:网络
I know that it seems a duplicate entry, but I red all the posts related with my problem and I can\'t find the solution. I\'m stuck with this problem about one week. Maybe I have made some design probl

I know that it seems a duplicate entry, but I red all the posts related with my problem and I can't find the solution. I'm stuck with this problem about one week. Maybe I have made some design problem or I don't know. The problem is I can't update a navigation property, I tried several options, everytime i got a different error or a duplicate. Ok, here's the scenario:

I have an object "List"

int ID

string Name

int SendType

Category category //these are navigation property

Product product //these are navigation property

Category and Product don't know about the relation with List. I use POCO classes generated by the CTP5 DbContext Generator Template and I use a repository for every entity. In each repository there's a reference to the dbcontext.

And this is the controller:

[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");                               
    }

If I try directly I receive the error

The entity type 'DbEntityEntry' is not part of the model for the current context

because I modify the state of the entity Category or product(they are from another context)

If I submit the changes, without modifying the association, I receive the error

'IDCategory' is a reference key and cannot be updated

And so on......Any suggest will be appreciated, I can also modify the viewmodel if I'm wrong.I'm without ideas! Thanks

UPDATE

    //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; }
        }
   }

This is all the code involved. Thanks!


Remove checkReferencies because:

  • List in your example is not modified so the first part of the method will not be executed.
  • The Product cannot be converted to Category and attached to DbSet. It will throw exception.
  • Category is already attached in Addes state (which is wrong because it will insert category again). Attaching entity again will throw the exception.

Just attach both Category and Product to context from listRepository before you set them in List.

Or better completely rewrite your code and share context among repostiories.

0

精彩评论

暂无评论...
验证码 换一张
取 消