简体   繁体   中英

Entity Framework same entity in multiple navigation collections

I have an issue updating specific entity graph, containing entity with two navigation properties of the same type (two foreign keys to the same table)

这是数据库结构

So, the product can participate in promo (one to many) and also promo has a set on products, using as a gifts (many to many). You buying one product and get another one (or many) for free if there is a promo associated with the product.

Here is my class structure:

public class Product
{
    public int Id { get; set; }

    public int? PromoItemId { get; set; }

    public virtual PromoItem PromoItem { get; set; }

    public virtual ICollection<PromoItem> AddedToPromoItems { get; set; }
}

public class PromoItem
{
    public int Id { get; set; }

    [InverseProperty("PromoItem")]
    public virtual ICollection<Product> Products { get; set; }

    public virtual ICollection<Product> AddedProducts { get; set; }
}

I'm trying to update PromoItem entity including Products and AddedProducts collections using single EF context:

    public void Update(PromoItem entity)
    {
        using (var context = new MyContext())
        {
            // original entity
            var originalEntity = context.PromoItems
                .Include(p => p.Products)
                .Include(p => p.AddedProducts)
                .Single(p => p.Id == entity.Id);

            // update products (one to many)
            var productIds = entity.Products.Select(ap => ap.Id).ToList(); // get products ids
            var products = context.Products // load products from DB
                .Where(p => productIds.Contains(p.Id))
                .ToList();
            originalEntity.Products.UpdateFrom(products, context); // here is Add, Remove etc to collection


            // update added products (many to many)
            // *********************
            // one of the product here was removed from Products collection, so it already attached to the  context and has "Deleted" state!
            // *********************
            var addedProductIds = entity.AddedProducts.Select(ap => ap.Id).ToList(); // get products ids
            var addedProducts = context.Products // load products from DB
                .Where(p => addedProductIds.Contains(p.Id))
                .ToList();
            originalEntity.AddedProducts = addedProducts; // assign many to many collection

            // update entity
            context.Update(originalEntity, entity);

            // save changes
            context.SaveChanges(); // here I got an error "Adding a relationship with an entity which is in the Deleted state is not allowed."
        }
    }

Problem appears when same product is in both collections. Let's say I want to remove it from one collection and add to another. I need to update only base entity and it associacions (not products itself). How to load the same entity twice with different state within same DB context?

I've encountered this problem as well, and the not-so-clean solution was to map the join table as an entity and use its navigation properties instead of having two relationships of a different kind between the same 2 entity models.

public class PromoItemProduct
{
     public int ProductId { get; set; }
     public int PromoItemId { get; set; }


     public virtual Product Products { get; set; }
     public virtual PromoItem PromoItem { get; set; }
}

And then change the many-to-many navigation properties of the Product and PromoItem models to PromoItemProduct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM