【问题标题】:Is it possible to query Entity Framework before calling DbContext.SaveChanges?是否可以在调用 DbContext.SaveChanges 之前查询实体框架?
【发布时间】:2013-09-25 04:09:58
【问题描述】:

在这个简单的例子中,我有两个实体:事件和地址。我每天晚上都有一个控制台应用程序运行,用于从 XML 源导入事件数据并将其添加到我的数据库中。

当我遍历 XML 事件节点(在实体框架上下文内)时,我检查数据库中是否已经存在具有给定值的地址记录。如果没有,它会添加一条新记录。

using (DemoContext context = new DemoContext())
{
    foreach (XmlNode eventNode in eventsXml.SelectNodes("/Events/Event"))
    {
        Event newEvent = new Event();

        newEvent.Title = **get from XML**

        Address address = context.Addresses.Where(a =>
            a.Title.Equals(title, StringComparison.OrdinalIgnoreCase) &&
            a.Address1.Equals(address1, StringComparison.OrdinalIgnoreCase) &&
            a.Address2.Equals(address2, StringComparison.OrdinalIgnoreCase) &&
            a.City.Equals(city, StringComparison.OrdinalIgnoreCase) &&
            a.State.Equals(state, StringComparison.OrdinalIgnoreCase) &&
            a.ZipCode.Equals(zipCode, StringComparison.OrdinalIgnoreCase)
        ).FirstOrDefault();

        if (address != null)
            newEvent.Location = address;
        else
        {
            newEvent.Location.Title = title;
            newEvent.Location.Address1 = address1;
            newEvent.Location.Address2 = address2;
            newEvent.Location.City = city;
            newEvent.Location.State = state;
            newEvent.Location.ZipCode = zipCode;
        }

        context.Events.Add(newEvent);
    }

    context.SaveChanges();
}

我知道在每个事件之后调用 context.SaveChanges() 会降低性能,所以我想在最后做这一切(或者分批做,但这与这个问题无关)。但是,当我查询 context.Addresses 时,它似乎不知道任何新地址,直到我调用 context.SaveChanges() 所以我得到重复记录。

出于我的目的,在每条记录之后而不是最后保存可能是可以的,但我想知道是否有一个好的、简单的替代方案。

【问题讨论】:

  • 据我了解 context.SaveChanges() 将一一添加新记录(为每条记录单独插入),而不是作为批量操作。在许多情况下,我更喜欢一一进行以分散数据库负载,而不是一次使用 1000 个插入来强调 Sql Server。虽然如果您希望所有插入作为单个事务的一部分,单个 context.SaveChanges() 可能会更好。

标签: c# entity-framework entity-framework-5 dbcontext savechanges


【解决方案1】:

直接针对 DbSet 的查询将始终向数据库发送查询。 Entity Framework 5 中有一个很好的替代方案 – DbSet.Local 属性,可让您使用内存中的数据(由您自己创建或从数据库加载)。

看这篇文章:http://msdn.microsoft.com/en-us/data/jj592872.aspx

【讨论】:

    【解决方案2】:

    当您以触及数据库的方式进行查询时,上下文中新添加的实体不会包含在结果中。 在 EF 4.1 中,您可以通过 DbSet<T>.Local

    获取它们

    见:

    Why do Entity Framework queries not return unsaved entities

    Entity Framework: Re-finding objects recently added to context

    【讨论】:

    • 谢谢,DbSet.Local 似乎很有希望。经过快速测试,似乎消除了在同一批次中添加重复项的问题,但如果数据库中已经保存了一条记录,则不能防止重复。有什么我可以查询的,或者我应该简单地如果 context.Addresses.Local 没有返回结果,则对 context.Addresses 进行单独查询?
    • @JKasper11 我知道哪些查询上下文以及必要时 DB 的唯一方法是 Find(key)。如果提供键的实体存在于上下文中,则返回,否则查询数据库获取。
    • 值得注意的是,local 不仅保存了添加的对象,还保存了删除和修改的对象..
    • @vishalsharma,Microsoft 数据开发中心不同意您的观点。他们说已删除的实体未包含在本地集合中:msdn.microsoft.com/en-us/data/jj592872.aspx.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 2014-02-21
    • 2014-12-27
    • 1970-01-01
    相关资源
    最近更新 更多