2014-07-10 40 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作爲靜態方法