获取本地实体或附加一个新实体

Pet*_*ete 4 c# entity-framework-core

我的实体看起来像这样:

public class User
{
    public int Id {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

我不想在每次获得特定用户时查询数据库,我知道此 Id 存在用户。似乎 Attach 适用于这种情况,但是如果 DbContext 已经在本地存储了此特定用户的实体,它将引发异常。

例如我想做的事情:

var user1 = ctx.GetLocalOrAttach(new User{Id = 1});
var user2 = ctx.GetLocalOrAttach(new User{Id = 2});
AddUserRelation(user1, user2);
Run Code Online (Sandbox Code Playgroud)

有什么解决办法吗?如果不是,检查本地是否存在实体的理想方法是什么。

Iva*_*oev 5

您可以搜索该DbSet<T>.Local属性,但这将是低效的。

IMO 的更好方法是使用FindTracked我的回答中的自定义扩展方法,以在 EntityFrameworkCore 中按 ID 删除加载和卸载的对象

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这类似于 EF CoreFind方法,但如果实体在本地不存在,则不会从数据库加载实体。

您的案例的用法如下:

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);
Run Code Online (Sandbox Code Playgroud)