Entity Framework映射的总结
EF是一个ORM工具,映射永远是最核心的部分。所以接下来详细介绍Code First模式下EF的映射配置。
通过Code First来实现映射模型有两种方式Data Annotation和Fluent API。
Data Annotation需要在实体类的属性上以Attribute的方式表示主键、外键等映射信息。这种方式不符合解耦合的要求所以一般不建议使用。
第二种方式就是要重点介绍的Fluent API。Fluent API的配置方式将实体类与映射配置进行解耦合,有利于项目的扩展和维护。
Fluent API方式中的核心对象是DbModelBuilder。
在重写的DbContext的OnModelCreating方法中,我们可以这样配置一个实体的映射:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>().HasKey(t => t.Id);
base.OnModelCreating(modelBuilder);
}
1.配置类对应于数据库中的表名
modelBuilder.Entity<Product>().ToTable("Product","dbo");
配置类对应于数据库中的表名,并指定表的所有者:
如果不指定表的所有者可以这样写
modelBuilder.Entity<Product>().ToTable("Product");
2.重新指定类属性与列名之间的映射关系
在默认约定的情况下,Entity Framework Code First创建的列名与类的属性名相同,可以根据需要进行重新指定类属性与列名之间的映射关系。
modelBuilder.Entity<Product>().Property(t => t.ProductID).HasColumnName("ProductId");
将ProductID改为ProductId.
modelBuilder.Entity<Product>().Property(t => t.ProductName).IsRequired()
.HasColumnName("ProductName")
.HasMaxLength(100);
ProductName是必须的,映射到数据库的名字为ProductName,长度为100.
3.为属性指定对应的SQL SERVER数据类型
在默认情况下,int类型的属性生成的列名对应SQL SERVER列int类型;而String类型的属性则对应SQL SERVER列的NVARCHAR类型。若类的字符串类型属性未设置MaxLength,则生成对应的列类型为NVARCHAR(MAX)。
为属性指定对应的SQL SERVER数据类型:
modelBuilder.Entity<Product>().Property(t => t.UnitPrice)
.HasColumnName("UnitPrice")
.HasColumnType("MONEY");
4.对主键的进行重写
Entity Framework Code First的默认主键约束:属性名为[ID]或[类名 + ID]。如在Product类中,Entity Framework Code First会根据默认约定将类中名称为ID或ProductID的属性设置为主键。Entity Framework Code First主键的默认约定也一样可以进行重写,重新根据需要进行设置。
modelBuilder.Entity<Product>().HasKey(t => t.ProductID);
若一个表有多个主键时:
modelBuilder.Entity<Product>().HasKey(t => new { t.KeyID, t.CandidateID });
Entity Framework Code First对于int类型的主键,会自动的设置其为自动增长列。但有时我们确实不需是自动增长的,可以通过以下方式进行取消自动增长。
modelBuilder.Entity<Product>().HasKey(t => t.ProductID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);//取消自动增长
modelBuilder.Entity<Category>().HasKey(t => t.ProductID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);//将ProductId设置为自动增长
5.设置类型的的精度
在Product类中,UnitPrice表示单价,对于价格类的字段,我们通常会希望其保留2为小数。这时可以使用Fluent API进行设置
modelBuilder.Entity<Product>().Property(t => t.UnitPrice)
.HasColumnName("UnitPrice")
.HasPrecision(18, 2);
6、非数据库字段属性
在类中,如果有一些属性不需要映射到对应生成的数据表中,可以通过以下方式设置。
modelBuilder.Entity<Product>().Ignore(t => t.Remark);
7. Fluent API配置Configuration映射类
在使用Fluent API进行Entity Framework Code First数据库映射时,除了以上的在重写OnModelCreating方法中直接对Entity进行配置之外,也可以对Configurations进行配置。这时可以先写一个单独的类,将数据表的全部映射要求都写在构造函数中。
类要继承
EntityTypeConfiguration<T>,然后再构造函数中添加映射,最后
modelBuilder.Configurations.Add(new T());
8.拓展
关联 1-1关联 Fluent API设置实体类生成的表引用与被引用通过WithRequiredPrincipal、WithRequiredDependent及WithOptionalPrincipal、WithOptionalDependent来设置,使用Principal属性的实体类将被另外的实体类生成的表引用,使用Dependent属性的实体类将引用另外的实体类。
这里说明一下
WithRequiredDependent 和 WithOptional(i => i.Product)是等价的;
//第一组(两条效果完全相同)
HasRequired(p => p.WarrantyCard).WithRequiredDependent(i => i.Product);
HasRequired(p => p.WarrantyCard).WithOptional(i => i.Product);
WithRequiredPrincipal 和 WithRequired是等价的//第二组(两条效果完全相同)
HasRequired(p => p.WarrantyCard).WithRequiredPrincipal(i => i.Product);
HasOptional(p => p.WarrantyCard).WithRequired(i => i.Product);
这里新登场角色是和发票,发票有自己的编号,有些产品有发票,有些产品没有发票。我们希望通过产品找到发票而又不需要由发票关联到产品。
public class Invoice
{
public int Id { get; set; }
public string InvoiceNo { get; set; }
public DateTime CreateDate { get; set; }
}
产品类新增的属性如下:
public virtual Invoice Invoice { get; set; }
public int? InvoiceId { get; set; }
可以使用如下代码创建Product到Invoice的关联
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
ToTable("Product");
HasKey(p => p.Id);
HasOptional(p => p.Invoice).WithMany().HasForeignKey(p => p.InvoiceId);
}
}
HasOptional表示一个产品可能会有发票,WithMany的参数为空表示我们不需要由发票关联到产品,HasForeignKey用来指定Product表中的外键列。
还可以通过WillCascadeOnDelete()配置是否级联删除,这个大家都知道,就不多说了。
运行迁移后,数据库生成的Product表外键可为空(注意实体类中表示外键的属性一定要为Nullable类型,不然迁移代码不能生成)。
单向1 - *关联(不可为空)
为了演示这个关联,请出一个新对象合格证,合格证有自己的编号,而且一个产品是必须有合格证。
public class Certification
{
public int Id { get; set; }
public string Inspector { get; set; }
}
public virtual Certification Certification { get; set; }
public int CertificationId { get; set; }
public class ProductPhoto
{
public int Id { get; set; }
public string FileName { get; set; }
public float FileSize { get; set; }
public virtual Product Product { get; set; }
public int ProductId { get; set; }
}
public virtual ICollection<ProductPhoto> Photos { get; set; }
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
ToTable("Product");
HasKey(p => p.Id);
HasMany(p => p.Photos).WithRequired(pp => pp.Product).HasForeignKey(pp => pp.ProductId);
}
}
public class ProductPhotoMap : EntityTypeConfiguration<ProductPhoto>
{
public ProductPhotoMap()
{
ToTable("ProductPhoto");
HasKey(pp => pp.Id);
HasRequired(pp => pp.Product).WithMany(p => p.Photos).HasForeignKey(pp => pp.ProductId);
}
}
public class Tag
{
public int Id { get; set; }
public string Text { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public virtual ICollection<Tag> Tags { get; set; }
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
ToTable("Product");
HasKey(p => p.Id);
HasMany(p => p.Tags).WithMany(t => t.Products).Map(m => m.ToTable("Product_Tag_Mapping"));
}
}
Entity Framework映射的总结的更多相关文章
- Entity Framework 映射问题
今天在数据库(mysql)新增了一个字段,但是一直以为添加字段,然后在实体模型中选择 一直是以为选择"添加",就导致有问题,原因就不说,有点蠢,人家都已经存在,还加上去干嘛,我要的 ...
- 第三篇:Entity Framework CodeFirst & Model 映射 续篇 EntityFramework Power Tools 工具使用
上一篇 第二篇:Entity Framework CodeFirst & Model 映射 主要介绍以Fluent API来实作EntityFramework CodeFirst,得到了大家一 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (8) -----第二章 实体数据建模基础之继承关系映射TPT
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-8 Table per Type Inheritance 建模 问题 你有这样一 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (9) -----第二章 实体数据建模基础之继承关系映射TPH
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-10 Table per Hierarchy Inheritance 建模 问题 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (10) -----第二章 实体数据建模基础之两实体间Is-a和Has-a关系建模、嵌入值映射
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-11 两实体间Is-a和Has-a关系建模 问题 你有两张有Is-a和Has-a ...
- 《Entity Framework 6 Recipes》中文翻译系列 (35) ------ 第六章 继承与建模高级应用之TPH继承映射中使用复合条件
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-11 TPH继承映射中使用复合条件 问题 你想使用TPH为一张表建模,建模中使 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (36) ------ 第六章 继承与建模高级应用之TPC继承映射
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-12 TPC继承映射建模 问题 你有两张或多张架构和数据类似的表,你想使用TP ...
- Entity Framework Code First属性映射约定
Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Fluent API.本文中采用创建Product类为例来说明tity Fram ...
- Entity Framework Code First关系映射约定
本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...
随机推荐
- hdu1198--并查集
Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle, and is ...
- erlang集成开发环境搭配配置出现的问题
问题:Unable to create the selected preference page. com.avaya.exvantage.ui.interfaces.eclipse.plugin ...
- 初识B/S结构编程技术
B/S结构编程语言 ASP(Active Server Page 动态服务器页面)技术 微软早期推出的B/S编程技术,出现在JSP和ASP.NET之前,PHP当时也很不稳定.ASP之前,动态网站使用G ...
- Python中BeautifulSoup中对HTML标签的提取
一开始使用了beautifulSoup的get_text()进行字符串的提取,后来一直提取失败,并提示错误为TypeError: 'NoneType' object is not callable 返 ...
- unix网络io模型
阻塞I/O(bloking I/O) 阻塞IO的特点就是在IO执行的两个阶段(recvfrom和数据从内核空间转移到用户空间)都被block了 非阻塞I/O(non-bloking I/O) 非阻 ...
- OGG学习笔记01-基础概述
OGG学习笔记01-基础概述 OGG(Oracle Golden Gate),最近几年在数据同步.容灾领域特别火,甚至比Oracle自己的原生产品DataGuard还要风光,主要是因为其跨平台.跨数据 ...
- css ie6最小高度问题
最小高度问题: 这个最小高度 min-height:的问题,因为min-height:只在IE7\FF中起作用.至于这个IE6死活就是不认.而我这个页面又必需得用这个最小高度来定. 但头痛的是I ...
- IronPython .NET Integration官方文档翻译笔记
http://ironpython.net/documentation/dotnet/这是原文地址 以下笔记仅记录阅读过程中我认为有必要记录的内容,大多数都是依赖翻译软件的机翻,配合个人对代码的理解写 ...
- HTML一级导航制作
今天分享一下简单导航栏的制作方法: 第一步:引入css样式表,新建一个id为nav的层,使用<ul>.<li>.<a>标签来制作完成效果. <!DOCTYPE ...
- [SQL基础教程] 4-1 数据的插入(INSERT)
[SQL基础教程] C4 数据更新 4-1 数据的插入(INSERT) INSERT INSERT INTO <表名>(列1,列2...) VALUES(值1,值2...); 清单 用() ...