EF使用Fluent API配置映射关系
定义一个继承自EntityTypeConfiguration<>泛型类的类来定义domain中每个类的数据库配置,在这个自定义类的构造函数中使用我们上次提到的那些方法配置数据库的映射。
映射实例
this.HasRequired(s => s.Company).WithMany().HasForeignKey(s => s.CompanyId);
this.HasOptional(s => s.User).WithMany().HasForeignKey(s => s.UserId);
this.HasRequired(s => s.User).WithOptional(s => s.WXUser);
this.Property(s => s.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
this.HasRequired(p => p.User).WithOptional(p => p.UserDepartment);
this.HasMany(s => s.Tags);
this.HasMany(s => s.CompanyAdminUsers).WithRequired().HasForeignKey(s => s.CompanyId);
HasMany(s => s.Images).WithOptional().HasForeignKey(s => s.FeedbackId);
modelBuilder.Entity<Course>()
.HasRequired(c => c.Department)
.WithMany(t => t.Courses)
.Map(m => m.MapKey("ChangedDepartmentID"));
待读:http://www.aizhengli.com/entity-framework6-code-first-get-started/95/entity-framework-code-first--fluent-api.html
实体类关系的映射
实体类映射中,关系的映射配置在关系的两端都可以配置。例如,用户信息与登录信息的 一对多 关系可以在用户信息端配置:
HasMany(m => m.LoginLogs).WithRequired(n => n.Member);
等效于在登录日志信息端配置:
HasRequired(m => m.Member).WithMany(n => n.LoginLogs);
但是,如果所有的关系映射都在作为主体的用户信息端进行配置,势必造成用户信息端配置的臃肿与职责不明。所以,为了保持各个实体类型的职责单一,实体关系推荐在关系的非主体端进行映射。
用户信息映射类,用户信息是关系的主体,所有的关系都不在此映射类中进行配置
namespace GMF.Demo.Core.Data.Configurations
{
public class MemberConfiguration : EntityTypeConfiguration<Member>
{
}
}
用户扩展信息映射类,配置用户扩展信息与用户信息的 0:1 关系
namespace GMF.Demo.Core.Data.Configurations
{
public class MemberExtendConfiguration : EntityTypeConfiguration<MemberExtend>
{
public MemberExtendConfiguration()
{
HasRequired(m => m.Member).WithOptional(n => n.Extend);
}
}
}
OnModelCreating配置
- ToTable - TableAttribute:配置此实体类型映射到的表名
- HasColumnName - ColumnAttribute:配置用于存储属性的数据库列的名称
- HasForeignKey - ForeignKeyAttribute:将关系配置为使用在对象模型中的外键属性。如果未在对象模型中公开外键属性,则使用Map方法
- Ignore - NotMappedAttribute:从模型中排队某个属性,使该属性不会映射到数据库
- HasRequired:通过此实体类型配置必需关系。除非指定此关系,否则实体类型的实例将无法保存到数据库。数据库中的外键不可为null。
- HasOptional:从此实体类型配置可选关系。实体类型的实例将能保存到数据库,而无需指定此关系。数据库中的外键可为null。
- HasMany:从此实体类型配置一对多关系。
- WithOptional:将关系配置为required:optional。(required:0…1端的1,表示必需,不可为null;optional:0…1端的0,表示可选,可为null。下同)
- WithOptionalDependent:将关系配置为optional:optional。要配置的实体类型将成为依赖对象,且包含主体的外键。作为关系目标的实体类型将成为关系中的主体。
- WithOptionalPrincipal:将关系配置为optional:optional。要配置的实体类型将成为关系中的主体。作为关系目标的实体类型将成为依赖对象,且包含主体的外键。
- WithRequired:将关系的指定端配置为必需的,且在关系的另一端有导航属性。
- WithRequiredDependent:将关系配置为required:required。要配置的实体类型将成为依赖对象,且包含主体的外键。作为关系目标的实体类型将成为关系中的主体。
- WithRequiredPrincipal:将关系配置为required:required。要配置的实体类型将成为关系中的实体。作为关系目标的实体类型将成为依赖对象,且包含主体的外键。
- WillCascadeOnDelete:配置是否对关系启用级联删除。
- Map:将关系配置为使用未在对象模型中公开的外键属性。可通过指定配置操作来自定义列和表。如果指定了空的配置操作,则约定将生成列名。如果在对象模型中公开了外键属性,则使用 HasForeignKey 方法。并非所有关系都支持在对象模型中公开外键属性。
- MapKey:配置外键的列名。
- ToTable:配置外键列所在表的名称和架构。
属性映射
主要配置:主键、数值长度、配置为必须、不映射,外键等
配置主键:
modelBuilder.Entity<ClassA>().HasKey(t => t.ID); //配置ClassA的ID属性为主键
配置联合主键:
modelBuilder.Entity<ClassA>().HasKey(t => new { t.ID, t.Name }); //配置ClassA的ID和Name为主键
设置数据非数据库生成:
modelBuilder.Entity<ClassA>().Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); //ClassA的Id属性不用数据库控制生成
设置字段最大长度:
modelBuilder.Entity<ClassA>().Property(t => t.Name).HasMaxLength(100); //设置ClassA类的Name属性的最大长度为100,如果值长度100,会抛出 DbEntityValidationException异常
设置字段为必需:
modelBuilder.Entity<ClassA>().Property(t =>t.Id).IsRequired(); //设置ClassA类的Id属性为必需
属性不映射到数据库:
modelBuilder.Entity<ClassA>().Ignore(t => t.A); //调过ClassA类的A属性,让之不映射到数据库中
将属性映射到数据库中特定列名:
modelBuilder.Entity<ClassA>()
.Property(t => t.A)
.HasColumnName("A_a"); //将类ClassA的属性A映射到数据库中对应列名A_a
类中不指定外键,但在数据库中指定外键名:
modelBuilder.Entity<Staff>()
.HasRequired(c => c.Department)
.WithMany(t => t.Staffs)
.Map(m => m.MapKey("DepartmentID")); //指定员工表中DepartmentID为Staff到Department的外键
指定属性映射的字段为Unicode类型:
modelBuilder.Entity<ClassA>()
.Property(t => t.Name)
.IsUnicode(true);
设置属性映射的列的类型:
modelBuilder.Entity<Department>()
.Property(p => p.Name)
.HasColumnType("varchar"); //设置列为varchar类型
设置复杂类型的属性(何为复杂类型? 没指定主键的类型):
modelBuilder.ComplexType<Details>()
.Property(t => t.Location)
.HasMaxLength(20);
modelBuilder.Entity<OnsiteCourse>()
.Property(t => t.Details.Location)
.HasMaxLength(20);
显示设定为复杂类型:
modelBuilder.ComplexType<ClassA>();
将属性配置为用作乐观并发令牌:
方法1、用 ConcurrencyCheck 特性或 IsConcurrencyToken 方法
modelBuilder.Entity<OfficeAssignment>()
.Property(t => t.Timestamp)
.IsConcurrencyToken();
方法2、IsRowVersion
modelBuilder.Entity<OfficeAssignment>()
.Property(t => t.Timestamp)
.IsRowVersion();
忽略类型,不映射到数据库中:
modelBuilder.Ignore<OnlineCourse>();
设置索引
您必须添加引用 ︰using System.Data.Entity.Infrastructure.Annotations;
基本例子
在这里是一种简单的用法,加上 User.FirstName
属性的索引
modelBuilder
.Entity<User>()
.Property(t => t.FirstName)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
实例 ︰
在这里是一个更现实的例子。它对多个属性添加一个 唯一索引 ︰ User.FirstName
和 User.LastName
,与索引名称"IX_FIrstNameLastName"
modelBuilder
.Entity<User>()
.Property(t => t.FirstName)
.IsRequired()
.HasMaxLength()
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_FirstNameLastName", ) { IsUnique = true })); modelBuilder
.Entity<User>()
.Property(t => t.LastName)
.IsRequired()
.HasMaxLength()
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_FirstNameLastName", ) { IsUnique = true }));
数据库模型发生改变的处理
暴力处理:直接删除掉后重新生成
namespace Portal
{
public class PortalContext : DbContext
{
static PortalContext()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<PortalContext>());
} public DbSet<Province> Provinces { get; set; }
public DbSet<Category> Categories { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ProvinceMap());
modelBuilder.Configurations.Add(new CategoryMap());
}
}
}
DropCreateDatabaseIfModelChanges<PortalContext>()太暴力了
Code First数据库迁移
改变原来类的结构后数据库将发生错误提示
1.第一次建立数据库迁移通过nugget来进行编辑
Package Manager Console-》Enable-Migrations -StartUpProjectName CodeFirst-》执行“Add-Migration FirstMigration”命令-》
执行“Update-Database”命令,更新数据库架构
你的项目中将自动生成一个名为”Migrations“的文件夹,里面包含两个文件: Configuration.cs和201308211510117_InitialCreate.cs(201308211510117是时间戳)。
Configuration.cs:是迁移配置代码,一般我们不需要修改。
namespace CodeFirst.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<CodeFirst.OrderContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
} protected override void Seed(CodeFirst.OrderContext context)
{
// This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
201308211510117_InitialCreate.cs:以代码的形式记录了本地数据库的表结构定义。
设置自动迁移
有以下两个参数可以对自动迁移进行设置:
1. AutomaticMigrationsEnabled:获取或设置 指示迁移数据库时是否可使用自动迁移的值。
2. AutomaticMigrationDataLossAllowed:获取或设置 指示是否可接受自动迁移期间的数据丢失的值。如果设置为false,则将在数据丢失可能作为自动迁移一部分出现时引发异常。
原文:
http://www.mamicode.com/info-detail-872834.html
http://www.cnblogs.com/liupeng/p/4797046.html
http://www.guanggua.com/question/21573550-setting-unique-constraint-with-fluent-api.html
https://msdn.microsoft.com/en-us/data/jj591617.aspx#PropertyIndex
http://www.cnblogs.com/lyq2012/p/6183895.html
EF使用Fluent API配置映射关系的更多相关文章
- 使用 Fluent API 配置/映射属性和类型(摘自微软Data Access and Storage)
使用 Fluent API 配置/映射属性和类型 使用实体框架 Code First 时,默认行为是使用一组 EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...
- 使用Fluent API 配置/映射属性和类型
Code First约定-Fluent API配置 使用Fluent API 配置/映射属性和类型 简介 通常通过重写派生DbContext 上的OnModelCreating 方法来访问Code F ...
- 使用 Fluent API 配置/映射属性和类型
使用 Fluent API 配置/映射属性和类型 使用实体框架 Code First 时,默认行为是使用一组 EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...
- 使用 Fluent API 配置/映射属性和类型2
1.将多个实体类映射到数据库中的一个表 要将多个实体映射到一个数据库表需要满足: a. 两个实体必须是一对一关系 b.两个实体共享一个主键 public class MyContext:DbConte ...
- Entity Framework Code First (五)Fluent API - 配置关系
上一篇文章我们讲解了如何用 Fluent API 来配置/映射属性和类型,本文将把重点放在其是如何配置关系的. 文中所使用代码如下 public class Student { public int ...
- Entity Framework Code First (五)Fluent API - 配置关系 转载 https://www.cnblogs.com/panchunting/p/entity-framework-code-first-fluent-api-configuring-relationships.html
上一篇文章我们讲解了如何用 Fluent API 来配置/映射属性和类型,本文将把重点放在其是如何配置关系的. 文中所使用代码如下 public class Student { public int ...
- Code First约定-Fluent API配置
转自:http://blog.163.com/m13864039250_1/blog/static/2138652482015283397609/ 用Fluent API 配置/映射属性和类型 简介 ...
- EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射
I.EF里的默认映射 上篇文章演示的通过定义实体类就可以自动生成数据库,并且EF自动设置了数据库的主键.外键以及表名和字段的类型等,这就是EF里的默认映射.具体分为: 数据库映射:Code First ...
- EF——默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射 02 (转)
EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射 I.EF里的默认映射 上篇文章演示的通过定义实体类就可以自动生成数据库,并且EF自动设置了数据库 ...
随机推荐
- 阿里云申请ssl证书配置tomcat访问https
首先去阿里云上面申请ssl证书,免费的,自己百度去. 申请完ok之后会让你下载一个压缩包,里面有四个文件. 在tomcat安装目录下创建cert文件夹,把这四个文件扔进去 在conf/server.x ...
- 微服务之consul
一.概述 consul是google开源的一个使用go语言开发的服务发现.配置管理中心服务.内置了服务注册与发现框 架.分布一致性协议实现.健康检查.Key/Value存储.多数据中心方案,不再需要依 ...
- ruby读取exce文件,使用roo---Gem
module SEquipsHelper #设备台账,从excel文件读取信息 require 'roo' #require 'roo-xls' #读取excel文件 # SEquipsHelper. ...
- Process和ProcessBuilder入门【原】
ProcessBuilder优点 ProcessBuilder(XXX).start()和Runtime.exec(XXX)功能相同,主要优点在使用过程中感受有: 前者是jdk1.5后的新方式 配置环 ...
- Golang入门教程(八)复合数据类型使用案例一
目录 数组 指针 结构体(struct) 一.数组 Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定 ...
- navicat and connection is being used
1.在已经保存的连接上上编辑,测试连接成功,但是点击连接就会一直提示 connection is being used 2.需要新建一个连接,才能使用,不能再已保存的上面修改
- NFine框架JqGrid导出选中行为Excel实现方法
客户端 function PostAndGetFileByUrl(url,type,postdata) { var temp; $.ajax({ url: url, type: type, data: ...
- vim 配置一:
一.vim前期准备 安装vimsudo apt-get install vim 需要保证自己的 vim 配置在 7.4 以上,有些插件只支持 7.4 以上的 vim 在根目录下建立 .vimrc 文件 ...
- Coursera, Deep Learning 5, Sequence Models, week2, Natural Language Processing & Word Embeddings
Word embeding 给word 加feature,用来区分word 之间的不同,或者识别word之间的相似性. 用于学习 Embeding matrix E 的数据集非常大,比如 1B - 1 ...
- python写商品管理练习
#.添加 #.商品名称 #.要从文件里面把所有的商品读出来 #.价格 #.写一个方法判断是否为合理的价格 #.数量 #整数 # product = { # "爱疯差":{ # &q ...