如何设计工作单元以支持批量操作并提供更高的性能?

我有两个不同的工作单元:一个基于ADO.NET ,主要调用存储过程( uowADO ),另一个使用Entity Framework 6uowEF ),最近为了支持Oracle数据库而添加,因此我没有必要重写所有SP(我的知识在那里有限)。

因此,在对数据库执行操作时,业务层只加载其中一个(基于配置)(但我不能并行使用它们,因为uowADO不支持Oracle)

添加新的uowEF我注意到了大的性能问题,当然主要是批量操作。

基本上我现在只有当前IUnitOfWork上的CommitRollback方法……非常接近本文的建议。

所以,我正在考虑重做这个工作单元。 例如,我读到有时在涉及批量操作时禁用dbContext.Configuration.AutoDetectChangesEnabled ,以及其他有关EF的优化提示可能有所帮助。

不幸的是,我不确定如何设计这样的工作单元以使其通用,以便我可以在BL和数据访问层的所有情况下使用它: ADO.NETEF

有什么想法,建议和良好的链接吗?

没有明确的答案。 它始终是灵活性和性能之间的折衷。 所有这些模式(存储库,工作单元)都有利于灵活性,但不是性能,因为具体实现通常需要进行一些调整以提供最大性能,并且这些调整可能(实际上它们不会)与通用接口兼容。 您可以调整界面,但它可能无法与其他实现一起使用。 所有这些ORM都非常不同,实现通用存储库/ UOF接口以支持所有这些ORM非常困难(几乎不可能),特别是如果你有ADO(低级ORM,实际上很难称之为ORM)和EF(高水平的ORM)。 将AutoDetectChangesEnabled设置为false只是使用EF可以执行的操作的一小部分。 要从中获得更多性能,您还必须以特定方式实现enities(添加一些属性,一些属性)。 如果我们看一下Linq2Sql(另一个ORM),它需要编译查询,所以,忘记这样的方法:

 T Single(Expression> predicate); 

在您的存储库中。 我只是谈论关系数据库的存储库。 NoSql数据库的存储库怎么样? 基于完全不同的数据源的存储库怎么样? 是的,可以提供具有通用逻辑的通用接口,但对于某些数据源来说它会非常慢。 如果您真的想要实现通用解决方案并获得最大性能,那么UOF的存储库应该具有非常具体的界面,例如:

 IEnumerable GetStudentsByName(srting name) void InsertStudents(IEnumerable students) 

其中T – 不应依赖具体存储库实现的业务级实体。 存储库应负责将T转换为可实现对其实现访问的ORM的实体。 但请记住,解决方案太复杂且难以支持。

如果我是你,我会选择一个最符合我要求的主要ORM,并在这个ORM周围设计存储库以获得最大的性能。 但是,我将保持界面足够灵活,以便至少可以实现对其他数据源或ORM的缓慢(但有效)访问。

不幸的是,我不确定如何设计这样的工作单元以使其通用,以便我可以在BL和数据访问层的所有情况下使用它:ADO.NET和EF。

首先要意识到EF无法访问数据库。 它依赖于ADO.NET。 最后,它使用命令,数据引导器等来完成低级工作。

以这样的方式进行设置是非常简单的,您可以在EF上下文中提取连接,然后直接使用ADO.NET。

由于EF无论如何都无法以高效率进行高效的批量操作 – 您无论如何都必须依赖ADO.NET。 从SQL的角度来看,EF本身就是如何处理大容量数据库的完美反例。 它每行使用一次更新/插入 – 尽管(例如,甚至忽略SqlBulkCopy)它可以为大多数数据库发出一个多行,因为语法完全允许。

如上所述:当您喜欢阅读样本文档时,获取基础连接非常简单。 这是我用于批量插入的代码。 ObjectBulkCopy类稍微复杂一些,但是在这里可以看到如何获取数据库连接:

 public static void BulkInsert(this Repository repository, IEnumerable objects) where T : class { var bulkCopy = new ObjectBulkCopy(); var connection = (SqlConnection) repository.Database.Connection; bulkCopy.Insert (objects, connection); } 

严重琐碎 – 它存在于任何存储库中作为属性,准备投射。