EF6学习笔记十九:不一样的复杂类型

要专业系统地学习EF推荐《你必须掌握的Entity Framework 6.x与Core 2.0》。这本书作者(汪鹏,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/

先来说一下二进制类型,我也就不实践了,直接记录一下书上说的一段话

EF支持二进制属性来存储二进制文件,比如在博客中存储一张图片

public byte[] BannerImage{get;set;}
View Code

如果我们想更改这张图片,那么必须通过设置一个新的byte[]实例来实现。不要尝试去改变已经存在二进制数组的内容。因为DetectChanges不会进入二进制数组里面来看其内容是否已经发生了改变。

换言之,将纸巾纸数组当做是不变的,只有重新设置新的二进制数组,实例才能进行数据更新。

现在来看一下复杂类型。

我们添加一个Person.里面有个复杂类型叫Address,那么如果没有Address,我们也必须要赋值一个空的对象

//  添加的时候,如果复杂类型没值,那么一定要给一个空值
ctx.People.Add(new Person { Name = "dfd" });
ctx.SaveChanges();
View Code

 不然报错

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();
View Code

那么修改了,正常的修改是OK 的

//  可以修改成功
var first = ctx.People.First();
first.Address.Province = "aaa";
first.Address.City = "ss";
first.Address.Area = "ff";
ctx.SaveChanges();
View Code

但是结合昨天认识到的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();
View Code

不报错,也不会修改成功。这个还是比较致命的吧,报个错始终是好的吧

行,看看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;
 }
View Code

没有问题

那么,书上说,在关闭自动追踪后,可以采用给整个复杂类型赋值一个新的实例的方式来修改

但是我跟着做没有成功,还是得通过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;
}
View Code

那么我们要知道一点,EF不会为复杂类型创建变更追踪代理。如果你用代理追踪的方式来,是修改不成功的。

原文地址:https://www.cnblogs.com/jinshan-go/p/10313121.html