Entity Framework复杂类型属性映射
时间:2022-07-24
本文章向大家介绍Entity Framework复杂类型属性映射,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
零、创建项目必须代码
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类后,我们编写将数据存入数据库的方法:
using (var efDbContext = new EfDbContext())
{
var user = new User()
{
Birthdate = DateTime.Now,
CreateDateTime = DateTime.Now,
Name = "张三",
IdNumber = "1234567"
};
efDbContext.Users.Add(user);
efDbContext.SaveChanges();
}
运行上述代码,会得到如下错误:
出现上述错误的原因是我们没有初始化 Address 类,其中一个(后面我会讲解另一个解决方法)解决方法是在 new User(){} 内初始化 Address,修正后的代码如下:
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 。我们看一下访问原始值和当前值得例子:
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();
}
运行上述代码,将会看到如下的输出:
同样,我们也可以通过链式调用,获取复杂了类型的属性或者设置复杂类型的属性:
var user = efDbContext.Users.Find(1);
var city = efDbContext.Entry(user).ComplexProperty(u => u.Address).Property(a => a.City).CurrentValue;
Console.Write(city);
二、复杂类型的限制
从上面的讲解我们卡一看到,用复杂类型很双,一直用一直爽,但是复杂类型还是有他的限制的:
- 不能共享引用:因为没有主键标识,不能被自身实例之外的任何对象引用;
- 没有优雅的方式标识空引用:即使查询出的数据为空,EF Code First 依然会初始化复杂类型对象;
- 无法延迟加载。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- spring进行mock测试
- RecyclerView实现纵向和横向滚动
- Android ListView列表视图的使用方法
- 滴滴自动化运维平台夜莺实战部署
- Android UI使用HorizontalListView实现水平滑动
- python操作yaml说明
- python由已知数组快速生成新数组的方法
- Git 修改已提交 commit 的信息
- 解决windows下python3使用multiprocessing.Pool出现的问题
- 解决pyqt5异常退出无提示信息的问题
- TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南
- 来来来,让咱重新认识一下算法的复杂度!
- 带你通过字节跳动面试---操作系统复习
- Java 8 中的接口和抽象类到底有啥区别?
- Android自定义View实现简单炫酷的球体进度球实例代码