使用DbContext.Database.Connection.CreateCommand的并发问题

时间:2011-04-30 21:30:05

标签: .net entity-framework sql-server-2008 concurrency entity-framework-4.1

我将尝试解释这一点,而不是真正搞砸我正在处理的应用程序的整个设计。因为谁在乎这一点。如果它是相关的,我可以提供更多细节但我认为我涵盖了以下所有内容。

主要问题

我有一些我需要定期执行的存储过程。我从数据库表中获取了proc名称,因此我的应用程序没有硬编码知识。这是设计的。我目前正在使用实体框架来进行所有数据访问。

我的应用程序是多线程的 - 我抓住了我需要运行的所有过程,然后遍历每个过程,从我的配置表中获取其属性并将其排队以在应用程序的线程池中的单独线程上运行。

我正在使用Database.Connection.CreateCommand方法并执行过程 - 将数据拉入数据表。当我只执行一个proc时,这很好用,但是当

问题是我遇到了并发问题。我得到的具体例外是

  

System.Data.SqlClient.SqlException:   不允许新的交易,因为   还有其他线程在运行   会话。

我假设这是因为我正在尝试执行我的程序,同时还通过实体框架访问另一个程序的属性。


我遇到的潜在解决方案/思路

  • 如果我编写一个包含我需要的字段的模型类,我可以使用DbContext.Database.SqlQuery方法正常工作。但是,如果我根本不想写一个模型类呢?有没有办法可以做到这一点让实体框架实际处理查询?

  • 在开始执行任何过程之前,我可以抓住所有属性。这可能会很好。如果我在模型上将我的属性定义为ICollections,告诉我要运行什么过程,当我从DB中选择所述模型时,有没有办法强制它们加载,而不是在我稍后迭代它们来读取它们时?

1 个答案:

答案 0 :(得分:4)

这里的主要问题是您使用单个数据库连接(Database.Connection为多个线程返回所有CreateCommand调用的相同实例)并且您尝试同时定义多个事务。此方案的解决方案只有一个 - 每个存储过程/线程使用一个新连接。您应该可以通过调用Database.Connection.ConnectionString来获取连接字符串。

  • 除非在每个帖子中运行新的上下文,否则您的第一个解决方案将无法解决问题。
  • Database.SqlQuery始终需要输入数据的类型。实体框架通过将结果集映射到类型来更轻松地访问数据。如果您没有类型,则无法利用EF。
  • 立即加载关系的方式称为预先加载,并由查询中使用的Include方法执行。您只需说明必须立即加载映射实体上的哪些导航属性。