Entity Framework Code First属性映射约定中“约定”一词,在原文版中为“Convention”,翻译成约定或许有些不好理解,这也是网上比较大多数的翻译,我们就当这是Entity Framework的一些使用“规则”,这样或许更好理解一些。

  Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Fluent API。本文中采用创建Product类为例来说明tity Framework Code First属性映射约定的具体方式。

  1、表名及所有者

  在默认约定的情况下,Entity Framework Code First创建的表名是根据类名的英语复数形式,创建的表所有者为dbo,可以通过重写约定来指定表名及表的所有者。

  1>、Data Annotation方式

  在使用Data Annotation方式进行Entity Framework Code First与数据库映射之前,需要先添加命名空间引用。

1
using System.ComponentModel.DataAnnotations.Schema;

  为类配置对应表名:

1
2
[Table("Product")]
public class Product

  为类配置对应表名并指定表的所有者:

1
2
[Table("Product", Schema = "dbo")]
public class Product

  2>、Fluent API方式

  Fluent API实现配置Entity Framework Code First与数据库映射关系主要是通过继承DbContext并重写其中的OnModelCreating方法来进行的。在本文中新建类文件PortalContext.cs继承DbContext。

  在继承DbContext之前,添加命名空间引用。

1
using System.Data.Entity;

  重写OnModelCreating方法,配置类对应于数据库中的表名:

1
2
3
4
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().ToTable("Product");
}

  重写OnModelCreating方法,配置类对应于数据库中的表名,并指定表的所有者:

1
2
3
4
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().ToTable("Product""dbo");
}

  到此处PortalContext.cs的完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.Data.Entity;
 
using Portal.Entities;
 
namespace Portal
{
    public class PortalContext : DbContext
    {
        static PortalContext()
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<PortalContext>());
        }
 
        public PortalContext()
            base("name=PortalContext")
        {
        }
 
        public DbSet<Product> Products { getset; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Product>().ToTable("Product""dbo");
        }
    }
}

2、字段名、长度、数据类型及是否可空

  在默认约定的情况下,Entity Framework Code First创建的列名与类的属性名相同,可以根据需要进行重新指定类属性与列名之间的映射关系。

  1>、Data Annotation方式

1
2
3
4
5
[Column("ProductID")]
public int ProductID { getset; }
[MaxLength(100)]
[Required, Column("ProductName")]
public string ProductName { getset; }

  在使用Required特性(Attribute)设置字段不允许为空时,需要添加命名空间引用:

1
using System.ComponentModel.DataAnnotations;

  2>、Fluent API方式

1
2
3
4
5
6
7
8
9
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().Property(t => t.ProductID)
        .HasColumnName("ProductID");
    modelBuilder.Entity<Product>().Property(t => t.ProductName)
        .IsRequired()
        .HasColumnName("ProductName")
     .HasMaxLength(100);
}

在默认情况下,int类型的属性生成的列名对应SQL SERVER列int类型;而String类型的属性则对应SQL SERVER列的NVARCHAR类型。若类的字符串类型属性未设置MaxLength,则生成对应的列类型为NVARCHAR(MAX)。

  为属性指定对应的SQL SERVER数据类型:

1
2
3
4
5
[Column("UnitPrice", TypeName = "MONEY")]
public decimal UnitPrice { getset; }
modelBuilder.Entity<Product>().Property(t => t.UnitPrice)
    .HasColumnName("UnitPrice")
    .HasColumnType("MONEY");

  到此步,Product.cs类文件的完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
 
namespace Portal.Entities
{
    [Table("Product", Schema = "dbo")]
    public class Product
    {
        [Column("ProductID")]
        public int ProductID { getset; }
 
        [MaxLength(100)]
        [Required, Column("ProductName")]
        public string ProductName { getset; }
 
        [Column("UnitPrice", TypeName = "MONEY")]
        public decimal UnitPrice { getset; }
    }
}

3、主键

  Entity Framework Code First的默认主键约束:属性名为[ID]或[类名 + ID]。如在Product类中,Entity Framework Code First会根据默认约定将类中名称为ID或ProductID的属性设置为主键。Entity Framework Code First主键的默认约定也一样可以进行重写,重新根据需要进行设置。

  1>、Data Annotation方式

1
2
3
[Key]
[Column("ProductID")]
public int ProductID { getset; }

  2>、Fluent API方式

1
2
3
4
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().HasKey(t => t.ProductID);
}

  若一个表有多个主键时:

1
2
3
4
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().HasKey(t => new { t.KeyID, t.CandidateID });
}

  4、数据库自动生成字段值

  Entity Framework Code First对于int类型的主键,会自动的设置其为自动增长列。但有时我们确实不需是自动增长的,可以通过以下方式进行取消自动增长。

  1>、Data Annotation方式

1
2
3
4
[Key]
[Column("ProductID")]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ProductID { getset; }

  2>、Fluent API方式

1
2
3
4
5
6
7
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().HasKey(t => t.ProductID);
    modelBuilder.Entity<Product>().Property(t => t.ProductID)
        .HasColumnName("ProductID")
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}

5、数字类型长度及精度

  在Product类中,UnitPrice表示单价,对于价格类的字段,我们通常会希望其保留2为小数。这时可以使用Fluent API进行设置,且Data Annotation不支持该设置。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().Property(t => t.UnitPrice)
        .HasColumnName("UnitPrice")
        .HasPrecision(18, 2);
}

  6、非数据库字段属性

  在类中,如果有一些属性不需要映射到对应生成的数据表中,可以通过以下方式设置。

  1>、Data Annotation方式

[NotMapped]
public string Remark { get; set; }

  2>、Fluent API方式

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().Ignore(t => t.Remark);
}

  7、Fluent API配置Configuration映射类

  在使用Fluent API进行Entity Framework Code First数据库映射时,除了以上的在重写OnModelCreating方法中直接对Entity进行配置之外,也可以对Configurations进行配置。这时可以先写一个单独的类,将数据表的全部映射要求都写在构造函数中。

  ProductMap.cs类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
 
using Portal.Entities;
 
namespace Portal.Mapping
{
    public class ProductMap : EntityTypeConfiguration<Product>
    {
        public ProductMap()
        {
            // Primary Key
            this.HasKey(t => t.ProductID);
 
            // Properties
            this.Property(t => t.ProductID)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
            this.Property(t => t.ProductName)
                .IsRequired()
                .HasMaxLength(100);
 
            // Table & Column Mappings
            this.ToTable("Product");
            this.Property(t => t.ProductID).HasColumnName("ProductID");
            this.Property(t => t.ProductName).HasColumnName("ProductName");
            this.Property(t => t.UnitPrice)
                .HasColumnName("UnitPrice")
                .HasPrecision(18, 2);
        }
    }
}

有了上面的映射类之后,在重写OnModelCreating方法中则可以直接调用映射类,从而减少了OnModelCreating方法的复杂度,同时也增强了代码维护的可读性。

1
2
3
4
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new ProductMap());
}
 

【EF】Entity Framework实现属性映射约定的更多相关文章

  1. Entity Framework实现属性映射约定

    Entity Framework Code First属性映射约定中“约定”一词,在原文版中为“Convention”,翻译成约定或许有些不好理解,这也是网上比较大多数的翻译,我们就当这是Entity ...

  2. Entity Framework Code First属性映射约定

    Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Fluent API.本文中采用创建Product类为例来说明tity Fram ...

  3. 补习知识:Entity Framework Code First属性映射约定

    Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Fluent API.本文中采用创建Product类为例来说明tity Fram ...

  4. Entity Framework Code First属性映射约定 转载https://www.cnblogs.com/libingql/p/3352058.html

    Entity Framework Code First属性映射约定   Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Flue ...

  5. [转载]灵动思绪EF(Entity FrameWork)

    很久之前就想写这篇文章了,但是由于种种原因,没有将自己学习的EF知识整理成一片文章.今天我就用CodeFirst和ModelFirst两种方式的简单案例将自己学习的EF知识做个总结. 在讲解EF之前, ...

  6. 第三篇:Entity Framework CodeFirst & Model 映射 续篇 EntityFramework Power Tools 工具使用

    上一篇 第二篇:Entity Framework CodeFirst & Model 映射 主要介绍以Fluent API来实作EntityFramework CodeFirst,得到了大家一 ...

  7. 第二篇:Entity Framework CodeFirst & Model 映射

    前一篇 第一篇:Entity Framework 简介 我有讲到,ORM 最关键的 Mapping,也提到了最早实现Mapping的技术,就是 特性 + 反射,那Entity Framework 实现 ...

  8. EFCodeFirst属性映射约定

    EFCodeFirst属性映射约定 EFCodeFirst 属性映射约定 CodeFirst与数据表之间得映射方式又两种:Data Annotation和Fluent API 默认约定: 表名为类名的 ...

  9. EF(Entity Framework)多对多关系下用LINQ实现"NOT IN"查询

    这是今天在实际开发中遇到的一个问题,需求是查询未分类的博文列表(未加入任何分类的博文),之前是通过存储过程实现的,今天用EF实现了,在这篇博文中记录一下. 博文的实体类BlogPost是这样定义的: ...

随机推荐

  1. 20155318 2016-2017-2 《Java程序设计》第三周学习总结

    20155318 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 一.类与对象 Clothes c1 = new Clothes();将c1名称参考至新建对象 ...

  2. 2288: 【POJ Challenge】生日礼物

    2288: [POJ Challenge]生日礼物 https://lydsy.com/JudgeOnline/problem.php?id=2288 分析: 贪心+堆+链表. 首先把序列变一下,把相 ...

  3. 1563: [NOI2009]诗人小G

    1563: [NOI2009]诗人小G https://lydsy.com/JudgeOnline/problem.php?id=1563 分析: 直接转移f[i]=f[j]+cost(i,j),co ...

  4. MySQL入门篇(五)之高可用架构MHA

    一.MHA原理 1.简介: MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Faceb ...

  5. 【excle基础】如何去掉excel某一列中的字段的空格

    如图所示,想要去掉A列的空格: 查找空格,全部替换

  6. iOS 上架的坑

    有3D-touch机型的坑 昨天在上线的时候遇到了一个坑,最后导致的结果是找了好几个小时,直接到半夜才能上线. 入正题: 坑是:项目运行在456上没什么问题,但是在6S以上的机型就有点击事件不响应的情 ...

  7. C#之#if #endif的简单用法

    有时候我们看到别人的代码中有#if #endif,其实这是通过不同版本来选择运行哪段代码,和咱们的if,else是一样的.下面看下简单的用法 #if DEBUG txt_display.Text = ...

  8. Spring Cloud Learning(一): 服务注册

    官网https://projects.spring.io/spring-cloud/,spring cloud官网各组件版本为: Component Edgware.SR4 Finchley.SR1 ...

  9. Redis5.0:在这些场景使用,高效率还低成本!

    很多大型电商网站.视频直播和游戏应用等,存在大规模数据访问,对数据查询效率要求高,且数据结构简单,不涉及太多关联查询. 这种场景使用Redis,在速度上对传统磁盘数据库有很大优势,能够有效减少数据库磁 ...

  10. lxd&openstack-lxd源码剖析

    lxd:https://linuxcontainers.org/lxd/,目标是融入到openstack体系被管理,像虚拟机一样被管理使用.从如下图可知,并非走的是libvirt-lxc路线,而是no ...