博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【EF】Entity Framework实现属性映射约定
阅读量:6787 次
发布时间:2019-06-26

本文共 6625 字,大约阅读时间需要 22 分钟。

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 { 
get
set
; }
 
        
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 { 
get
set
; }
[MaxLength(100)]
[Required, Column(
"ProductName"
)]
public 
string 
ProductName { 
get
set
; }

  在使用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 { 
get
set
; }
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 { 
get
set
; }
 
        
[MaxLength(100)]
        
[Required, Column(
"ProductName"
)]
        
public 
string 
ProductName { 
get
set
; }
 
        
[Column(
"UnitPrice"
, TypeName = 
"MONEY"
)]
        
public 
decimal 
UnitPrice { 
get
set
; }
    
}
}

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 { 
get
set
; }

  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 { 
get
set
; }

  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());
}

 

 

转载地址:http://tsbgo.baihongyu.com/

你可能感兴趣的文章
作为架构师,你必需要搞清楚的概念:POJO、PO、DTO、DAO、BO、VO
查看>>
golang-web框架revel一个表单提交的总结
查看>>
PHP 根据IP获取地理位置
查看>>
如何设置同一单据的单据头字段各行合并显示吗?
查看>>
HAProxy负载均衡代理
查看>>
汇编中参数的传递和堆栈修正【转载】
查看>>
web安全实践系列导航
查看>>
[Oracle]GoldenGate官方文档
查看>>
第 42 章 WMware
查看>>
动感的网页相册
查看>>
Nginx的反向代理与负载均衡
查看>>
redis之(十四)redis的主从复制的原理
查看>>
Velocity入门指南
查看>>
ntp redhat
查看>>
sum(case when status=1 then 1 else 0 end) 的意思
查看>>
Win7硬盘安装方法
查看>>
python - 列表
查看>>
UIVisualEffectView用法
查看>>
springmvc+mybatis整合cms+UC浏览器文章功能
查看>>
docker安装(centos6.5_x86_64)
查看>>