使用实体框架

时间:2015-05-26 22:53:49

标签: c# entity-framework nopcommerce

我需要向Nop Commerce导入大约150,000种带有类别,制造商,图像和属性的产品。我写了一个基于Nop.Services.ExportImport.ImportManager的插件。导入的产品越多,导入过程运行的速度就越慢。前100个产品将在1.5分钟内导入。大约2500种产品进口另外100种产品需要15到20分钟。一次导入超过2500个产品会导致内存不足异常。在2500停止然后再进行第二次导入后,事情甚至会变慢。

以下是插件使用的过程:

  1. 创建新的产品实体,填充详细信息,然后使用Nop.Services.Catalog.ProductService.InsertProduct插入产品。有必要使用ProductService,因为我们需要Product.ID的值来将子对象添加到产品中。

  2. 首先搜索制造商是否存在,添加产品制造商。如果找不到制造商,则创建制造商并使用ManufacturerService添加。然后添加ProductManufactuer实体以将产品分配给制造商。此实体将添加到列表对象中。

  3. 对类别,规范属性,URL记录和产品标签执行相同的例程。

  4. 下载第一张图片并使用PictureService添加。 PictureService将Picture实体插入数据库,然后将图像保存到images目录。然后创建一个ProductPicture实体并将其添加到列表中。

  5. 每100个产品,我使用SQLBulkCopy / EFBulkInsert将ProductManufacturers,ProductCategories,ProductImages等列表插入数据库。然后我清除列表并重新开始。

  6. 因此,在整个过程中,我们使用Entity Framework逐一将产品,类别,制造商,产品标签和规格属性添加到数据库中。这是必要的,因为我们需要获取这些项的ID,以便我们可以通过将记录插入映射表来将它们分配给产品。添加到映射表的记录可以添加到列表中,然后使用SQLBulkCopy / EFBulkInsert批量插入到数据库中。

    每次添加产品及其属性时,整个过程都会越来越慢。随着时间的推移,它似乎也会使用越来越多的内存。我不知道下一步该做什么。

    我不确定Entity Framework是否导致问题。我已经读过,随着时间的推移,实体框架倾向于使用越来越多的内存,并且每隔一段时间重置一次DBContext是个好主意。问题是Nop通过它在Nop.Data中的EFRepository Layer来管理DBContext。

    使用EFBulkInsert / SQLBulkCopy将产品属性映射记录添加到数据库似乎可以加快速度。我想过可能会经历并使用它来首先插入所有产品,然后再回过头来导入属性。我仍然会遇到无法将Picture实体批量导入数据库的问题,因为我需要PictureID和ProductID来将图片与产品相关联。

    我还考虑过使用ADO.NET和存储过程来逐个插入,但我不确定这是否会改善。有没有人有什么建议?

2 个答案:

答案 0 :(得分:2)

我是EFUtilities https://github.com/MikaelEliasson/EntityFramework.Utilities的作者,其中包括批量插入等。对于下一个版本,它将能够从批量插入返回商店生成的id。

现在这个有效但没有发布。我期待在本周末或下周末发布。同时你可以在https://github.com/MikaelEliasson/EntityFramework.Utilities/blob/release20/EntityFramework.Utilities/EntityFramework.Utilities/SqlQueryProvider.cs#L56找到它的代码,如果你下载并构建了release20分支,你应该可以使用它。

以下是测试,显示如何启用Id返回(默认情况下它稍慢,因此禁用)https://github.com/MikaelEliasson/EntityFramework.Utilities/blob/release20/EntityFramework.Utilities/Tests/InsertTests.cs#L125

using (var db = Context.Sql())
{
     EFBatchOperation.For(db, db.BlogPosts).InsertAll(list, new BulkSettings
            {
                ReturnIdsOnInsert = true,
            });
}

答案 1 :(得分:1)

我已经告诉你你现在面对的是什么。但我们有大约30K的产品和图像。我确实尝试过EF,SSIS和Plain SQL Scripts。

我的偏好是,

  1. 纯SQL脚本。
  2. SSIS。
  3. 实体框架导入。
  4. 我曾经把普通的SQL脚本写成一个文件来恢复空白NopCommerce DB的副本,从源数据库读取数据并填充表格。

    使用Plain SQL,

    1. 它很快,但很难在第一时间发展。你需要按表构建数据导入表。
    2. 使用打印命令轻松调试。
    3. 如果您在导入后发现任何错误,则可以快速修复并重新运行。
    4. 这方面的缺点是,您应该知道nopcommerce中表格的所有关系。基于你的问题,我可以看到你对它有很好的理解。

      使用SSIS,

      1. 它很快。
      2. 快速发展。
      3. 如果您在导入后发现任何错误,则可以快速修复并重新运行。
      4. 使用EF,

        你的问题全部说明了。

        现在,如果您需要在定期时间内导入数据,则编写存储过程并使用ADO.NET调用存储过程进行导入。这将是导入/更新的最快方式。每次导入完成后,不要忘记在nop admin中调用clear cache。

        资料来源:我在基于nopcommerce的电子商务平台工作超过2年。