代码之家  ›  专栏  ›  技术社区  ›  Pete

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

  •  1
  • Pete  · 技术社区  · 7 年前

    我的实体看起来是这样的:

    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);
    

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

    2 回复  |  直到 7 年前
        1
  •  2
  •   Ivan Stoev    7 年前

    你可以搜索 DbSet<T>.Local 但那将是低效的。

    更好的方法是使用 FindTracked 从我的答案到自定义扩展方法 Delete loaded and unloaded objects by ID in EntityFrameworkCore

    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);
    
        2
  •  0
  •   Kristof    7 年前

    我使用ef已经很多年了,我从来没有使用过连接机制,它通常只会给你带来麻烦。
    如果我查看代码,我猜您希望在两个用户记录之间创建关系,但希望通过不查询两个用户记录来优化性能。(就我个人而言,我不在乎获取用户对象所需的20毫秒开销,但我想这可能很重要)。

    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将使用两个有效外键创建userrelation记录。