我想基于实体框架创建函数,该函数将更新SQL数据库中的表。
该表具有父子关系,因此我基于来更新一堆孩子parentID
。
我想拥有一个泛型函数,而且我不知道如何从编译时不知道其定义的对象中获取ID。
我尝试使用Func
它可能非常整洁,但不能在Linq-To-Entities中使用。
代码:
protected static void update<TEntity>(DbSet<TEntity> set, int parentID,
List<TEntity> entities, Func<TEntity, bool> isNew, Func<TEntity, int> getID = null,
Func<TEntity, int> getParentID, Action<TEntity, TEntity> updateSingleEntity)
where TEntity : class
{
var currentIDs = entities.Select(e => getID(e));
var newEntities = entities.Where(e => isNew(e));
var existingEntities = entities.Where(e => !isNew(e));
var deletedEntities
= set.Where(e => getParentID(e) == parentID && !currentIDs.Contains(getID(e)));
foreach (var toAdd in newEntities)
{
set.Add(toAdd);
}
foreach (var toDelete in deletedEntities)
{
var entity = set.Find(getID(toDelete));
set.Remove(entity);
}
foreach (var toUpdate in existingEntities)
{
var entity = set.Find(getID(toUpdate));
updateSingleEntity(toUpdate, entity);
}
}
我想这样使用此功能:
update(set, parentID, someList, e => e.ID != 0, e => e.ID, e => ParentID, somefunc);
IMO非常整洁。有什么办法可以实现这样的功能?
我做不到(我尝试过):
具有ID属性的接口可以整齐。但是我无法parentID
在此接口中定义,因为该属性的名称在DB中的实体周围有所不同。
首先,正如您在评论中告诉您的那样,您需要使用Expression<Func<TEntity,int>> getId
。
要使用它,请勿执行此操作,entities.Select(e => getID(e))
而只需执行this即可entities.Select(getID)
。原因是Select
需要一个lamba表达式,并且getId
包含lambda表达式。这Expression<>
是必需的,因此它是EF工作所需的表达式树,而不是已编译的表达式。您可以阅读以获取更多信息。
对于接口的替代解决方案,您必须像这样实现它:
public interface IId
{
public int GetId();
}
然后,您需要在所有类中实现它,例如:
public int GetId() { return parentId; }
或者
public int GetId() { return parentId; }
您还应该将接口约束添加到通用方法中,如下所示: where TEntity: class ,IId
但是,您会发现两个问题:
GetId
对所有实体类型(或至少对于将与thid方法一起使用的那些实体类型)实施GetId
函数无法转换为表达式树,因此EF不知道如何将其转换为SQL表达式。(我不确定,但是它甚至可能会引发错误)。本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句