Pau*_*ton 8 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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
确保安装了以下软件包:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.SqlServer.Design
Run Code Online (Sandbox Code Playgroud)
如有必要,更改连接字符串。
跑 dotnet ef migrations add initial
跑 dotnet ef database update
在您的数据库中运行以下代码:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.SqlServer.Design
Run Code Online (Sandbox Code Playgroud)
因此,当您在调试时运行 Main 程序并放置一个断路器时,您会注意到在检查过程中没有任何对象返回由该过程更新的值。在调试过程中,如果您在表上运行 select 语句,您将看到“Comment”字段确实已更新。
为什么是这样?
这不是特定于FromSql,而是 EF Core(所有版本)跟踪查询的工作方式。
以下是 EF Core How Queries Work文档主题的摘录:
以下是每个查询所经历的过程的高级概述。
- LINQ 查询由 Entity Framework Core 处理以构建准备由数据库提供程序处理的表示
- 结果被缓存,这样就不需要每次执行查询时都做这个处理
- 结果传递给数据库提供者
- 数据库提供者标识可以在数据库中评估查询的哪些部分
- 查询的这些部分被转换为特定于数据库的查询语言(例如,关系数据库的 SQL)
- 一个或多个查询被发送到数据库并返回结果集(结果是来自数据库的值,而不是实体实例)
- 对于结果集中的每个项目
- 如果这是一个跟踪查询,EF 检查数据是否表示上下文实例的更改跟踪器中已有的实体如果是,则返回现有实体如果不是,则创建一个新实体,设置更改跟踪,并创建新实体被退回
请注意最后一个项目符号。他们所做的基本上是所谓的客户端获胜策略的实现(与您正在寻找的数据库获胜相反),目前除了使用无跟踪查询之外没有其他方法可以改变它。
在您的示例中,AsNotTracking()在查询中的某处插入(之前ToList,之后dbContext.TestTables- 这真的无关紧要,因为它适用于整个查询),或者只是
dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
Run Code Online (Sandbox Code Playgroud)
现在您将看到更新的值(从您的 SP 调用或从其他会话到同一数据库)。
| 归档时间: |
|
| 查看次数: |
4916 次 |
| 最近记录: |