我的实体看起来像这样:
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);
有什么解决方案吗?如果不是,那么检查实体是否存在于本地的理想方法。
答案 0 :(得分:2)
您可以搜索DbSet<T>.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 Core 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);
答案 1 :(得分:0)
我多年来一直使用EF而且我从未使用过附加机制,它通常只会让你陷入麻烦。
如果我查看代码,我猜你想在2个用户记录之间创建关系,但是你想通过不查询两个用户记录来优化性能。 (就我个人而言,我不关心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);
请注意,在我的上一个代码示例中,我没有查询两个用户对象,但EF将使用2个有效的外键创建UserRelation记录。