EF Core Stored Procedure FromSqlRaw Does Not Give Updated Values
当使用
我已经能够重现此行为。 若要重现,请使用.net core 3.1创建一个新的控制台应用程序c#。
将下面的代码复制粘贴到您的主Program.cs文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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"); } } } |
确保已安装以下软件包:
1 2 3 4 | Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.SqlServer.Design |
如有必要,请更改您的连接字符串。
运行
运行
在您的数据库中运行以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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"字段确实已更新。
为什么是这样?
这不是特定于
以下是EF Core How Queries Work文档主题的摘录:
The following is a high level overview of the process each query goes through.
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
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)
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
注意最后一个项目符号。 他们所做的基本上是所谓的"客户获胜"策略的实现(与您正在寻找的数据库获胜相对),当前除了使用无跟踪查询外,没有其他方法可以更改。
在您的示例中,将
1 | dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; |
现在,您将看到更新后的值(从您的SP调用或从其他会话到同一数据库)。