【问题标题】:Method returns -1 instead of the number of updated rows方法返回 -1 而不是更新的行数
【发布时间】:2017-11-29 22:26:46
【问题描述】:

我正在尝试通过执行存储过程在我的数据库中进行批量更新。我正在调用 DbContext.Database.ExecuteSqlCommand 方法,如下所示:

_context.Database.ExecuteSqlCommand("EXECUTE TestProcedure");

在这个粗略的测试中,我的存储过程如下所示:

BEGIN
    UPDATE TestTable
    SET MyColumn = 'changed'
END

Select @@ROWCOUNT

当我直接在 SSMS 中执行 SProc 时,我得到了返回的行数。但是,如果我通过上面发布的代码执行此操作,我总是得到 -1 的结果(即使 SProc 正确执行 - 我可以在我的表中验证)。

当我把代码改成这样时:

_context.Database.ExecuteSqlCommand("UPDATE TestTable SET MyColumn = "changed");

然后我得到正确数量的更新行。由于我的实际代码更冗长,我想使用一个 SProc,但我需要准确的受影响行数。

如何使用 SProc?

【问题讨论】:

    标签: c# entity-framework-core


    【解决方案1】:

    Database.ExecuteSqlCommand 返回受影响的行数,而不是 SQL 中任何 SELECT... 语句的结果。

    如果要返回结果集,则需要改用Database.SqlQuery

    编辑:由于这是 Entity Framework Core,SqlQuery 方法不存在(但计划中)。但是,您可以执行类似的操作来获取原始连接并使用反射返回数据。它不是特别有效,但应该可以工作:

    public static class DbContextExtensionss
    {
        public static IEnumerable<TEntity> ExecSQL<TEntity>(this DbContext context, string query) where TEntity : new()
        {
            using (var connection = context.Database.GetDbConnection())
            using (var command = connection.CreateCommand())
            {
                command.CommandText = query;
                command.CommandType = CommandType.Text;
    
                if(connection.State != ConnectionState.Open)
                {
                    connection.Open();
                }
    
                using (var result = command.ExecuteReader())
                {
                    while (result.Read())
                    {
                        var entity = new TEntity();
                        foreach (PropertyInfo prop in typeof(TEntity).GetProperties())
                        {
                            if (!object.Equals(result[prop.Name], DBNull.Value))
                            {
                                prop.SetValue(entity, result[prop.Name], null);
                            }
                        }
                        yield return entity;
                    }
                }
            }
        }
    }   
    

    你会这样使用它:

    public class TestClass
    {
        public int RowCount { get; set; }
    }
    
    var results = _context.ExecSQL<>("EXECUTE TestProcedure");
    
    foreach(var testClass in results)
    {
        Console.WriteLine(testClass.RowCount);
    }
    

    注意:您需要更改存储过程以命名它返回的列以匹配类:

    SELECT @@ROWCOUNT AS [RowCount]
    

    【讨论】:

    • @ErikPhilips 我在看msdn.microsoft.com/en-us/library/…。我错误地假设了“执行命令后数据库返回的结果”这一行。将对应于 SProc 返回的内容。在发布我的问题之前,我试图对此进行调查。你能指出你所指的文档吗?
    • 大卫,这是实体框架核心。我没有看到 Database 类的 SqlQuery 方法。它在哪个包/命名空间中?
    • @MattM DavidG 包含链接.. 这是他回答中的第一个词。
    • @ErikPhilips 澄清一下,我认为“文档清楚地说明了这一点”是指这一行:“如果要返回结果集,则需要改用 Database.SqlQuery。”正如我之前所说,该方法在 EF Core 中似乎不可用。
    • @MattM 抱歉没有发现它是 EF Core。不幸的是,您不能在 EF Core 中运行即席查询 - 所有查询都必须返回有效的实体。例如:_context.Customers.FromSql("SELECT * FROM Customers")
    猜你喜欢
    • 2012-04-04
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    • 2014-10-30
    • 2010-10-04
    • 2016-10-14
    相关资源
    最近更新 更多