【问题标题】:Get output parameter value in EF Core with stored procedure but without return table data使用存储过程但不返回表数据在 EF Core 中获取输出参数值
【发布时间】:2020-09-22 01:29:45
【问题描述】:

我有一个应该通过 id 返回登录的存储过程:

CREATE PROCEDURE MyProcedure
(
    @id INT,
    @login NVARCHAR(50) OUTPUT
)
AS
BEGIN
    SELECT
            ID
        ,
            Login
FROM
    Users
WHERE
    ID = @id
END
GO

在端点中使用此代码可以正常工作:

            var id = new SqlParameter
            {
                ParameterName = "id",
                SqlDbType = SqlDbType.Int,
                Value = 15,
            };
            var login = new SqlParameter
            {
                ParameterName = "login",
                SqlDbType = SqlDbType.NVarChar,
                Direction = ParameterDirection.Output,
                Size = 50,
            };
            var query = $"EXEC MyProcedure @{id}, @{login} OUTPUT";
            var result = _context.Set<User>()
                .FromSqlRaw(query, id, login).ToList();
            foreach (var item in result) Console.WriteLine(item.Login);

和类:

    public class User
    {
        public string Login { get; set; }
    }

和属性:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>().HasNoKey();
        }

我得到一个包含一个搜索元素的列表,它的 Login 属性是我想要的。

但是如果我把SELECT改成(原来的程序是这样的,我不能改):

    SELECT
        @id = 
            ID
        ,
        @login = 
            Login

我收到一个错误The required column 'Login' was not present in the results of a 'FromSql' operation.

那么获取Login 的正确方法是什么?

【问题讨论】:

    标签: stored-procedures entity-framework-core


    【解决方案1】:

    解决此问题的一种简单方法是使用context.Database.ExecuteSqlInterpolated()context.Database.ExecuteSqlRaw() 而不是context.Set&lt;T&gt;().FromSqlRaw()

    这是一个完整的示例控制台程序,它演示了该方法:

    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    using Microsoft.Data.SqlClient;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Logging;
    
    namespace IssueConsoleTemplate
    {
        public class User
        {
            public int UserId { get; set; }
            public string Login { get; set; }
        }
        
        public class Context : DbContext
        {
            public DbSet<User> Users { get; set; }
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder
                    .UseSqlServer(
                        @"Data Source=.\MSSQL14;Integrated Security=SSPI;Initial Catalog=So63991939")
                    .UseLoggerFactory(LoggerFactory.Create(b => b
                        .AddConsole()
                        .AddFilter(level => level >= LogLevel.Information)))
                    .EnableSensitiveDataLogging()
                    .EnableDetailedErrors();
            }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<User>()
                    .HasData(
                        new User {UserId = 1, Login = "John"},
                        new User {UserId = 2, Login = "Jane"});
            }
        }
    
        internal static class Program
        {
            private static void Main()
            {
                using var context = new Context();
    
                context.Database.EnsureDeleted();
                context.Database.EnsureCreated();
    
                var connection = context.Database.GetDbConnection();
                connection.Open();
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = @"CREATE PROCEDURE uspGetUsers (
        @userCount INT OUTPUT
    ) AS
    BEGIN
        SELECT 
            UserId,
            Login
        FROM
            Users;
    
        SELECT @userCount = @@ROWCOUNT;
    END;";
                    command.ExecuteNonQuery();
                }
    
                var userCountParameter = new SqlParameter("@myUserCountParam", SqlDbType.Int) {Direction = ParameterDirection.Output};
                context.Database.ExecuteSqlInterpolated($"EXEC uspGetUsers @userCount={userCountParameter} OUTPUT");
                
                Debug.Assert((int)userCountParameter.Value == 2);
            }
        }
    }
    

    您可以使用此.NET Fiddle 运行示例代码。

    【讨论】:

      猜你喜欢
      • 2017-09-23
      • 2017-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-30
      相关资源
      最近更新 更多