Entity Framework(七):Fluent API配置案例
一、配置主键
要显式将某个属性设置为主键,可使用 HasKey 方法。在以下示例中,使用了 HasKey 方法对 Product 类型配置 ProductId 主键。
1、新加Product类
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace FluentAPI.Model 8 { 9 public class Product 10 { 11 public int ProductId { get; set; } 12 public string ProductName { get; set; } 13 public decimal Price { get; set; } 14 } 15 }
2、新建ProductMap类,用来设置主键
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Data.Entity; 7 using System.Data.Entity.ModelConfiguration; 8 using FluentAPI.Model; 9 10 namespace FluentAPI.Data.FluentAPIMap 11 { 12 public class ProductMap : EntityTypeConfiguration<Product> 13 { 14 public ProductMap() 15 { 16 //使用 HasKey 方法对 Product 类型配置 ProductId 主键。 17 this.HasKey(p => p.ProductId); 18 } 19 } 20 }
3、查看数据库
二、配置复合主键
以下示例配置要作为Department 类型的组合主键的DepartmentID 和 Name 属性。
1、创建Department类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace FluentAPI.Model 8 { 9 public class Department 10 { 11 public int DepartmentId { get; set; } 12 public string Name { get; set; } 13 public decimal Budget { get; set; } 14 public DateTime StartDate { get; set; } 15 } 16 }
2、创建DepartmentMap类,用来设置复合主键
1 using FluentAPI.Model; 2 using System; 3 using System.Collections.Generic; 4 using System.Data.Entity.ModelConfiguration; 5 using System.Linq; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace FluentAPI.Data.FluentAPIMap 10 { 11 public class DepartmentMap : EntityTypeConfiguration<Department> 12 { 13 public DepartmentMap() 14 { 15 // 使用匿名类的方式配置DepartmentId和Name作为复合主键 16 this.HasKey(p => new {p .DepartmentId,p.Name}); 17 } 18 } 19 }
3、查看数据库
使用EF的数据迁移,然后查看数据库表
三、关闭数值主键的标识
数值主键的标识DatabaseGeneratedOption是一个枚举值,该枚举值具有下面三个值:
DatabaseGeneratedOption.None:关闭数值主键。
DatabaseGeneratedOption.Identity:设置数值主键 自动增长 ,
DatabaseGeneratedOption.Computed :数值主键的值由计算得到(此列将无法插入值)。
1、设置关闭数值主键
1 using FluentAPI.Model; 2 using System; 3 using System.Collections.Generic; 4 using System.ComponentModel.DataAnnotations.Schema; 5 using System.Data.Entity.ModelConfiguration; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 10 namespace FluentAPI.Data.FluentAPIMap 11 { 12 public class DepartmentMap : EntityTypeConfiguration<Department> 13 { 14 public DepartmentMap() 15 { 16 // 使用匿名类的方式配置DepartmentId和Name作为复合主键 17 this.HasKey(p => new {p .DepartmentId,p.Name}); 18 19 // 以下示例将DepartmentID 属性设置为System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None,以指示该值不由数据库生成。 20 this.Property(p => p.DepartmentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 21 } 22 } 23 }
插入数据库表的时候DepartmentId列要显示的指定值:
INSERT INTO Departments VALUES (1, '人事部',12.3,GETDATE());
四、指定属性的最大长度
HasMaxLength可以设置表中列的最大长度。
1 using FluentAPI.Model; 2 using System; 3 using System.Collections.Generic; 4 using System.ComponentModel.DataAnnotations.Schema; 5 using System.Data.Entity.ModelConfiguration; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 10 namespace FluentAPI.Data.FluentAPIMap 11 { 12 public class DepartmentMap : EntityTypeConfiguration<Department> 13 { 14 public DepartmentMap() 15 { 16 // 使用匿名类的方式配置DepartmentId和Name作为复合主键 17 this.HasKey(p => new {p .DepartmentId,p.Name}); 18 19 // 以下示例将DepartmentID 属性设置为System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None,以指示该值不由数据库生成。 20 //this.Property(p => p.DepartmentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 21 22 // 以下示例将DepartmentID 属性设置为System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None,以指示该值由数据库自动生成。 23 //this.Property(p => p.DepartmentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 24 25 //Name属性不应超过 50 个字符。如果其值超过 50 个字符,则出现 DbEntityValidationException 异常。 26 //如果 Code First 基于此模型创建数据库,它还会将 Name 列的最大长度设置为50 个字符。 27 this.Property(p => p.Name).HasMaxLength(50); 28 29 } 30 } 31 }
五、将属性配置为必需
1 using FluentAPI.Model; 2 using System; 3 using System.Collections.Generic; 4 using System.ComponentModel.DataAnnotations.Schema; 5 using System.Data.Entity.ModelConfiguration; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 10 namespace FluentAPI.Data.FluentAPIMap 11 { 12 public class DepartmentMap : EntityTypeConfiguration<Department> 13 { 14 public DepartmentMap() 15 { 16 // 使用匿名类的方式配置DepartmentId和Name作为复合主键 17 this.HasKey(p => new {p .DepartmentId,p.Name}); 18 19 // 以下示例将DepartmentID 属性设置为System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None,以指示该值不由数据库生成。 20 //this.Property(p => p.DepartmentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 21 22 // 以下示例将DepartmentID 属性设置为System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None,以指示该值由数据库自动生成。 23 //this.Property(p => p.DepartmentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 24 25 //Name属性不应超过 50 个字符。如果其值超过 50 个字符,则出现 DbEntityValidationException 异常。 26 //如果 Code First 基于此模型创建数据库,它还会将 Name 列的最大长度设置为50 个字符。 27 this.Property(p => p.Name).HasMaxLength(50); 28 29 /* 30 Name属性是必需的。如果不指定 Name,则出现 DbEntityValidationException 异常。如果 Code First 基于此模型创建数据库,则用于存储此属性的列将不可为空。 31 */ 32 this.Property(p => p.Name).IsRequired(); 33 34 } 35 } 36 }
六、指定不将CLR 属性映射到数据库中的列
1 using FluentAPI.Model; 2 using System; 3 using System.Collections.Generic; 4 using System.ComponentModel.DataAnnotations.Schema; 5 using System.Data.Entity.ModelConfiguration; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 10 namespace FluentAPI.Data.FluentAPIMap 11 { 12 public class DepartmentMap : EntityTypeConfiguration<Department> 13 { 14 public DepartmentMap() 15 { 16 // 使用匿名类的方式配置DepartmentId和Name作为复合主键 17 this.HasKey(p => new {p .DepartmentId,p.Name}); 18 19 // 以下示例将DepartmentID 属性设置为System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None,以指示该值不由数据库生成。 20 //this.Property(p => p.DepartmentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 21 22 // 以下示例将DepartmentID 属性设置为System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None,以指示该值由数据库自动生成。 23 //this.Property(p => p.DepartmentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 24 25 //Name属性不应超过 50 个字符。如果其值超过 50 个字符,则出现 DbEntityValidationException 异常。 26 //如果 Code First 基于此模型创建数据库,它还会将 Name 列的最大长度设置为50 个字符。 27 this.Property(p => p.Name).HasMaxLength(50); 28 29 /* 30 Name属性是必需的。如果不指定 Name,则出现 DbEntityValidationException 异常。如果 Code First 基于此模型创建数据库,则用于存储此属性的列将不可为空。 31 */ 32 this.Property(p => p.Name).IsRequired(); 33 34 /* 35 以下示例显示如何指定CLR 类型的属性不映射到数据库中的列。 36 Ignore 等同于数据注解NotMapped 37 */ 38 this.Ignore(p => p.Budget); 39 40 } 41 } 42 }
七、将CLR 属性映射到数据库中的特定列
HasColumnName可以用来设置映射到数据库表中列的列名。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Data.Entity; 7 using System.Data.Entity.ModelConfiguration; 8 using FluentAPI.Model; 9 using System.ComponentModel.DataAnnotations.Schema; 10 11 namespace FluentAPI.Data.FluentAPIMap 12 { 13 public class ProductMap : EntityTypeConfiguration<Product> 14 { 15 public ProductMap() 16 { 17 //使用 HasKey 方法对 Product 类型配置 ProductId 主键。 18 this.HasKey(p => p.ProductId); 19 20 /* 21 * 以下示例将Price CLR 属性映射到ProductPrice 数据库列。 22 */ 23 this.Property(p => p.Price).HasColumnName("ProductPrice"); 24 } 25 } 26 }
八、配置字符串属性是否支持Unicode 内容
IsUnicode()方法可以用来设置是否支持Unicode字符,该方法有两个重载函数。
1、没有参数的重载,默认支持Unicode字符
2、有参数的重载,参数为bool值,true支持Unicode,false不支持Unicode
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Data.Entity; 7 using System.Data.Entity.ModelConfiguration; 8 using FluentAPI.Model; 9 using System.ComponentModel.DataAnnotations.Schema; 10 11 namespace FluentAPI.Data.FluentAPIMap 12 { 13 public class ProductMap : EntityTypeConfiguration<Product> 14 { 15 public ProductMap() 16 { 17 //使用 HasKey 方法对 Product 类型配置 ProductId 主键。 18 this.HasKey(p => p.ProductId); 19 20 /* 21 * 以下示例将Price CLR 属性映射到ProductPrice 数据库列。 22 */ 23 this.Property(p => p.Price).HasColumnName("ProductPrice"); 24 25 /* 26 * 默认情况下,字符串为Unicode(SQLServer 中的nvarchar)。您可以使用IsUnicode 方法指定字符串应为varchar 类型。 27 */ 28 this.Property(p => p.PlaceOfOrigin).IsUnicode(false); 29 } 30 } 31 }
查看数据库列类型:
九、配置数据库列的数据类型
HasColumnType 方法支持映射到相同基本类型的不同表示。
1 /* 2 HasColumnType 方法支持映射到相同基本类型的不同表示。使用此方法并不支持在运行时执行任何数据转换。 3 * 请注意,IsUnicode 是将列设置为 varchar 的首选方法,因为它与数据库无关。 4 */ 5 this.Property(p => p.Name).HasColumnType("varchar");
十、配置复杂类型的属性
1、新建类Course,里面有一个Department类型的属性:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace FluentAPIApp.Model 8 { 9 public class Course 10 { 11 public int CourseID { get; set; } 12 public string Title { get; set; } 13 public int Credits { get; set; } 14 public virtual Department Department { get; set; } 15 } 16 }
1 using FluentAPI.Model; 2 using System; 3 using System.Collections.Generic; 4 using System.Data.Entity.ModelConfiguration; 5 using System.Linq; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace FluentAPI.Data.FluentAPIMap 10 { 11 public class CourseMap : EntityTypeConfiguration<Course> 12 { 13 public CourseMap() 14 { 15 /*可以使用点表示法访问复杂类型的属性。 16 设置Course类里面的Department属性的Name的最大长度是32 17 */ 18 this.Property(p => p.Department.Name).HasMaxLength(32); 19 } 20 } 21 }
十一、将CLR 实体类型映射到数据库中的特定表
1 /*Department 的所有属性都将映射到名为 t_ Department 的表中的列。*/ 2 ToTable("t_Department"); 3 /*您也可以这样指定架构名称:*/ 4 ToTable("t_Department", "school");
代码地址:https://pan.baidu.com/s/1eR20fWe
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决