我最近加入了我团队的一个项目。他们使用ASP.NET MVC和MS SQL以及Entity Framework作为ORM。
我注意到EF中使用的每个存储过程在存储过程定义开始时都有这个共同的行
IF(0=1) SET FMTONLY OFF
我认为这是一个非常奇怪的情况所以我在谷歌上搜索了一下,并向我的同事询问了这件事。他们说,当EF映射存储过程时,它将所有参数发送为null并跳过所有if循环。因此,它也会跳过IF(0=1)
条件,然后SET FMTONLY OFF
在搜索SET FMTONLY OFF
MSDN时,说
仅返回客户端的元数据。可以用来测试格式 没有实际运行查询的响应。
当你不控制数据库时会出现问题,你必须不断告诉DBA添加它并反复向他们解释为什么首先需要它。
我仍然不清楚为什么要这样做。如果有人能够详细解释这一点,或者引导我找到一些链接,这个链接涵盖了这个主题对我来说意味着世界。
答案 0 :(得分:3)
我暂时这样做是为了能够使用设计器映射函数来代表代码中的存储过程。问题是设计者默认将null传递给过程来确定模式。如果传递null,那么有时候存储过程会执行验证并抛出异常等问题。你描述的设置可以解决这个问题,因为它返回的是meta而不是实际的数据。
答案 1 :(得分:3)
我认为原因类似于从SSRS运行的存储过程。总之,当FMTONLY处于活动状态时,您的存储过程可能会有一些意外的结果。因此明确将其关闭的原因。有关详细信息,请阅读Dealing with the Evil of FMTONLY from SSRS
答案 2 :(得分:2)
IF(0=1) SET FMTONLY OFF
在实体框架读入的存储过程中随便做似乎是一件冒险的事。
实体框架是此标志的唯一来源,被设置为我所知道的标准做法(可能是其他ORM可能会使用它)。
目的(据我所知)是提供一种获取过程返回模式而不实际触及任何数据的方法。 (一些您不想执行的存储过程只是为了更新一个orm的对象模型。
所以除非你有一个表计算你的EF模型更新的次数(这在学术上可能很有趣)
有关其他信息,请参阅 Stored procedure returns int instead of result set
使用ftmonly与实体框架(在我看来)最安全的方法是.. 在以下情况下
在复杂程序的开头执行以下操作
if(0=1) -- if FMTONLY is on this if condition is ignored
begin
-- this loop will only be entered if fmtonly is on (ie EF schema read)
select
column1
,column2
...
,columnX
from whateverA
cross join whateverB
...
cross join whateverQ
-- joins don't matter but they might make it easier to get the column definitions
-- and names you desire. the important thing here is generating the proper
-- return schema... which is as complex as whatever you are trying to return
where 1=0
set FMTONLY off -- do this so that you can now force an early return since EF
-- usually only wants the first data set schema... other orms might
-- do something different
return -- this will be ignored if FMTONLY is still on
end
答案 3 :(得分:0)
据我了解的情况,当更新EDMX时,要为存储过程返回结果集而不是INT,SET FMTONLY OFF会有所帮助。
例如在存储过程中写入“ SELECT * FROM @tempTable”,为此存储过程更新edmx时,在Context.cs文件中为此存储过程生成的类型可以是- 公共虚拟int SPName。
理想情况下,它必须是: 公共虚拟ObjectResult SPName
要获得上述结果,我们必须使用SET FMTONLY OFF。
我们避免将返回类型设为INT并将其设为结果集的类型: 链接以了解使用方法:http://www.sandeepknarware.in/?p=247