c# - 存在列表导航属性时 AutoDetectChanges 不起作用
问题描述
我遇到了一个错误,在某些依赖 EF6 的代码中,没有检测到更改(尽管它们被持久化到数据存储区)。
使用List<Child>
导航属性时,如果父对象中的属性发生更改,则不会检测到更改。EntityState 保持不变。
示例控制台应用程序(带有 NuGet EntityFramework 6.2 的 .NET Framework 4.7.2)代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations.Schema;
namespace EFStateTest
{
public class Tests
{
public static void Main()
{
var context = new StandaloneContext();
/* First time run, generate some test data to work with */
if (!context.Set<ParentTable>().Any())
{
ParentTable p = new ParentTable()
{
Data = "Foo",
Children = new List<ChildTable>()
{
new ChildTable()
{
ManyData = "Bar",
},
},
};
context.Set<ParentTable>().Add(p);
}
/* nth run, do the test */
else
{
var p = context.Set<ParentTable>().FirstOrDefault(); // Get our test record
p.Data = DateTime.Now.Ticks.ToString(); // Change some data
try
{
// Get the state
object d = p.GetType().GetField("_entityWrapper").GetValue(p);
System.Data.Entity.Core.Objects.ObjectStateEntry ose = d.GetType().GetProperty("ObjectStateEntry").GetValue(d) as System.Data.Entity.Core.Objects.ObjectStateEntry;
Console.WriteLine(ose.State);
}
catch
{
Console.WriteLine("Not a proxy class");
}
}
context.SaveChanges();
Console.WriteLine("DONE");
Console.ReadLine();
}
}
// Context
public class StandaloneContext : DbContext
{
public StandaloneContext() : base("Server=(local);Database=EFTest;Integrated Security=SSPI")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ParentTableSchema());
modelBuilder.Configurations.Add(new ChildTableSchema());
base.OnModelCreating(modelBuilder);
}
}
public class ParentTable
{
public virtual int Id { get; set; }
public virtual string Data { get; set; }
public virtual List<ChildTable> Children { get; set; }
}
public class ChildTable
{
public virtual int Id { get; set; }
public virtual int ParentId { get; set; }
public virtual string ManyData { get; set; }
public virtual ParentTable Parent { get; set; }
}
public class ParentTableSchema : EntityTypeConfiguration<ParentTable>
{
public ParentTableSchema()
{
HasKey(m => m.Id)
.Property(m => m.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasMany(m => m.Children)
.WithRequired(c => c.Parent)
.HasForeignKey(c => c.ParentId);
}
}
public class ChildTableSchema : EntityTypeConfiguration<ChildTable>
{
public ChildTableSchema()
{
HasKey(m => m.Id)
.Property(m => m.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
}
运行一次以在本地计算机上生成数据库,并再次显示错误。改变父对象的属性p.Data = DateTime.Now.Ticks.ToString();
(
现在,如果您删除 的导航集合List<ChildTable> Children
,那么问题就会消失(但我有点想要导航属性)并且更改跟踪器正确更改为已修改。
我已经有一个修复,但它没有回答为什么。将导航属性更改为定义为ICollection<ChildTable>
而不是 List、IList 等,它也可以工作。
到目前为止,我在 EF 上阅读的文档说导航属性需要实现 ICollection - List 就是这样做的。那么这里给出了什么?我是不是搞错了什么,或者完全错过了什么?
解决方案
推荐阅读
- azure - 尝试从保存的磁盘创建 VM 时未找到磁盘错误
- c# - 只有在检查复选框时,如何才能进行所需的文件上传(ASP .NET)?
- css - 将 IconButton 与一行中的文本对齐
- python - 无法使用 slack SocketModeHandler 从 Python 中的 slack 读取通道消息
- r - ps 和 processx 包更新失败
- python - 使用 spaCy 时如何同时删除停用词和词形还原?
- python - 在 for 循环中创建一个包含变量名称的数据框列
- php - Apache 中的 Shell Exec 将输出发送到错误日志
- xamarin - 一段时间后要求验证
- python - 使用 python pandas 构建产品层次结构