我正在使用EF Core处理数据(而且我是EF的新手).我有一个DbContext,我用它从SQL Server获取数据.一旦将数据加载到内存中,我就会更改不同行上的值,但现在还不会将数据写回SQL Server(我想在用户只单击OK按钮时写入数据库).

下面就是正在发生的事情:我有一个名为Equipments的表,它的列是FkIdType.我将第FkIdType行的值从NULL更改为5,例如:

var equ = DataAccess.GetEquipment(pkIdEqu);
equ.FkIdEquipmentType = (int)GVEquipmentTypes.GetFocusedRowCellValue(colPkId);

DataAccess是一个帮助器类,它只执行

context.Where(x => x.PkId == pkID).FirstOrDefault();

在那之后,我想要获得一个全部Equipments的列表,其中FkIdType是5.查询如下:

var query = context.Equipments.Where(x => x.FkIdType == 5);
query.ToList();

问题就在这里.如果我放一个断点并判断context.Equipments,我可以清楚地看到值已经改变.但是,查询不会返回任何内容(如果它是值为5的FkIdType的唯一行).为什么?

我try 直接在数据库中更改值(使用SSMS手动更改),查询似乎实际上是在数据库中查找,而不是在本地上下文中查找.我不明白为什么.

以下是我try 过的:

  1. 强迫ChangeTracker.LazyLoadingEnabled = false;
  2. 已try 使用context.Database.BeginTransaction();
  3. 从"另一方"获取数据.我的意思是这样使用TYPE表:
Types.Where(x => x.PkId == FkIdType)
     .Select(x => x.Equipments).ToList();

但同样奇怪的事情也会发生.如果我执行代码,列表就是空的.如果我"判断"Types个对象,并在中断模式下打开"结果视图"属性,那么我会看到数据,然后查询返回一个包含预期数据的列表……为什么?

推荐答案

尽管这种行为可能感觉不对,但它的行为是可以解释的.问题是,当您修改被跟踪的实体时,EF将返回该被跟踪的实体,而不是数据读取,只有当该记录由数据读取标识时,它才会这样做.

当你 run 时:

var query = context.Equipments.Where(x => x.FkIdType == 5);
query.ToList();

这将生成一个类似于以下内容的SQL查询:

SELECT * FROM [dbo].Equipments WHERE FkIdType == 5

这就是问题所在.EF将转到数据库,try 查找任何匹配的行.无论它是否找到任何更改,它都会not找到您要进行更改的行.EF将用它正在跟踪的实体替换它读取的任何实体,但它不会将扫描跟踪缓存作为查询的一部分.如果您使用从SQL查询返回已修改行的某个其他公共标识符来查询行,则结果中将替换掉FkIdType为5的已跟踪、已修改实体.

解决此问题的一种方法是,如果可能将状态修改为包含,则将数据加载到跟踪缓存中,然后显式查询跟踪缓存:

context.Equipments.Where(x => x.FkIdType == 5).ToList();
var equipments = context.Equipments.Local
    .Where(x => x.FkIdType == 5).ToList();

在这里,执行第一个查询,并将默认情况下将所选项目加载到跟踪缓存中.第二条语句针对本地跟踪缓存执行,本地跟踪缓存包括新加载的实体以及任何可能已修改的实体.不过,最终最好在读取数据之前将更新状态设置为SaveChanges().在更改跟踪中保留已修改的行任意时间都可能导致中毒的DbContext,其中跟踪的更改变得无效,并停留在那里,阻止future 的SaveChanges()调用.

Csharp相关问答推荐

Autofac:如何防止丢弃通过ServicCollection注册的服务?

Microsoft.AspNetCore.Mvc. Controller Base.用户:属性或索引器Controller Base.用户无法分配给--它是只读的

FromServices不使用WebAppliationFactory程序>

为什么在GuardationRule的收件箱函数中,decode.TryParse(valueString,out valueParsed)在给出1.0.1时返回true?

如何在NServicebus中配置学习传输的文件夹(NService bus 8)

编写DataAnnotations自定义验证器的多种方法

为什么任务需要在内部使用ManualResetEventSlim?

XUNIT是否使用测试数据的源生成器?

如何解决提交按钮后 Select 选项错误空参照异常

异步实体框架核心查询引发InvalidOperation异常

单元测试:模拟返回空

如何在VS代码中为C#DotNet配置.json选项以调试内部终端的控制台应用程序

当try 测试具有协变返回类型的抽象属性时,类似功能引发System.ArgumentException

ASP.NET MVC数据批注验证组复选框

未显示详细信息的弹出对话框

C#System.Commandline:如何向命令添加参数以便向其传递值?

SignalR跨域

在使用.NET EF Core DbContext属性之前,是否应使用null判断

读取测试项目中的应用程序设置

根据运行时值获取泛型类型的字典