【发布时间】:2019-11-12 23:42:09
【问题描述】:
我在实体框架中有一个多对多的关系,在映射中,EF 允许我们指定键和表名。在下面的示例中,一个用户可以拥有多个设备日志,而一个设备日志可以属于多个用户。
HasMany(e => e.DeviceLogs)
.WithMany(e => e.Users)
.Map(m => m.ToTable("UserDeviceLog")
.MapLeftKey("UserId")
.MapRightKey("LogId")
);
现在,当我尝试从用户中删除设备日志时:
using (var context = new MyDbContext())
{
var user = context.Users.Find(userId);
var deviceLog = context.DeviceLogs.Find(logId);
user.DeviceLogs.Remove(deviceLog);
context.SaveChanges();
}
我知道我要从表“UserDeviceLog”中删除一个关系,而不是设备日志本身。 上面的代码 sn-p 有效,但问题是 Entity Framework 将加载所有设备日志,然后从表 UserDeviceLog 中删除一条记录。
执行上述逻辑时,我的应用程序被阻止。从截图中可以看到,两条 SQL 语句之间大约有 23 秒。对于指定的用户,它有大约 20K 条记录(第一条 SQL 语句)。我猜它是通过将这 20K 记录从 SQL Server 传输到我的应用程序而采取的,这导致我的应用程序非常慢。
虽然这是不必要的,但我该如何避免呢?我不想写一个普通的SQL删除语句,我更喜欢EF方式的解决方案。
谢谢!
【问题讨论】:
-
使用标记为“重复”的帖子接受的答案中的
ChangeRelationshipState助手。例如如果您将其设为公共扩展方法,而不是user.DeviceLogs.Remove(deviceLog);,您将使用context.ChangeRelationshipState(user, deviceLog, e => e.DeviceLogs, EntityState.Deleted);(或等效的context.ChangeRelationshipState(deviceLog, user, e => e.Users, EntityState.Deleted);),这将删除链接而不会延迟加载集合。 -
@Ivan Stoev,谢谢!这个对我有用。顺便说一句,要删除所有链接而不延迟加载集合吗?
-
最低要求是从 db 中获取带有 id 的列表,然后禁用延迟加载并使用状态管理器和伪造的“存根”实体实例进行一些技巧。换句话说,可能,但不是自然和棘手的。
标签: entity-framework navigation-properties