sql-server - EF Core 存储过程 FromSqlRaw 不提供更新值

标签 sql-server stored-procedures entity-framework-core ef-core-3.1

使用 FromSqlRaw 在 EF Core 3 上运行过程时更新表中的值,EF 当我在数据库中查询这些更改的值时返回更新的值。

我已经能够重现这种行为。要使用 .net core 3.1 重现创建一个新的控制台应用程序 c#。

将下面的代码复制粘贴到您的主 Program.cs 文件中:

using System;
using System.Linq;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;

namespace EfCoreTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            // testing proc
            var dbContext = new TestContext();
            var tables = dbContext.TestTables.ToList();
            var updated = dbContext.TestTables
                .FromSqlRaw("execute testProc @Id=@Id, @Comments=@Comments", new object[]
                {
                    new SqlParameter("Id", 1),
                    new SqlParameter("Comments", "testing comments 2"),
                })
                .ToList();
            var again = dbContext.TestTables.ToList();
        }
    }


    public class TestTable
    {
        public int TestTableId { get; set; }

        public string Comment { get; set; }
    }

    public class TestContext : DbContext
    {
        public DbSet<TestTable> TestTables { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Server=localhost\SQLEXPRESS;Database=TestDb;Trusted_Connection=True");
        }
    }
}

确保安装了以下软件包:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.SqlServer.Design

如有必要,更改连接字符串。

运行 dotnet ef migrations add initial
运行 dotnet ef database update
在您的数据库中运行以下代码:

drop procedure if exists testProc
go
create procedure testProc
@Id int,
@Comments nvarchar(max)
as
begin
    update dbo.TestTables
    set Comment = @Comments
    where TestTableId = @Id;

    select * from dbo.TestTables;
end

go


INSERT INTO [dbo].[TestTables]
(Comment) VALUES ('Test Comment');

因此,当您在调试时运行 Main 程序并放置一个断路器时,您会注意到没有任何对象返回在检查过程中由该过程更新的值。在调试过程中,如果您在表上运行 select 语句,您将看到“Comment”字段确实已更新。

为什么是这样?

最佳答案

这不是特定于 FromSql ,但是EF Core(所有版本)的方式tracking queries工作。

这是 EF Core How Queries Work 的摘录文档主题:

The following is a high level overview of the process each query goes through.

  1. The LINQ query is processed by Entity Framework Core to build a representation that is ready to be processed by the database provider
    • The result is cached so that this processing does not need to be done every time the query is executed
  2. The result is passed to the database provider
    • The database provider identifies which parts of the query can be evaluated in the database
    • These parts of the query are translated to database specific query language (for example, SQL for a relational database)
    • One or more queries are sent to the database and the result set returned (results are values from the database, not entity instances)
  3. For each item in the result set
    • If this is a tracking query, EF checks if the data represents an entity already in the change tracker for the context instance If so, the existing entity is returned If not, a new entity is created, change tracking is setup, and the new entity is returned


请注意最后一个项目符号。他们所做的基本上是所谓的客户端获胜策略的实现(与您正在寻找的数据库获胜相反),目前除了使用无跟踪查询之外没有其他方法可以改变它。

在您的示例中,插入 AsNotTracking()在查询中的某个地方(在 ToList 之前,在 dbContext.TestTables 之后 - 这真的无关紧要,因为它适用于整个查询),或者只是

dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

现在您将看到更新的值(从您的 SP 调用或从其他 session 到同一数据库)。

关于sql-server - EF Core 存储过程 FromSqlRaw 不提供更新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60101625/

相关文章:

sql-server - SQL 过程中的打印语句会影响性能吗?

tsql - 仅通过存储过程强制插入

sql-server - 登录前握手期间发生 mssql-cli 连接到本地服务器服务器容器错误

entity-framework - 为什么我的 EF Core 迁移会忽略模型的 OnDelete 设置?

c# - Entity Framework 核心 : Adding an object with a List to a DbContext results in an empty List

sql - 在 T/SQL 中如何按一列分组并检索具有另一列最小值的行?

sql-server - 如何批量插入显示文件名的附加列?

java - 如何将用户定义的表类型传递给来自 Java 的 MSSQL 请求

mysql - 2015 年未曾就诊的患者及其最后一次就诊日期

sql - "Version"是 TRANSACT-SQL 中的保留字吗? (显示蓝色但不在保留字列表中)