要专业系统地学习EF推荐《你必须掌握的Entity Framework 6.x与Core 2.0》。这本书作者(汪鹏,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/
先来说一下二进制类型,我也就不实践了,直接记录一下书上说的一段话
EF支持二进制属性来存储二进制文件,比如在博客中存储一张图片
public byte[] BannerImage{ get;set;}
如果我们想更改这张图片,那么必须通过设置一个新的byte[]实例来实现。不要尝试去改变已经存在二进制数组的内容。因为DetectChanges不会进入二进制数组里面来看其内容是否已经发生了改变。
换言之,将纸巾纸数组当做是不变的,只有重新设置新的二进制数组,实例才能进行数据更新。
现在来看一下复杂类型。
我们添加一个Person.里面有个复杂类型叫Address,那么如果没有Address,我们也必须要赋值一个空的对象
// 添加的时候,如果复杂类型没值,那么一定要给一个空值ctx.People.Add(new Person { Name = "dfd" });ctx.SaveChanges();
不然报错
System.Data.Entity.Infrastructure.DbUpdateException: Null value for non-nullable member. Member: 'Address'. ---> System.Data.Entity.Core.UpdateException: Null value for non-nullable member. Member: 'Address'.
在 System.Data.Entity.Core.Mapping.Update.Internal.ExtractorMetadata.RetrieveMember(IEntityStateEntry stateEntry, IExtendedDataRecord record, Boolean useCurrentValues, EntityKey key, Int32 ordinal, ModifiedPropertiesBehavior modifiedPropertiesBehavior)需要这样
// 添加成功ctx.People.Add(new Person { Name = "李四", Address = new Address() });ctx.SaveChanges();
那么修改了,正常的修改是OK 的
// 可以修改成功var first = ctx.People.First();first.Address.Province = "aaa";first.Address.City = "ss";first.Address.Area = "ff";ctx.SaveChanges();
但是结合昨天认识到的DetectChanges,那么关闭DetectChangs来修改
// 关闭自动追踪,以属性赋值的方式来修改复杂属性// 不报错,但是修改不成功,ctx.Configuration.AutoDetectChangesEnabled = false;var first = ctx.People.FirstOrDefault();first.Address.Province = "ddd";first.Address.City = "dfd";first.Address.Area = "ere";ctx.SaveChanges();
不报错,也不会修改成功。这个还是比较致命的吧,报个错始终是好的吧
行,看看API的方式修改
// 用API修改,可以修改 try { ctx.Configuration.AutoDetectChangesEnabled = false; var first = ctx.People.FirstOrDefault(); //Console.WriteLine(JsonConvert.SerializeObject(first)); var complex = ctx.Entry(first).ComplexProperty(x => x.Address); complex.Property(x => x.Province).CurrentValue = "湖南"; complex.Property(x => x.City).CurrentValue = "岳阳"; complex.Property(x => x.Area).CurrentValue = "回复"; ctx.SaveChanges(); } finally { ctx.Configuration.AutoDetectChangesEnabled = true; }
没有问题
那么,书上说,在关闭自动追踪后,可以采用给整个复杂类型赋值一个新的实例的方式来修改
但是我跟着做没有成功,还是得通过API的方式来
// 关闭自动追踪,不修改复杂类型中的属性值,而是设置一个新的复杂类型实例try{ ctx.Configuration.AutoDetectChangesEnabled = false; var p = ctx.People.FirstOrDefault(); // 书上说这样可以,但是还是不行啊 //p.Address = new Address { Province = "广西", City = "钦州", Area = "df" }; // 下面这个可以 ctx.Entry(p).ComplexProperty(x => x.Address).CurrentValue = new Address { Province = "广西", City = "钦州", Area = "fff" }; ctx.SaveChanges();}finally{ ctx.Configuration.AutoDetectChangesEnabled = true;}
那么我们要知道一点,EF不会为复杂类型创建变更追踪代理。如果你用代理追踪的方式来,是修改不成功的。