繁体   English   中英

从Entity Framework 6异常行为中调用存储过程

[英]Calling stored procedure from Entity Framework 6 abnormal behavior

我有一个存储过程需要花费一些时间(〜60秒)才能执行,我使用EF这样调用它:

context.Database.ExecuteSqlCommand(
    "myStoredProcedure @param1",
    new SqlParameter("param1", param1)
);

存储过程由两部分组成:

  1. 在表tblSomeTable插入新行,然后

  2. 从不包含tblSomeTable多个表中计算一些信息。

第二项操作很耗时。 当我从SSMS执行此存储过程时,我可以看到在过程完成执行之前将新行添加到tblSomeTable 这是正常现象,但是,当我使用上述代码运行相同的确切过程时,则tblSomeTable的新行是仅在过程完成执行时添加。

另外,在过程运行时,我无法从tblSomeTable上查询到tblSomeTable (都来自EF和SSMS),因为我假设tblSomeTabletblSomeTable放置了锁,直到过程完成为止。 为什么会这样呢?

这是在SQL Server 2008上。

根据文档

默认情况下,从EF6 Database.ExecuteSqlCommand()开始,会将命令包装在事务中(如果尚不存在)

因此,直到SSMS结束,您都不会看到任何更改。

为什么会这样呢?

这不是异常行为。 您看不到插入到tblSomeTable的数据,因为在调用context.Database.ExecuteSqlCommand时,将创建一个新的SQL Server事务。 这就是文档所说的:

如果不存在本地事务或环境事务,则将使用新事务执行命令。

EF用于事务的默认隔离级别是最高的,即Serializable 这意味着在未提交事务时,在事务外部执行的任何SQL查询都看不到当前插入到tblSomeTable任何数据。 context.Database.ExecuteSqlCommand未完成其工作时,该数据对于在SSMS中执行的查询不可见。

您可以更改隔离级别,但是如果这样做的唯一目的是在调用context.Database.ExecuteSqlCommand时检查存储过程在做什么,则我不建议您这样做。

@David Browne之后编辑 -微软评论:

EF的默认隔离级别是READ COMMITTED,而不是如上所述的SERIALIZABLE 无法读取未提交的数据仍然适用。

文档中的定义:

指定语句无法读取已被其他事务修改但未提交的数据。 这样可以防止脏读。 数据可以被当前事务中各个语句之间的其他事务更改,从而导致不可重复的读取或幻象数据。 此选项是SQL Server的默认选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM