Code First05--CodeFirst中值对象
今天主要介绍EF Code First中一个高级部分:Value Object,中文翻译过来叫做值对象。
所谓的值对象就是一些没有生命周期,也没有业务逻辑上唯一标识符的类。哪些类是Entity,哪些类是Value Object不是固定的,取决于具体的业务逻辑。比如说Customer这个类,如果在CRM系统当中,它是最重要的信息,我们需要跟踪它的状态,管理它的生命周期。但是在其他系统中,客户信息可能只代表一个名字和一些其他的属性。
下面我有一个需求,我们的订单系统有一个Customer类。在我们以前的示例中,Customer类的Address属性是一个字符串。现在我们的业务逻辑发生了改变,需要把地址信息分类显示和保存,把地址信息细分为国家,省,城市,街道及门牌号,还有邮政编码。在我们的业务中,地址信息仅仅是一些属性的集合,不需要跟踪它的生命周期,也不存在业务中的唯一标识符。所以我们把它定义为一个Value Object:
public class Address { public string Country { get; set; } public string Province { get; set; } public string City { get; set; } public string StreetAddress { get; set; } public string ZipCode { get; set; } }
想要让Entity Framework Code First默认地识别出值对象,我们的类必须具备三个条件:
1.值对象的类不能有主键。
2.值对象的类只能包含.net基础类型的属性。
3.使用值对象的类,只能包含值对象的一个实例,不能使用值对象的集合。
然后我们需要改变我们的Customer类,使用Address值对象来替代以前的字符串。
public class Customer
{ public string IDCardNumber { get; set; } public string CustomerName { get; set; } public string Gender { get; set; } public Address Address { get; set; } public string PhoneNumber { get; set; } }
如果值对象不满足三个默认的值对象识别条件,我们就需要在我们自定义的DbContext类的OnModelCreating方法中声明Address是一个值对象。
modelBuilder.ComplexType<Address>();
以下为一个测试的方法,看他是怎么样生成到数据库的表的:
[TestMethod]
public void CanAddNewCustomerWithAddress()
{
OrderSystemContext unitOfWork = new OrderSystemContext();
CustomerRepository repository = new CustomerRepository(unitOfWork);
Customer newCustomer = new Customer() { IDCardNumber = "", CustomerName = "Alex", Gender = "M", PhoneNumber = "test" }
Address customerAddress = new Address { Country = "China", Province = "Tianjin", City = "Tianjin", StreetAddress = "Crown Plaza", ZipCode = "" };
newCustomer.Address = customerAddress;
repository.AddNewCustomer(newCustomer);
unitOfWork.CommitChanges();
}
我们使用可插入基础数据的DropCreateOrderDatabaseWithSeedValueAlways自定义数据库初始化类,每次执行测试方法之前都重新建立数据库。
[TestInitialize]
public void InitializeCustomerRepositoryTest()
{
Database.SetInitializer(new DropCreateOrderDatabaseWithSeedValueAlways());
}
可以看到生成的对应表结构如下:
由上我们可以看到,我们可以看到Code First默认会把Address值对象的属性作为Customers表的列。列的名字默认是值对象类的名字+“_”+值对象属性的名字。
public class AddressComplexTypeConfiguration:ComplexTypeConfiguration<Address> {
public AddressComplexTypeConfiguration()
{
Property(a => a.Country).HasColumnName("Country").HasMaxLength();
Property(a => a.Province).HasColumnName("Province").HasMaxLength();
Property(a => a.City).HasColumnName("City").HasMaxLength();
Property(a => a.StreetAddress).HasColumnName("StreetAddress").HasMaxLength();
Property(a => a.ZipCode).HasColumnName("ZipCode").HasMaxLength();
}
}
我们通过HasColumnName这个方法,可以改变属性对应的列的名字。Entity Framework Code First默认会使用类中属性的名字作为列的名字。
总结:本章主要还是讲的是Fluent API的配置映射,如何生成对应的数据库的表结构。
Code First05--CodeFirst中值对象的更多相关文章
- 关于项目中值对象Identifier的设计-领域驱动
到现在为止做了不项目,发现每个实体都会有个相应的值对象. 先简单说一下值对象和实体之间的区别: (以下内容来着<领域驱动设计>一书) 当一个小孩画画的时候,他注意的是画笔的颜色和笔尖的粗细 ...
- EFCore:关于DDD中值对象(Owns)无法更新数值
最近使用DDD+EFCore时,使用EFCore提供的OwnsOne或者OwnsMany关联值对象保存数据,没想到遇到一个很奇怪的问题:值对象中的值竟然无法被EFCore保存!也没有抛出任何异常!我瞬 ...
- DDD 领域驱动设计-Value Object(值对象)如何使用 EF 进行正确映射
写在前面 首先,这篇博文是用博客园新发布的 MarkDown编辑器 编写的,这也是我第一次使用,语法也不是很熟悉,但我觉得应该会很爽,博文后面再记录下用过的感受,这边就不多说. 阅读目录: 上一篇回顾 ...
- Value Object(值对象)如何使用 EF 进行正确映射
DDD 领域驱动设计-Value Object(值对象)如何使用 EF 进行正确映射 写在前面 首先,这篇博文是用博客园新发布的 MarkDown编辑器 编写的,这也是我第一次使用,语法也不是很熟悉, ...
- [原创]java WEB学习笔记59:Struts2学习之路---OGNL,值栈,读取对象栈中的对象的属性,读取 Context Map 里的对象的属性,调用字段和方法,数组,list,map
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- DDD Code First 迁移数据实现EF CORE的软删除,值对象迁移配置
感谢Jeffcky大佬的博客: EntityFramework Core 2.0全局过滤 (HasQueryFilter) https://www.cnblogs.com/CreateMyself/p ...
- DDD实战12 值对象不创建表,而是直接作为实体中的字段
这里的值对象如下风格: namespace Order.Domain.PocoModels { //订单地址 //虽然是值对象 但是不继承ValueObject //因为继承ValueObject会有 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (44) ------ 第八章 POCO之POCO中使用值对象和对象变更通知
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-4 POCO中使用值对象(Complex Type--也叫复合类型)属性 问题 ...
- DDD 领域驱动设计-“臆想”中的实体和值对象
其他博文: DDD 领域驱动设计-三个问题思考实体和值对象 DDD 领域驱动设计-三个问题思考实体和值对象(续) 以下内容属于博主"臆想",如有不当,请别当真. 扯淡开始: 诺兰的 ...
随机推荐
- Mysql学习笔记(五)数据查询之测试sql部分。
正文之前,介绍mysql一些很有趣的命令. 快速的创建表,并填充表数据. create table test like 已经有的表名: inset into test select * from f ...
- C#注释的几种方法
// 单行注释 /**/ 块注释 ///说明注释,注释以后可以自动生成说明文档档 #region 折叠注释,可以将代码折叠 #endregion 只是#region 所在行后面的文字是注释文字,而其它 ...
- Rsync
转自:http://www.mike.org.cn/blog/index.php?load=read&id=639###pp=0 [rsync实现网站的备份,文件的同步,不同系统的文件的同步, ...
- NSFileManager(沙盒文件管理)数据持久化 <序列化与反序列化>
iOS应用程序只能在为该改程序创建的文件中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文本文件等. 默认情况下 ...
- android studio中ListView与SQLite的结合使用
Da.java public class Db extends SQLiteOpenHelper { public Db(Context context) { super(context, " ...
- Java Web之Servlet
Servlet参考文献: 1.http://www.cnblogs.com/luoxn28/p/5460073.html 2.http://www.cnblogs.com/xdp-gacl/p/376 ...
- 【codeblocks配置】C对Mysql数据的查询
codeblocks 编写C文件连接mysql数据库 codeblocks 设置.1.设置lib库文件: Settings->Compiler settings->Linker setti ...
- POJ 2389 Bull Math(水~Java -大数相乘)
题目链接:http://poj.org/problem?id=2389 题目大意: 大数相乘. 解题思路: java BigInteger类解决 o.0 AC Code: import java.ma ...
- HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010 题目大意: 输入 n m t,生成 n*m 矩阵,矩阵元素由 ‘.’ 'S' 'D' 'X' 四 ...
- ecshop商品-》购买记录
注意事项:{insert name='bought_notes' id=$id} 有了产品ID一切都好说 html代码 <!-- #BeginLibraryItem "/libra ...