我遇到了一个错误,即在某些依赖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();
)的属性不会更改实体的跟踪状态,我使用反射将其放置在此处,但这与在上下文中使用ChangeTracker时相同。>
现在,如果您删除List<ChildTable> Children
的导航集合,那么问题就消失了(但是我有点想要导航属性),并且更改跟踪器正确地更改为Modified。
我已经有一个修复程序,但是没有回答为什么。将导航属性更改为ICollection<ChildTable>
而不是List,IList等,它也可以工作。
到目前为止,我在EF上阅读的文档都说导航属性需要实现ICollection-List可以实现。那么,这里有什么呢?我是在弄错其他东西,还是完全错过了东西?