0

概括

在我们的应用程序中,我们使用 Entity Framework 6 和 SQL Server 2016。在将具有复杂逻辑的存储过程导入 EF 模型时,特别是在使用临时表时,我们将其放在首位:

SET FMTONLY OFF

这会导致存储过程运行完整的逻辑并因此返回正确的输出格式,从而允许 EF 模型正确生成复杂类型。

一般来说,它工作正常。但是,Microsoft 文档https://docs.microsoft.com/en-us/sql/t-sql/statements/set-fmtonly-transact-sql?view=sql-server-ver15指出:请勿使用此功能。所以我想知道推荐的方法是导入存储过程并正确生成复杂类型。

更多细节

首先,我被这个注释弄糊涂了,不要在微软网站上使用这个关于FMTONLY. 这不是ONEF 模型更新程序调用的相同命令(带有选项)吗?这意味着 EF 模型更新程序使用了不应使用的功能。

其次,我假设此 EF 模型更新程序行为旨在防止在使用所有输入参数 equal 执行存储过程时进行不必要的 DB 数据操作NULL。但实际行为似乎与这个假设不一致。

考虑下面一个简单的存储过程,我试图避免使用SET FMTONLY OFF. 在从 Visual Studio(2013,CU 5,Pro)更新 EF 模型时,我使用 SQL 分析器分析了确切的行为。

SET NOCOUNT ON;

IF (1=0) --FOR EF edmx update this will actually execute
BEGIN
    DECLARE @tempTable TABLE
                       (
                           [id] [int], 
                           [date_local] [datetime2](7), 
                           [value] [float] NULL
                       )

    SELECT * FROM @tempTable
    RETURN 0
END

CREATE TABLE #TempValue
(
    [id] [int] NOT NULL,
    [date_local] [datetime2](7) NOT NULL,
    [value] [float] NULL

    CONSTRAINT [PK_TempValue] 
        PRIMARY KEY CLUSTERED ([id] ASC, [date_local] ASC)
                    WITH (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

INSERT INTO #TempValue (id, date_local, value)
    SELECT @id, *
    FROM OPENJSON(@valueJson)
    WITH (
          date_local datetime2(7) '$.dateTime',
          value float '$.value'
         );

SELECT * FROM #TempValue

要点:

  1. EF 模型更新程序调用它,进入内部IF (1=0)(如预期的那样SET FMTONLY ON),并SELECT * from @tempTable正确运行。

  2. 它忽略return 0并继续运行存储过程主体的其余部分。

  3. 它跳过CREATE TABLE #TempValue但随后尝试运行INSERT INTO #TempValue当然不存在的,所以它在这里停止并且不执行SELECT * FROM #TempValue,这也会失败。

在这种情况下,复杂类型被正确生成,因为最后一次成功的选择是SELECT * from @tempTable. 但我觉得这只是运气,因为没有实际运行的后续选择。对我来说,这整个行为是有缺陷的,特别是跳过return 0然后CREATE TABLE #TempValue允许INSERT INTO;如果您确定允许INSERT INTO您不保留数据库数据?

因此,我们尝试过的两种实际可行的解决方法如下:

  1. 放在SET FMTONLY OFF上面。它有效,但我对此有点担心不要在 Microsoft 网站上使用此功能。

  2. 注释掉整个 SP 正文并DECLARE @tempTable table ... SELECT * from @tempTable按照上面的示例添加。更新 EF 模型后,删除添加的块并取消注释原始代码。每次更新 EF 模型时都执行此操作,因此效率不高。

什么是正确且推荐的方法?

4

0 回答 0