2014-07-10 35 views
2

这是一种方法,我必须更新多对多关系中的单个导航属性,但它对于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(); 
      } 
     } 
+0

可能是一个更好的问题为http://programmers.stackexchange.com – Evonet

回答

2

你可以这样做。

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<TEntity,object> 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作为静态方法