我的实体看起来像这样:
public class User
{
public int Id {get; set;}
}
我不想在每次获得特定用户时都查询数据库,因为我知道此Id存在用户。似乎Attach适用于这种情况,但是如果DbContext已经在本地存储了这个特定用户的实体,它将抛出一个异常。
举个我想做的例子:
var user1 = ctx.GetLocalOrAttach(new User{Id = 1});
var user2 = ctx.GetLocalOrAttach(new User{Id = 2});
AddUserRelation(user1, user2);
对此有什么解决方案吗?如果不是,那么检查实体是否在本地存在的理想方法是什么。
发布于 2018-06-08 04:13:07
您可以搜索DbSet.Local
属性,但效率会很低。
IMO的一个更好的方法是使用我对Delete loaded and unloaded objects by ID in EntityFrameworkCore的回答中的FindTracked
自定义扩展方法
using Microsoft.EntityFrameworkCore.Internal;
namespace Microsoft.EntityFrameworkCore
{
public static partial class CustomExtensions
{
public static TEntity FindTracked<TEntity>(this DbContext context, params object[] keyValues)
where TEntity : class
{
var entityType = context.Model.FindEntityType(typeof(TEntity));
var key = entityType.FindPrimaryKey();
var stateManager = context.GetDependencies().StateManager;
var entry = stateManager.TryGetEntry(key, keyValues);
return entry?.Entity as TEntity;
}
}
}
这类似于EF核心Find
方法,但如果实体在本地不存在,则不会从数据库加载该实体。
您的案例的用法如下:
var user1 = ctx.FindTracked(1) ?? ctx.Attach(new User { Id = 1 }).Entity;
var user2 = ctx.FindTracked(2) ?? ctx.Attach(new User { Id = 2 }).Entity;
AddUserRelation(user1, user2);
发布于 2018-06-08 03:23:46
我已经使用EF很多年了,但我从来没有使用过attach机制,它通常只会给你带来麻烦。
如果我看一下代码,我猜您希望在两个用户记录之间创建一个关系,但您希望通过不同时查询两个用户记录来优化性能。(就我个人而言,我并不关心获取用户对象所花费的20ms开销,但我想这可能很重要)。
EF允许您在不加载外部实体的情况下使用外键创建记录。
因此,您可以将以下代码从:
var user1 = context.Users.Find(1);
var user2 = context.Users.Find(2);
var userRelation = new UserRelation();
userRelation.FromUser = user1;
userRelation.ToUser = user2;
context.UserRelations.Add(userRelation);
至:
var userRelation = new UserRelation();
userRelation.FromUserId = 1;
userRelation.ToUserId = 2;
context.UserRelations.Add(userRelation);
请注意,在我的上一个代码示例中,我没有同时查询两个user对象,但是EF将使用2个有效的外键创建UserRelation记录。
https://stackoverflow.com/questions/50748522
复制相似问题