实体框架,如何避免这个问题

本文关键字:问题 何避免 框架 实体 | 更新日期: 2023-09-27 18:13:41

我有一个这样的方法:

    public FbUser FindUserByGraphOrInsert(dynamic json, bool commit = false)
    {
        string graphId = json.id;
        EntityDataModelContext context = DataContext.GetDataContext();
        FbUser user = context.FbUsers.FirstOrDefault(u => u.FbGraphId == graphId);
        if (user == null)
        {
            user = new FbUser();
            user.FbGraphId = json.id;
            user.FbUsername = StringExtensions.UnicodeDecode(json.name);
            context.FbUsers.AddObject(user);
            if (commit)
                context.SaveChanges();
        }
        return user;
    }

我在一个循环中反复调用这个方法(比如80次以上),使用commit = false

问题是,我希望这个方法让我知道用户是否已经在上下文中,但情况似乎并非如此。

结果是,当我最终保存更改时,我得到一个包含80个用户的列表,其中27个是不同的。

我希望这个方法返回那27,我怎么能改变它来实现这一点?
我真的需要每次都保存更改吗?

实体框架,如何避免这个问题

您不能"简单地"这样做,问题是每个查询默认情况下总是会命中数据库,因为EF无法知道您要么查询相同的数据,要么自打开连接以来数据库中没有底层更改。

但是,您可以检查ChangeTracker/ObjectStateManager是否存在已更改的对象,并在决定添加新对象之前查询该对象。

示例:

var addedObjects = context.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added);
var equalObjects = addedObjects.OfType<MyEntity>().Where(x => x.Name == newObject.Name);

根据Polity的回答,我实现了以下扩展方法,并成功了。

    public static IEnumerable<T> IncludeUnsaved<T>(this ObjectSet<T> set) where T : class
    {
        var addedObjects = set.Context.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added);
        var equalObjects = addedObjects.Select(e => e.Entity).OfType<T>();
        return equalObjects.Concat(set);
    }