为什么在使用Entity Framework时我们必须在存储过程中写SET FMTONLY OFF

Yas*_*ser 7 sql-server entity-framework

我最近加入了我团队的一个项目.他们使用ASP.NET MVC和MS SQL以及Entity Framework作为ORM.

我注意到EF中使用的每个存储过程在存储过程定义开始时都有这个公共行

IF(0=1) SET FMTONLY OFF
Run Code Online (Sandbox Code Playgroud)

我认为这是一个非常奇怪的情况,所以我搜索了一下它并且还向我的同事询问了它.他们说,当EF映射存储过程时,它将所有参数发送为null并跳过所有if循环.因此,它也会跳过这个IF(0=1)条件 SET FMTONLY OFF

关于搜索SET FMTONLY OFFMSDN,说

仅返回客户端的元数据.可用于测试响应的格式,而无需实际运行查询.

当你不控制数据库时,它会成为一个问题,你必须不断告诉DBA添加它并一遍又一遍地向它们解释为什么首先需要它.

我仍然不清楚为什么这是必需的.如果有人能够详细解释这一点,或者引导我到一些链接,这个主题涵盖了对我来说意味着世界.

wod*_*ode 7

在实体框架读入的存储过程中随意执行似乎IF(0=1) SET FMTONLY OFF 是一件有风险的事情。

据我所知,实体框架是该标志被设置为标准实践的唯一来源(大概其他 ORM 可能会使用它)。

目的(据我所知)是提供一种获取过程返回模式而不实际接触任何数据的方法。(您不想仅仅为了更新 orm 的对象模型而执行某些存储过程。

所以除非你有一个表来计算 EF 模型更新的次数(这在学术上可能很有趣)

有关其他信息,请参阅 存储过程返回 int 而不是结果集

在我看来,将 ftmonly 与实体框架一起使用的最安全的方法是..在以下情况下

  1. 如果相关过程很复杂并且会混淆 EF(EF 读取第一个返回的架构,忽略流逻辑)
  2. 让 EF 为您立旗。(我在下面清除它以提前退出)
  3. 使用始终错误的逻辑(当 FTMONLY 打开时将被忽略 - 将其解释为 EF 正在尝试读取架构)
  4. 在复杂过程开始时执行以下操作

    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
    
    Run Code Online (Sandbox Code Playgroud)


Dav*_*vid 6

我相信原因类似于从 SSRS 运行的存储过程的原因。综上所述,当 FMTONLY 处于活动状态时,您的存储过程可能会出现一些意想不到的结果。因此,明确关闭它的原因。有关详细信息,请阅读来自 SSRS 的处理 FMTONLY 的邪恶


TGH*_*TGH 4

我暂时这样做是为了能够使用设计器映射函数以在代码中表示存储过程。问题是设计者默认将 null 传递给过程来确定架构。如果传递 null ,这有时可能是执行验证并引发异常等的存储过程的问题。您描述的设置可以解决此问题,因为它返回元而不是实际数据。