这是一种方法,我必须以多对多关系更新单个导航属性,但它对于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 :(得分: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作为静态方法