EF使用Fluent API配置映射关系

简介: 我们可以定义一个继承自EntityTypeConfiguration泛型类的类来定义domain中每个类的数据库配置,我们在这个自定义类的构造函数中使用我们上次提到的那些方法配置数据库的映射。   实体类关系的映射 实体类映射中,关系的映射配置在关系的两端都可以配置。

我们可以定义一个继承自EntityTypeConfiguration<>泛型类的类来定义domain中每个类的数据库配置,我们在这个自定义类的构造函数中使用我们上次提到的那些方法配置数据库的映射。

 

实体类关系的映射

实体类映射中,关系的映射配置在关系的两端都可以配置。例如,用户信息与登录信息的 一对多 关系可以在用户信息端配置:

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配置

  1. ToTable - TableAttribute:配置此实体类型映射到的表名
  2. HasColumnName - ColumnAttribute:配置用于存储属性的数据库列的名称
  3. HasForeignKey - ForeignKeyAttribute:将关系配置为使用在对象模型中的外键属性。如果未在对象模型中公开外键属性,则使用Map方法
  4. Ignore - NotMappedAttribute:从模型中排队某个属性,使该属性不会映射到数据库
  5. HasRequired:通过此实体类型配置必需关系。除非指定此关系,否则实体类型的实例将无法保存到数据库。数据库中的外键不可为null。
  6. HasOptional:从此实体类型配置可选关系。实体类型的实例将能保存到数据库,而无需指定此关系。数据库中的外键可为null。
  7. HasMany:从此实体类型配置一对多关系。
  8. WithOptional:将关系配置为required:optional。(required:0…1端的1,表示必需,不可为null;optional:0…1端的0,表示可选,可为null。下同)
  9. WithOptionalDependent:将关系配置为optional:optional。要配置的实体类型将成为依赖对象,且包含主体的外键。作为关系目标的实体类型将成为关系中的主体。
  10. WithOptionalPrincipal:将关系配置为optional:optional。要配置的实体类型将成为关系中的主体。作为关系目标的实体类型将成为依赖对象,且包含主体的外键。
  11. WithRequired:将关系的指定端配置为必需的,且在关系的另一端有导航属性。
  12. WithRequiredDependent:将关系配置为required:required。要配置的实体类型将成为依赖对象,且包含主体的外键。作为关系目标的实体类型将成为关系中的主体。
  13. WithRequiredPrincipal:将关系配置为required:required。要配置的实体类型将成为关系中的实体。作为关系目标的实体类型将成为依赖对象,且包含主体的外键。
  14. WillCascadeOnDelete:配置是否对关系启用级联删除。
  15. Map:将关系配置为使用未在对象模型中公开的外键属性。可通过指定配置操作来自定义列和表。如果指定了空的配置操作,则约定将生成列名。如果在对象模型中公开了外键属性,则使用 HasForeignKey 方法。并非所有关系都支持在对象模型中公开外键属性。
  16. MapKey:配置外键的列名。
  17. 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(60)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(
            new IndexAttribute("IX_FirstNameLastName", 1) { IsUnique = true }));

modelBuilder 
    .Entity<User>() 
    .Property(t => t.LastName) 
    .IsRequired()
    .HasMaxLength(60)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(
            new IndexAttribute("IX_FirstNameLastName", 2) { 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

相关文章
|
22天前
|
Java API Maven
email api java编辑方法?一文教你学会配置步骤
在Java开发中,Email API是简化邮件功能的关键工具。本文指导如何配置和使用Email API Java:首先,在项目中添加javax.mail-api和javax.mail依赖;接着,配置SMTP服务器和端口;然后,创建邮件,设定收件人、发件人、主题和正文;最后,使用Transport.send()发送邮件。借助Email API Java,可为应用添加高效邮件功能。
|
22天前
|
安全 API 数据安全/隐私保护
email api接口配置教程步骤详解
Email API是用于程序化访问邮件服务的工具,让开发者能集成邮件功能到应用中。配置Email API包括选择供应商(如SendGrid、Mailgun、AokSend),注册获取API密钥,配置API参数,及测试邮件发送。使用Email API能提升邮件发送的可靠性和效率,便于邮件管理及营销活动。AokSend支持大量验证码发送,适合高效邮件运营。
|
2月前
|
存储 关系型数据库 API
Python 任务自动化工具:nox 的配置与 API
Python 任务自动化工具:nox 的配置与 API
22 0
|
2月前
|
消息中间件 缓存 Java
Kafka Consumer java api 配置
Kafka Consumer java api 配置
|
3月前
|
供应链 数据挖掘 API
和 SAP 系统单点登录 MYSAPSSO2 相关的一些配置和 API
和 SAP 系统单点登录 MYSAPSSO2 相关的一些配置和 API
25 0
|
4月前
|
Java API
SpringBoot【集成ElasticSearch 01】2种方式的高级客户端 RestHighLevelClient 使用(依赖+配置+客户端API测试源码)
SpringBoot【集成ElasticSearch 01】2种方式的高级客户端 RestHighLevelClient 使用(依赖+配置+客户端API测试源码)
71 0
|
5月前
|
应用服务中间件 API nginx
通过 docker 学习 nginx,附全部配置及 API 测试,使用 apifox 直接打开
本篇文章以前端的视角,介绍下 nginx 的常见配置,并通过 docker 的方式学习 nginx,这保证所有实例配置都能正常运行。
|
6月前
|
JavaScript API
让 Spartacus 服务器端渲染引入 long API 调用超时机制的两种配置方法
让 Spartacus 服务器端渲染引入 long API 调用超时机制的两种配置方法
49 0
|
7月前
|
存储 JavaScript 前端开发
如何为 SAP 电商云每个不同的 JavaScript Storefront 分别配置 API endpoint
如何为 SAP 电商云每个不同的 JavaScript Storefront 分别配置 API endpoint
39 0
|
9月前
|
缓存 负载均衡 监控
php开发中大数据量优化的问题总结(1):smarty循环优化、API掉包丢失数据排查、负载平衡配置
php开发中大数据量优化的问题总结(1):smarty循环优化、API掉包丢失数据排查、负载平衡配置
114 0