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

时间:2011-11-08 02:43:12

标签: c# entity-framework

我有这样的方法:

    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,我怎么能改变它来实现这个呢? 我真的需要每次都保存更改吗?

2 个答案:

答案 0 :(得分:2)

你不能“简单地”这样做,问题是默认情况下每个查询总是会命中数据库,因为EF无法知道你查询相同的数据或者数据库中没有潜在的更改打开了连接。

然而,在决定添加新对象之前,您可以检查ChangeTracker / ObjectStateManager以查找现有的已更改对象并查询该对象。

示例:

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

答案 1 :(得分:0)

根据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);
    }