网站首页 全球最实用的IT互联网站!

人工智能P2P分享Wind搜索发布信息网站地图标签大全

当前位置:诺佳网 > 软件工程 > 后端开发 > .Net >

EFCore如何更改跟踪状态 - Rick Carter - 博客园

时间:2024-11-20 15:52

人气:

作者:admin

标签:

导读:这里简单介绍下几种修改实体或者导航的跟踪状态。 1. 直接修改实体 对已在DbContext中跟踪的实体,直接操作,如给字段赋值、给导航属性赋值或者添加删除等 对未在DbContext中跟踪的实...

这里简单介绍下几种修改实体或者导航的跟踪状态。

对已在DbContext中跟踪的实体,直接操作,如给字段赋值、给导航属性赋值或者添加删除等
对未在DbContext中跟踪的实体,调用DbContext的Add、Update、Remove等方法,对已跟踪的实体也有效
需要注意所有添加的实体都需要调用DbContext.Add方法

这个很简单,关键的是如何获得InternalEntityEntry,方法是调用IStateManager.TryGetEntry方法返回获得,该方法多个重载,主要都是传实体或者主键。

Type type = ....// 实体类型
DbContext ctx=...
var entityType = ctx.Model.FindEntityType(type);
var key = entityType.FindPrimaryKey();
var internalEntityEntry = ((IDbContextDependencies)ctx).StateManager.TryGetEntry(key,主键值);
((IDbContextDependencies)ctx).StateManager.ChangingState(internalEntityEntry,EntityState.Modified);

传主键同样可以获得隐式定义的ISkipNavigation的InternalEntityEntry,请看5中示例。

INavigationBase.GetCollectionAccessor()返回IClrCollectionAccessor类型,使用它的Add和Remove方法操作集合,但是这里只针对已经在DbContext跟踪的才有效果,否则请参考5中的做法。

对于已经跟踪的实体或导航,还可以NavigationCollectionChanged方法更改添加或者删除,主要是针对集合导航属性。

Object entity=...//实体对象,假设它有个集合导航属性:Data
var navigationEntry = ctx.Entry(entity).Navigation("Data");
var obj = entity.Data.First();//假设不为空
//将集合导航属性Data中obj修改成添加状态(EntityState.Added)
((IDbContextDependencies)ctx).StateManager.InternalEntityEntryNotifier.NavigationCollectionChanged(ctx.Entry(entity).GetInfrastructure(), navigationEntry.Metadata, new[] { obj }, Array.Empty<object>());
//将集合导航属性Data中obj修改成删除状态(EntityState.Deleted)
((IDbContextDependencies)ctx).StateManager.InternalEntityEntryNotifier.NavigationCollectionChanged(ctx.Entry(entity).GetInfrastructure(), navigationEntry.Metadata, Array.Empty<object>(), new[] { obj });

在第4点中,对于ISkipNavigation,无法修改导航的状态为EntityState.Unchanged,那么这里可以这么做。

if (navigationEntry.Metadata is ISkipNavigation skipNavigation)
{
    var targetEntry = ((IDbContextDependencies)ctx).StateManager.GetOrCreateEntry(obj, navigationEntry.Metadata.TargetEntityType);
    var key = skipNavigation.JoinEntityType.FindPrimaryKey();
    var a = ctx.Entry(entity).GetInfrastructure()[skipNavigation.ForeignKey.PrincipalKey.Properties[0]];
    var b = targetEntry[skipNavigation.Inverse.ForeignKey.PrincipalKey.Properties[0]];
    var joinEntry = ((IDbContextDependencies)ctx).StateManager.TryGetEntry(key, new[] { a, b });
    joinEntry.SetEntityState(EntityState.Unchanged);//也可以用IStateManager.ChangingState
}

如果ISkipNavigation还是未跟踪的,那么上面的代码joinEntry获得的是null,可以在上面代码之前加这两行就可以了。

((IDbContextDependencies)ctx).StateManager.CompleteAttachGraph()
((IDbContextDependencies)ctx).StateManager.InternalEntityEntryNotifier.NavigationCollectionChanged(ctx.Entry(entity).GetInfrastructure(), navigationEntry.Metadata, new[] { obj }, Array.Empty<object>());

作者:Rick Carter
出处:http://pains.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信