【问题标题】:Entity Framework Core, Stored Procedure实体框架核心,存储过程
【发布时间】:2017-04-26 22:10:27
【问题描述】:

对于如何使用 Entity Framework Core 使用存储过程,我完全感到困惑。如果存储过程返回匿名类型,我该如何检索数据?如果返回类型不是匿名的,我该怎么办?如何添加输入/输出参数?

我之所以提出这些问题,是因为无论我在哪里,都会得到不同的答案。我猜 EF Core 正在迅速发展,微软正在尝试很多想法。

【问题讨论】:

    标签: entity-framework


    【解决方案1】:

    如何添加输入/输出参数?

    我将回答你的这个特殊问题。

    下面是一个有两个输入和两个输出参数的TSQL存储过程

    CREATE PROCEDURE [dbo].[yourstoredprocedure] 
    -- Add the parameters for the stored procedure here
        @varone bigint
        ,@vartwo Date
        ,@varthree double precision OUTPUT
        ,@varfour bigint OUTPUT
    AS
    BEGIN
      -- SET NOCOUNT ON added to prevent extra result sets from
      -- interfering with SELECT statements.
      SET NOCOUNT ON;
    
      -- YOUR CODE HERE
      SET @varthree = 10.02;
      SET @varfour = @varone;
      return;
    END
    

    现在使用 Entity Framework Core 执行这个存储过程

    MyContext.Database
                       .ExecuteSqlCommand(@"EXECUTE [yourstoredprocedure] " +
                                           " {0} " +
                                           ", {1} " +
                                           ",@varthree OUTPUT " +
                                           ", @varfour OUTPUT ", dataOne, dataTwo, outputVarOne, outputVarTwo);
    
    
    var outputResultOne= outputVarOne.Value as double?;
    var outputResultTwo= outputVarTwo.Value as long?;
    

    您可以简单地使用上述参数化查询来传递您的输入。您还可以创建命名参数。例如对于输出参数,我创建了两个命名参数为 -

    var outputVarOne = new SqlParameter
            {
                ParameterName = "@varthree ",
                DbType = System.Data.DbType.Double,
                Direction = System.Data.ParameterDirection.Output
            };
    var outputVarTwo = new SqlParameter
            {
                ParameterName = "@varfour ",
                DbType = System.Data.DbType.Int64,
                Direction = System.Data.ParameterDirection.Output
            };
    

    这就是使用 EF Core 执行带有输入和输出参数的存储过程的方式。希望这对某人有所帮助。

    【讨论】:

    • @downvoter 如果您的反对票被解释为好像我做错了什么我想知道并纠正自己,我将不胜感激。如果不解释不赞成投票,我永远不会知道我在这里做错了什么。
    【解决方案2】:

    您可以使用StoredProcedureEFCore 之类的扩展名

    那么用法就更直观了。

    列出行 = null;

    ctx.LoadStoredProc("dbo.ListAll")
       .AddParam("limit", 300L)
       .AddParam("limitOut", out IOutParam<long> limitOut)
       .Exec(r => rows = r.ToList<Model>());
    
    long limitOutValue = limitOut.Value;
    
    ctx.LoadStoredProc("dbo.ReturnBoolean")
       .AddParam("boolean_to_return", true)
       .ReturnValue(out IOutParam<bool> retParam)
       .ExecNonQuery();
    
    bool b = retParam.Value;
    
    ctx.LoadStoredProc("dbo.ListAll")
       .AddParam("limit", 1L)
       .ExecScalar(out long l);
    

    【讨论】:

      【解决方案3】:

      此解决方案提供调用存储过程并将返回值映射到已定义(非模型)实体的方法。 https://github.com/verdie-g/StoredProcedureDotNetCore

      微软解决了这个问题: “SQL 查询只能用于返回属于模型一部分的实体类型。我们的积压工作有一个增强功能,可以从原始 SQL 查询返回临时类型。” https://docs.microsoft.com/en-us/ef/core/querying/raw-sql

      这是在 GitHub 中跟踪的问题:https://github.com/aspnet/EntityFramework/issues/1862

      【讨论】: