一. 前言
沉寂了约一个月的时间, 今天用一篇简单的文章重新回归博客, 主要来探讨一下 Fluent API 模式在实际项目中的使用流程.
1. Fluent API 属于 EF CodeFirst 模式的一种, EF 还有一种模式是 DataAnnotations, 两种模式各有千秋吧, 前面的 EF 系列已经详细介绍过他们的使用了, 本节主要介绍 Fluent API 模式在实际框架中的使用流程.
本节需要用到的技术有:
1:EF 的三种模式(四) 之 原生正宗的 CodeFirst 模式的默认约定
2:EF 的 CodeFirst 模式通过 DataAnnotations 修改默认协定
3:EF 的 CodeFirst 模式通过 Fluent API 修改默认协定
4:EF 的 CodeFirst 模式的四种初始化策略和通过 Migration 进行数据的迁移
2. 框架模式
这里不采用传统的三层架构 (DAL,BLL), 而是使用: Ypf.DTO,Ypf.Service,Ypf.IService,Ypf.Utils,Ypf.web 这种划分模式, 本节为了方便测试, 仅仅使用 Ypf.Service 和 Ypf.Test(控制台) 两个框架进行测试.
3. 业务模拟
1. 用户基本信息和角色基本信息, 不做关联
2. 用户信息增加了或者删除
3. 角色信息删除了或者增加
二. 使用步骤
1. 新建[Ypf.Service] 类库和[Ypf.Test] 控制台项目, 并分别通过 Nuget 安装 EF 程序集.
2. 在[Ypf.Service] 类库中新建 "UserInfor","RoleInfor" 实体类,"UserInforConfig","RoleInforConfig" 实体类对应的隔离出来的表的配置文件.
PS: 这里为了方便管理, 一张表对应一个 EF 的配置类文件, 比全部直接写在 OnModelCreating 方法中更清晰.
分享实体类代码:
- 1 /// <summary>
- 2 /// 用户表
- 3 /// </summary>
- 4 public class UserInfor
- 5 {
- 6 public string id { get; set; }
- 8 public string userName { get; set; }
- 10 public int userAge { get; set; }
- 11 14 }
- 15 /// <summary>
- 16 /// 角色信息
- 17 /// </summary>
- 18 public class RoleInfor
- 19 {
- 20 public string id { get; set; }
- 22 public string roleName { get; set; }
- 24 public int roleAge { get; set; }
- 25 }
分享表配置文件代码:
- /// <summary>
- /// UserInfor 实体对应表的配置
- /// </summary>
- class UserInforConfig :EntityTypeConfiguration<UserInfor>
- {
- public UserInforConfig()
- {
- this.ToTable("T_UserInfor");
- this.HasKey<string>(u => u.id).Property(u => u.id).HasColumnType("varchar").HasMaxLength(32);
- this.Property(u => u.userName).HasColumnType("varchar").HasMaxLength(50);
- this.Property(u => u.userAge).HasColumnType("int").IsRequired();
- }
- }
- /// <summary>
- /// RoleInfor 实体对应表的配置
- /// </summary>
- class RoleInforConfig : EntityTypeConfiguration<RoleInfor>
- {
- public RoleInforConfig()
- {
- this.ToTable("T_RoleInfor");
- this.HasKey<string>(u => u.id).Property(u => u.id).HasColumnType("varchar").HasMaxLength(32);
- this.Property(u => u.roleName).HasColumnType("varchar").HasMaxLength(50);
- this.Property(u => u.roleAge).HasColumnType("int").IsRequired();
- }
- }
3. 在[Ypf.Service] 类库中新建 EF 上下文 "YpfContext" 类, 使用 EF 的默认初始化策略(DB 不存在则创建, 实体不对应则报错) , 然后 override OnModelCreating 方法, 并通过反射一次性加载 EF 的所有 Fluent API 配置, 最后声明要映射的实体.
分享 EF 上下文的代码
- public class YpfContext:DbContext
- {
- /// <summary>
- /// 继承父类构造函数, ypfConnectionString 代表配置文件中连接字符串的名字
- /// </summary>
- public YpfContext():base("name=ypfConnectionString")
- {
- }
- /// <summary>
- /// OnModelCreating 方法重写, FluentAPI 对表的配置都是在该方法中, 但是当表数量多的话
- /// 该方法内部就会显得特别乱, 所以我们这里采用分离的方式, 一张表对应一个配置文件类,
- /// 最后全部注册到该方法中即可
- /// </summary>
- /// <param name="modelBuilder"></param>
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
- //1. 分开注册
- //modelBuilder.Configurations.Add(new UserInforConfig());
- //modelBuilder.Configurations.Add(new RoleInforConfig());
- //2. 一次性加载所有 Fluent API 的配置
- modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly());
- }
- public DbSet<UserInfor> UserInfor { get; set; }
- public DbSet<RoleInfor> RoleInfor { get; set; }
- }
4. 给[Ypf.Test] 配置数据库连接字符串, 并且进行一个简单的数据库查询操作, 会发现在 SQLServer 默认目录生成一个名为 "FrameFluentApiDB" 的数据库, 且表, 字段对应均正确.
分享数据库连接字符串代码:
- <connectionStrings>
- <add name="ypfConnectionString" connectionString="Data Source=localhost;Initial Catalog=FrameFluentApiDB;User ID=sa;Password=123456" providerName="System.Data.SqlClient" />
- </connectionStrings>
分享简单的数据库查询代码:
- class Program
- {
- static void Main(string[] args)
- {
- using (YpfContext db=new YpfContext())
- {
- var list = db.UserInfor.ToList();
- Console.WriteLine("创建成功");
- Console.ReadKey();
- }
- }
- }
运行后生成的数据库:
5. 给 UserInfor 实体增加一个 "userSex" 属性, 并在 UserInforConfig 文件中对该属性进行配置, 如下图, 再次运行代码, 报错, 提示上下文发生改变, 请走数据迁移.
修改后代码:
报错提示:
PS: 配置数据迁移策略固然可以解决该问题, 但我们这里用一种比较笨的方法, 关闭数据库初始化策略, 然后手动配置代码和修改数据库字段进行对应即可.
分享关闭数据库初始化策略的代码:
手动修改数据库和代码实体中的属性对应后重新运行代码, 运行成功.
!
作 者 : Yaopengfei(姚鹏飞)
博客地址 : http://www.cnblogs.com/yaopengfei/
声 明 1 : 本人才疏学浅, 用郭德纲的话说 "我是一个小学生", 如有错误, 欢迎讨论, 请勿谩骂 ^_^.
声 明 2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址, 否则保留追究法律责任的权利.
来源: https://www.cnblogs.com/yaopengfei/p/9663044.html