使用 DbContext.Database.Connection.CreateCommand 的并发问题
我将尝试解释这一点,但不会真正破坏我正在开发的应用程序的整个设计。因为谁在乎这个呢。如果相关的话,我可以提供更多细节,但我想我涵盖了下面的所有内容。
主要问题:
我有一些需要定期执行的存储过程。我从数据库表中获取过程名称,因此我的应用程序没有关于它们的硬编码知识。这是设计使然。我目前正在使用实体框架来进行所有数据访问。
我的应用程序是多线程的——我获取需要运行的所有进程,然后迭代每个进程,从我的配置表中获取其属性,并将其排队以在应用程序线程池中的单独线程上运行。
我正在使用 Database.Connection.CreateCommand 方法并执行过程——将数据拉入数据表。当我只执行一个过程时,这种方法效果很好,但当
问题是我遇到并发问题时。我得到的具体异常是
System.Data.SqlClient.SqlException: 不允许新交易,因为 还有其他线程在运行 会议。
我假设这是因为我试图执行我的过程,同时还通过实体框架访问另一个过程的属性。
我想到的潜在解决方案/思路:
如果我编写一个具有我需要的字段的模型类,我可以使用 DbContext.Database.SqlQuery 方法让它正常工作。但是如果我根本不想编写模型类怎么办?有没有办法可以做到这一点并让实体框架实际处理查询?
在开始执行任何过程之前,我可以获取所有属性。那可能会很好用。如果我将属性定义为模型上的 ICollections,告诉我要运行什么过程,有没有办法在我从数据库中选择所述模型时强制它们加载,而不是在稍后迭代它们来读取它们时加载?
I'm gonna try to explain this without actually mucking through the whole design of the application I'm working on. Cause who cares about that. If it's pertinent, I can give more detail but I think I cover everything below.
main problem:
I've got a few stored procedures that I need to execute periodically. I get the proc names from a database table, so my application has no hard coded knowledge of them. This is by design. I'm currently using the entity framework to do all my data access.
My application is multi threaded -- I grab all the procs that I need to run, then iterate through each one, grab its properties from my configuration tables and queue it up to run on a separate thread in the app's thread pool.
I'm using the Database.Connection.CreateCommand method and executing the procs -- pulling the data into a data table. This works out well when I'm only executing one proc, but when
Problem is that I run into concurrency issues. The specific exception I'm getting is
System.Data.SqlClient.SqlException:
New transaction is not allowed because
there are other threads running in the
session.
I'm assuming this is because I'm trying to execute my procedure while also accessing the properties of another procedure via the entity framework.
Potential solutions / trains of thought that occur to me:
I can get this to work just fine using the DbContext.Database.SqlQuery method if I write a model class that has the fields I need. But what if I don't want to write a model class at all? Is there a way I can do this and let the entity framework actually handle the query?
I could grab all of the properties before i start executing any procs. That would probably work fine. If I define my properties as ICollections on the model that tells me what procedure to run, is there a way to force them to load when I select said model from the DB instead of when I iterate through them later to read them?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里的主要问题是您正在通过多个线程使用单个数据库连接(
Database.Connection
为所有CreateCommand
调用返回相同的实例),并且您试图定义多个交易同时进行。这种情况的解决方案只有一个 - 每个存储过程/线程使用一个新连接。您应该能够通过调用Database.Connection.ConnectionString 来获取连接字符串。Database.SqlQuery
始终需要类型来加载数据。实体框架通过将结果集映射到类型来简化数据访问。如果您没有类型,则无法利用 EF 的任何优势。Include
方法执行。您只需说出必须立即加载映射实体上的哪些导航属性。The main problem here is that you are using single database connection (
Database.Connection
returns the same instance for all yourCreateCommand
calls) by multiple threads and you are trying to define multiple transactions concurrently. The solution for this scenario is only one - use a new connection per stored procedure / thread. You should be able to get connection string by callingDatabase.Connection.ConnectionString
.Database.SqlQuery
always require type for loading data. Entity framework make easier data access by mapping result sets to types. If you don't have a type you can't take any advantage of EF.Include
method used in the query. You will just say which navigation properties on the mapped entity must be loaded immediately.