C# 在TEntity通用存储库上更新父集合和子集合

C# 在TEntity通用存储库上更新父集合和子集合,c#,entity-framework-core,C#,Entity Framework Core,我的基本存储库类 公共类存储库:i存储库,其中tenty:class,ienty { 受保护的只读上下文\u上下文; 私人DbSet_实体; 公共存储库(CBS上下文) { _context=context??抛出新ArgumentNullException(nameof(context)); _实体=_context.Set(); } 公共异步任务UpdateAsync(TEntity实体) { wait Task.Run(()=>_context.Entry(entity.St

我的基本存储库类

公共类存储库:i存储库,其中tenty:class,ienty
{       
受保护的只读上下文\u上下文;
私人DbSet_实体;
公共存储库(CBS上下文)
{
_context=context??抛出新ArgumentNullException(nameof(context));
_实体=_context.Set();
}
公共异步任务UpdateAsync(TEntity实体)
{
wait Task.Run(()=>_context.Entry(entity.State=EntityState.Modified);
}
//更新下面添加的子实体代码
}
和我的实体接口

公共接口的可扩展性
{
TId Id{get;set;}
}
公共类客户:IEntity
{
公共int Id{get;set;}
公共字符串CustomerNo{get;set;}
公共ICollection

anser是基于自定义的基础,但我使用的是IEnity

已完成的工作:

我用Tentity替换了baseentity。但是显示错误

下面是保存子元素的新代码

公共异步任务UpdateAsync(tenty实体,参数表达式[]导航)
{
var dbEntity=await_context.FindAsync(entity.Id);
var dbEntry=_context.Entry(dbEntity);
dbEntry.CurrentValues.SetValues(实体);
foreach(导航中的表达式属性)
{
var propertyName=property.GetPropertyAccess().Name;
var dbItemsEntry=dbEntry.Collection(propertyName);
var accessor=dbItemsEntry.Metadata.GetCollectionAccessor();
等待dbItemsEntry.LoadAsync();
var dbItemsMap=((IEnumerable)dbItemsEntry.CurrentValue)
.ToDictionary(e=>e.Id);
var items=(IEnumerable)访问器.GetOrCreate(实体);
foreach(项目中的var项目)
{
如果(!dbItemsMap.TryGetValue(item.Id,out var oldItem))
accessor.Add(dbEntity,item);
其他的
{
_context.Entry(oldItem).CurrentValues.SetValues(item);
dbItemsMap.Remove(item.Id);
}
}
foreach(dbItemsMap.Values中的var oldItem)
accessor.Remove(dbEntity,oldItem);
}
等待任务。运行(()=>_context.saveChangesSync());
}
下面显示错误:


是否有其他方法..我是.net core的新手..请建议是否有其他方法。

更新:

评论中还提出了一些其他问题。如何处理引用导航属性,如果相关实体未实现此类泛型接口,如何处理,以及编译器在使用此类泛型方法签名时无法推断泛型类型参数

经过思考,我得出结论,根本不需要基类/接口(甚至通用实体类型),因为EF核心元数据包含使用PK所需的所有信息(例如,
Find
/
FindAsync
方法和更改跟踪器使用PK)

以下是一种仅使用EF核心元数据信息/服务递归应用断开连接的实体图修改的方法。如果需要,可以对其进行修改以接收“排除”筛选器,以防跳过某些实体/集合:

公共静态类EntityGraphUpdateHelper
{
公共静态异步值任务UpdateGraphAsync(此DbContext上下文,对象实体)=>
wait context.UpdateGraphAsync(wait context.findentitySync(entity),entity,new HashSet());
私有静态异步值任务UpdateGraphAsync(已访问此DbContext上下文、对象dbEntity、对象实体、哈希集)
{
bool isNew=dbEntity==null;
如果(isNew)dbEntity=entity;
var dbEntry=context.Entry(dbEntity);
如果(是新的)
dbEntry.State=EntityState.Added;
其他的
{
//确保已连接(跟踪)
if(dbEntry.State==EntityState.Detached)
dbEntry.State=EntityState.Unchanged;
//更新基本值
dbEntry.CurrentValues.SetValues(实体);
}
//进程导航
foreach(dbEntry.Navigations中的var navEntry)
{
如果(!visited.Add(navEntry.Metadata.ForeignKey))继续;//已处理
等待navEntry.LoadAsync();
如果(!navEntry.Metadata.IsCollection())
{
//引用类型导航属性
var refValue=navEntry.Metadata.GetGetter().GetClrValue(实体);
navEntry.CurrentValue=refValue==null?null:
wait context.UpdateGraphAsync(navEntry.CurrentValue、refValue、visited);
}
其他的
{
//集合类型导航属性
var accessor=navEntry.Metadata.GetCollectionAccessor();
var items=(IEnumerable)accessor.GetOrCreate(entity,false);
var dbItems=(IEnumerable)accessor.GetOrCreate(dbEntity,false);
var itemType=navEntry.Metadata.GetTargetType();
var keyProperties=itemType.FindPrimaryKey().Properties
.Select((p,i)=>(索引:i,Getter:p.GetGetter(),比较器:p.GetKeyValueComparer())
.ToList();
var keyValues=新对象[keyProperties.Count];
void GetKeyValues(对象sourceItem)
{
foreach(keyProperties中的var p)
keyValues[p.Index]=p.Getter.GetClrValue(sourceItem);
}
对象FindItem(IEnumerable targetCollection,对象sourceItem)
{
GetKeyValues(sourceItem);
foreach(targetCollection中的var targetItem)
{
bool-keyMatch=true;
foreach(keyProperties中的var p)
{