public class BaseModel { public int Id { get; set; } public DateTime CreateDateTime { get; set; } } public class Address { public string Street { get; set; } public string City { get; set; } public string ZipCode { get; set; } } public class User:BaseModel { public string Name {get;set;} public string Birthdate {get;set;} public string IdNumber {get;set;} public Address Address {get;set;} }
以上代码在ORM中称为组合类,EF会将这两个类映射在一张表中。当Code First发现不能推断出类的主键,而且没有经过Data Annotations或Fluent API注册主键,那么该类型将被自动注册为复杂类型。数据库
注意:
咱们接下来建立 DbContext 类函数
public class EfDbContext : DbContext { public EfDbContext() { Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EfDbContext>()); } public DbSet<User> Users { get; set; } }
建立完DbContext类后,咱们编写将数据存入数据库的方法:ui
using (var efDbContext = new EfDbContext()) { var user = new User() { Birthdate = DateTime.Now, CreateDateTime = DateTime.Now, Name = "张三", IdNumber = "1234567" }; efDbContext.Users.Add(user); efDbContext.SaveChanges(); }
运行上述代码,会获得以下错误:spa
出现上述错误的缘由是咱们没有初始化 Address 类,其中一个(后面我会讲解另外一个解决方法)解决方法是在 new User(){} 内初始化 Address,修正后的代码以下:code
using (var efDbContext = new EfDbContext()) { var user = new User() { Birthdate = DateTime.Now, CreateDateTime = DateTime.Now, Name = "张三", IdNumber = "1234567", Address = new Address() }; efDbContext.Users.Add(user); efDbContext.SaveChanges(); }
如今咱们按照上面所述,对咱们先前编写的内容进行改造,这三条规则也是解决咱们前面所遇到的BUG的另外一个方法。对象
public class BaseModel { public int Id { get; set; } public DateTime CreateDateTime { get; set; } } public class Address { public string Street { get; set; } public string City { get; set; } public string ZipCode { get; set; } public bool HasValue { get { return (Street != null || ZipCode != null || City != null); } } } public class User : BaseModel { public User() { Address = new Address(); } public string Name { get; set; } public DateTime Birthdate { get; set; } public string IdNumber { get; set; } public Address Address { get; set; } } public class EfDbContext : DbContext { public EfDbContext() { Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EfDbContext>()); } public virtual void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.ComplexType<Address>(); } public DbSet<User> Users { get; set; } }
代码改造后咱们能够轻松的经过 变动追踪API 来访问数据的原始值和当前值。所谓原始值就是从数据库查询出来的值,当前值就是实体目前的值。入口点是 DbContext的Entry方法,返回对象类型是 DbEntityEntry 。咱们看一下访问原始值和当前值得例子:ip
using (var efDbContext = new EfDbContext()) { var user = efDbContext.Users.Find(1); var oriValue = efDbContext.Entry(user).ComplexProperty(u => u.Address).OriginalValue; //将city的值改成北京 user.Address.City = "北京"; var curValue = efDbContext.Entry(user).ComplexProperty(u => u.Address).CurrentValue; Console.WriteLine("原始值:"+oriValue.City+" 当前值:"+curValue.City); Console.Read(); }
运行上述代码,将会看到以下的输出:ci
一样,咱们也能够经过链式调用,获取复杂了类型的属性或者设置复杂类型的属性:rem
var user = efDbContext.Users.Find(1); var city = efDbContext.Entry(user).ComplexProperty(u => u.Address).Property(a => a.City).CurrentValue; Console.Write(city);
从上面的讲解咱们卡一看到,用复杂类型很双,一直用一直爽,可是复杂类型仍是有他的限制的:get