第十六节: EF的CodeFirst模式通过Fluent API修改默认协定

一. 简介

 1. 优先级:Fluent API > data annotations > default conventions.

 2. 所有的Fluent API配置都要在 OnModelCreating这个重写方法中进行

 3. 常见的配置:

   ① 获取表对应的配置根: var stu =modelBuilder.Entity<XXX>();

   ② 设置主键:HasKey<string>(s => s.studentKey);

   ③ 获取属性:stu.Property(p => p.stuName)

   ④ 设置可空或非空:IsRequired和IsOptional

   ⑤ 设置最大值:HasMaxLength

   ⑥ 修改属性名→修改属性的次序→修改属性对应的数据库类型:HasColumnName→HasColumnOrder→HasColumnType

   ⑦ 修改表名:ToTable

 4. 可以建立多个Fluent API的配置文件,然后通过 modelBuilder.Configurations.Add(new XXX());添加到一起

PS:或者利用这句话   modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly());     把所有的配置文件一次性全部加进来

二. 代码实战

 1   public class Student5
 2     {
 3         //主键声明
 4         public string studentKey { get; set; }
 5 
 6         //非空声明
 7         public string stuName { get; set; }
 8 
 9         //最大长度
10         public string stuTxt1 { get; set; }
11 
12         //最大长度和最小长度
13         public string stuTxt2 { get; set; }
14 
15         //设置为时间戳
16         public byte[] rowVersion { get; set; }
17 
18         //并发检查
19         public string stuTxt3 { get; set; }
20 
21         //public virtual StudentAddress5 stuAddress5 { get; set; }
22     }
23    public class StudentAddress5
24     {
25          //既是主键、又是外键
26         public string stuAddressId { get; set; }
27 
28          //设置映射数据库中表的列名
29         public string stuAddressName { get; set; }
30 
31         //设置映射数据库中表的列名、顺序、类型
32         public string stuAddrssName2 { get; set; }
33 
34         //不映射数据
35         public string addressNum { get; set; }
36 
37         //不映射数据
38         public string txt1 { get { return stuAddrssName2; } }
39 
40         //不映射数据
41         public string _txt2 = "1";
42         public string txt2 { set { _txt2 = value; } }
43 
44         //public virtual Student5 stu { get; set; }
45     }
46 
47     /// <summary>
48     /// Game实体,与其它两个没有什么直接关系,单纯的为了演示, Fluent API的配置,可以根据实体进行拆分
49     /// 文件来配置,方便管理
50     /// </summary>
51     public class Game
52     {
53         public int GameId { get; set; }
54 
55         public string GameName { get; set; }
56     }
 1      /// <summary>
 2     /// Game实体的配置文件
 3     /// </summary>
 4     public class GameConfiguration : EntityTypeConfiguration<Game>
 5     {
 6         public GameConfiguration()
 7         {
 8             this.HasKey(p => p.GameId);
 9 
10             this.Property(p => p.GameName).HasMaxLength(10).IsRequired();
11         }
12     }
 1 public class dbContext5 : DbContext
 2     {
 3         public dbContext5()
 4             : base("name=dbContext5")
 5         {
 6 
 7         }
 8 
 9         public DbSet<Student5> Student5 { get; set; }
10 
11         public DbSet<StudentAddress5> StudentAddress5 { get; set; }
12 
13 
14         protected override void OnModelCreating(DbModelBuilder modelBuilder)
15         {
16             //所有的FluentAPI均在方法中进行重写
17 
18             //一. 属性层次上的设置
19             var stu = modelBuilder.Entity<Student5>();
20             var stuAddress = modelBuilder.Entity<StudentAddress5>();
21 
22             //1. 设置主键 
23             stu.HasKey<string>(s => s.studentKey);
24             stuAddress.HasKey<string>(s => s.stuAddressId);   //为什么需要动态设置主键,有待研究??
25 
26             //2. 设置非空   (扩展:IsOptional 设置可空)
27             stu.Property(p => p.stuName).IsRequired();
28 
29             //3. 设置最大值(不能设置最小值)
30             stu.Property(p => p.stuTxt1).HasMaxLength(10);
31 
32 
33             //4. 修改列的名称、排序、类型
34             stuAddress.Property(p => p.stuAddrssName2).HasColumnName("myAddress2").HasColumnOrder(1).HasColumnType("varchar");
35 
36             //5.修改表名
37             stu.Map<Student5>(c =>
38             {
39                 c.ToTable("MyStudent");
40 
41             });
42 
43             //6.将一个实体映射成多张表,并分别给其命名
44             //stuAddress.Map<StudentAddress5>(c =>
45             //{
46             //    c.Properties(p => new
47             //    {
48             //        p.stuAddressId,
49             //        p.stuAddressName
50             //    });
51             //    c.ToTable("MyStuAddress1");
52             //}).Map<StudentAddress5>(c =>
53             //{
54             //    c.Properties(p => new
55             //    {
56             //        p.stuAddressId,
57             //        p.stuAddrssName2
58             //    });
59             //    c.ToTable("MyStuAddress2");
60             //});
61 
62 
63 
64 
65             //三. 将Game实体的配置添加进来
66             modelBuilder.Configurations.Add(new GameConfiguration());
67 
68             base.OnModelCreating(modelBuilder);
69         }
70     }
1    <!--正宗的CodeFirst Fluent API-->
2     <add name="dbContext5" connectionString="data source=localhost;initial catalog=CodeFirstDB5;persist security info=True;user id=sa;password=123456;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
3    

三. 总结

   无论是DataAnnotation还是Fluent API,都会发现一个现象,当数据库结构发生变化的时候,就会抛出异常,不得不把数据库删除,重新生成,这样就会导致原数据库中的数据丢失,在实际开发中,显然是不可取的。那么为什么会抛异常呢?怎么解决这个数据丢失的问题呢?详见下一个章节:数据库初始化策略和数据迁移。

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

 

posted @ 2017-11-10 19:47  Yaopengfei  阅读(1315)  评论(0编辑  收藏  举报