【问题标题】:Why do we have to write SET FMTONLY OFF in stored procedures when using Entity Framework为什么我们在使用Entity Framework的时候必须在存储过程中写SET FMTONLY OFF
【发布时间】:2020-01-24 13:40:00
【问题描述】:

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

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

IF(0=1) SET FMTONLY OFF

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

在搜索SET FMTONLY OFFMSDN 时,说

仅将元数据返回给客户端。可以用来测试格式 没有实际运行查询的响应。

当您不控制数据库时,就会出现问题,您必须不断告诉 DBA 添加它,并一遍又一遍地向他们解释为什么首先需要它。

我仍然不清楚为什么需要这样做。如果有人可以详细解释一下,或者引导我找到涵盖该主题的链接,对我来说意味着世界。

【问题讨论】:

  • 微软已经更新了他们的 SET FMTONLY 页面:- 不要使用这个功能。此功能已被 sp_describe_first_result_set (Transact-SQL)、sp_describe_undeclared_pa​​rameters (Transact-SQL)、sys.dm_exec_describe_first_result_set (Transact-SQL) 和 sys.dm_exec_describe_first_result_set_for_object (Transact-SQL) 取代。

标签: sql-server entity-framework


【解决方案1】:

我相信原因与从 SSRS 运行的存储过程类似。总之,当 FMTONLY 处于活动状态时,您的存储过程可能会出现一些意想不到的结果。因此,明确将其关闭的原因。详情请阅读Dealing with the Evil of FMTONLY from SSRS

【讨论】:

    【解决方案2】:

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

    实体框架是这个标志被设置为我知道的标准做法的唯一来源(可能其他 ORM 可能会使用它)。

    目的(据我所知)是提供一种无需实际接触任何数据即可获得过程返回模式的方法。 (一些你不想执行的存储过程只是为了更新 orm 的对象模型。

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

    有关其他信息,请参阅 Stored procedure returns int instead of result set

    在实体框架中使用 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
      

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        据我了解的场景,当更新 EDMX 时,为存储过程返回结果集而不是 INT,SET FMTONLY OFF 很有帮助。

        例如。 “SELECT * FROM @tempTable”写在存储过程中,当为此存储过程更新edmx时,在Context.cs文件中为该存储过程生成的类型可以是- public virtual int SPName。

        理想情况下它必须是: 公共虚拟 ObjectResult SPName

        要达到上述结果,我们必须使用 SET FMTONLY OFF。

        我们避免将返回类型设为 INT 并将其设为结果集类型: LINK了解如何使用:http://www.sandeepknarware.in/?p=247

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-22
          • 1970-01-01
          • 2021-12-12
          • 2011-01-21
          • 1970-01-01
          • 2013-04-30
          • 1970-01-01
          • 2011-03-17
          相关资源
          最近更新 更多