【问题标题】:Making a generic method to update entity framework many-to-many navigation property制作更新实体框架多对多导航属性的通用方法
【发布时间】:2014-07-10 22:16:28
【问题描述】:

这是一种我必须以多对多关系更新单个导航属性的方法,但它对于 DAL 来说太具体了。我想知道是否有人可以帮助使此方法更通用,以便它可以处理传入的任何实体。

我会传入两个参数:要更新的实体和要修改的导航属性。

以下方法适用于多对多关系中涉及的项目表和属性表。一个项目可以分配给多个属性,一个属性可以有多个项目。

感谢您提供的任何帮助。

public void UpdateItems(Property property)
        {
            using (var context = new PropertyManagementDBEntities())
            {
                var customerInDb = context.Properties.Include("Items")
                    .Single(c => c.propertyId == property.propertyId);



                // Remove types
                foreach (var itemInDb in customerInDb.Items.ToList())
                    if (!property.Items.Any(t => t.itemId == itemInDb.itemId))
                        customerInDb.Items.Remove(itemInDb);

                // Add new types
                foreach (var item in property.Items)
                    if (!customerInDb.Items.Any(t => t.itemId == item.itemId))
                    {
                        context.Items.Attach(item);
                        customerInDb.Items.Add(item);
                    }

                context.SaveChanges();
            }
        }

【问题讨论】:

标签: c# asp.net sql-server linq entity-framework


【解决方案1】:

你可以这样做。

public void UpdateItems<TEntity,TRelated>(
    // Entity with new list of related items
    TEntity entity, 
    // Selector for the key of the entity element
    Func<TEntity,object[]> entityKeySelector,
    // Selector for the related items of the Property
    Expression<Func<TEntity,ICollection<TRelated>>> relatedItemsSelector,
    // Comparer of related items
    Func<TRelated, TRelated, bool> relatedItemsComparer)
    where TEntity : class
    where TRelated : class
{
    using (var context = new TCtx())
    {
        // get the Keys for the entity
        object[] entityKeyValues = entityKeySelector.Invoke(entity);
        // gets the entity entity from the DB
        var entityInDb = context.Set<TEntity>().Find(entityKeyValues);
        // loads the related entities from the DB
        context.Entry(entityInDb).Collection(relatedItemsSelector).Load();

        // gets the list of properties in the passed entity
        var newRelatedItems 
            = relatedItemsSelector.Compile().Invoke(entity);

        // Gets the list of properties loaded from the DB
        var relatedItemsInDb 
            = relatedItemsSelector.Compile().Invoke(entityInDb);

        // Remove related elements
        foreach (var relatedInDb in relatedItemsInDb)
            if (!newRelatedItems.Any(item => relatedItemsComparer
                 .Invoke(relatedInDb, item)))
            {
                // If the related intem in DB is not in the entity, remove it
                relatedItemsInDb.Remove(relatedInDb);
            }

        // Add new types
        foreach (var item in newRelatedItems)
            if (!relatedItemsInDb.Any(itemInDb => relatedItemsComparer
                .Invoke(itemInDb, item)))
            {
                // Attach the item to the Set
                context.Set<TRelated>().Attach(item);
                // If the related item is not in the DB add it
                relatedItemsInDb.Add(item);
            }

        context.SaveChanges();
    }
}

如果您的实体只有一个键字段,您可以将实体键选择器更改为此:Func&lt;TEntity,object&gt; entityKeySelector,这样更易​​于使用(或实现两种签名)。

例如,如果您有可以具有不同颜色的项目,则可以这样调用它

ManyToManyHandler<MyDbContext>.UpdateItems(
    item,
    i => new object[] {i.ItemId},
    i => i.Colors,
    (c1, c2) => c1.ColorId == c2.ColorId
    );

第二次重载:

ManyToManyHandler<MyDbContext>.UpdateItems(
    item,
    i => i.ItemId,
    i => i.Colors,
    (c1, c2) => c1.ColorId == c2.ColorId
    );

注意:我使用的是 ManyToManyHandler 类,它是一个泛型静态类,TCtx 作为泛型参数,UpdateItems 作为静态方法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多