【问题标题】:Inserting and updating disconnected entities in EF code first首先在 EF 代码中插入和更新断开连接的实体
【发布时间】:2015-03-17 00:01:58
【问题描述】:

我正在从许多不同的来源(例如 XML 和 Web 服务)检索有关书籍的数据,然后我使用 EF Code First 6 通过通用存储库和显然是 DbContext 将这些数据存储在数据库中。

问题是性能很差。

我的模型中有以下(虚构但类似的)POCO

public class Book
{
    public int Id {get; set;}
    public string Title {get; set;}
}

还有

public class BookDataSource
{
    public int Id {get; set;}
    public virtual List<Book> Books {get; set;};
}

所以我从某个来源检索图书数据并构造上述图书对象。

然后我需要检查这本书是否已经存在于数据库中,如果存在则更新它,如果不存在则插入它。然后,我还需要删除数据源中不再存在的所有书籍。

//以下方法以要更新的数据源(类型:IBookDataSource)为参数

public string UpdateBooks(BookDatasource dataSource)
{
    string successMessage = "";

    //Disconnected entities
    List<Book> retreivedBooks= dataSource.RetreiveBooks();

    foreach (Book retreivedBook in retreivedBooks)
    {
        //Check if the dataSource already contains a book (based on title)
        Book localBook =
            dataSource.Books.SingleOrDefault(
                b => b.Title== retreivedBook.Title);

        if (localBook ==null)
        {
            //Insert a new one
            _unitOfWork.BookRepository.Insert(retreivedBook);
        }
        else
        {
            //Update existing
            localBook.Title= retreivedPortalMerchant.PortalsMerchantName;
            _unitOfWork.PortalMerchantRepository.Update(localPortalMerchant);
        }
    }

    //Soft delete any existing ones that no longer exist in the received data
    foreach (Book existingBook in dataSource.Books)
    {
        if (  !retreivedBooks.Exists(
                b => m.Title == existingBook.Title))
        {
            existingBook.Deleted = true;
            _unitOfWork.PortalMerchantRepository.Update(existingBook);
        }
    }
}

但是性能很差。有时从数据源中检索到 25000 本书,我必须执行两个 for 循环。 ForEach 检索的书,检查数据库中是否存在相应的插入/更新。另一个循环所有现有书籍并检查它是否不再存在于数据源中并软删除。

有没有更好的方法来附加实体并监控它们的状态。在上面的示例中,我认为我每次都在查询上下文而不是数据库,所以为什么性能如此糟糕。我应该恢复到 T-SQL 吗?

【问题讨论】:

    标签: entity-framework ef-code-first


    【解决方案1】:

    对于插入-更新-删除断开连接实体的正确算法,您可以查看“第 4 章。使用断开连接的实体,包括“N-Tier Applications”的“Programming Entity Framework: DbContext by Julia Lerman, Rowan Miller”一书。

    还在this SO answer 中解释了一些提高 EF 性能的方法。答案是批量插入,但它也可能适用于您的场景。

    【讨论】:

      【解决方案2】:

      最快的方法是使用bulk insert extension

      这是maxlegodescription

      它使用 SqlBulkCopy 和自定义数据读取器来获得最大性能。因此,它比使用常规插入或 AddRange EntityFramework.BulkInsert vs EF AddRange 快 20 倍以上

      context.BulkInsert(hugeAmountOfEntities);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-06
        相关资源
        最近更新 更多