EF全称Entity Framework,我们都知道java对应数据库就有很多的orm框架,而且很好用比如hibernate,当然EF并没有说用到xml去配置映射,EF的映射是直接写到代码里,通过一定的规则交给.Net Framework去处理映射关系的。
EF有Code First,DB Frist,DB First就是先建数据库,然后根据数据库自动映射生成对应的C#类,Code First就是先写C#代码,然后通过一些特定的指令去生成数据库表。
我们以vs2017+SqlServer2012开发环境具体说下Code First的创建步骤:
首先我们新建一个类库项目,在类库项目添加新建项-数据,选择ADO.NET实体数据模型:
选择来自数据库的Code First:
点击下一步,点击配置你要设置的数据库名称等,这样处理的好处是,vs会自动生成app.config的连接字符串以及一些其他操作。
我这里是因为之前创建过这个test连接,所以直接会有历史记录。我们继续点击下一步,选中表:
点击完成。
原来没有新建EF时的原始类库架构图:
点击完成之后,自动生成的架构:
我们可以看到,自动生成了一个DBcontext的上下文类。我们看下这个类的代码:
public partial class DBContext : DbContext { public DBContext() : base("name=DBContext") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { } }
然后我们来新建两个类,学生类和班级类:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations.Schema; namespace EFLibrary { public class Students { /// <summary> /// ID 自动生成 自增列 /// </summary> [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public string StName { get; set; } public string StNumber { get; set; } /// <summary> /// 班级ID /// </summary> public int StuCalssId { get; set; } public StuClass StuClass { get; set; } } }
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EFLibrary { public class StuClass { /// <summary> /// ID 自动生成 自增列 /// </summary> [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public string ClaName { get; set; } public string ClaIntro { get; set; } public List<Students> Students { get; set; } } }
我们可以看到班级和学生有一个外键关系,然后这里在学生类中有一个StuClass的对象,而在班级类里有一个Students的集合,这里就很好的说明了他们的表关系,一个班级里可以有多个学生,而一个学生只能有一个班级,所以学生和班级是一对多的关系。
然后我们需要在DBContext上下文去配置这两个类的表映射,以及相应的表外键关系:
namespace EFLibrary { using System; using System.Data.Entity; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; public partial class DBContext : DbContext { public DBContext() : base("name=DBContext") { } //设置 实体-表 映射 public DbSet<StuClass> StuClasses { get; set; } public DbSet<Students> Students { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { //处理表外键关系 modelBuilder.Entity<StuClass>().HasMany(c => c.Students).WithRequired(s => s.StuClass).HasForeignKey(c => c.StuCalssId) //不使用级联删除功能 需要最后加上WillCascadeOnDelete(false)语句即可 //modelBuilder.Entity<StuClass>().HasMany(c => c.Students).WithRequired(s => s.StuClass).HasForeignKey(c => c.StuCalssId).WillCascadeOnDelete(false); } } }
如此基本上编码类已经完成,下面需要运行命令去交给EF生成数据库表,我们先看下现在的数据库是没有任何表的:
在vs中我们打开程序包管理器控制台,一定要记得把当前类库项目设为默认项目:
一、我们需要执行三条命令,这三条命令是有先后顺序的:
1.enable-migrations(-force)
我们发现,在运行完该条命令后,会自动生成一个类,我们不用管这个类,
二、执行第二条命令
add-migration temp(temp你可以随意取名字)
执行完命令后会自动生成一个temp.cs的类
三、执行第三条命令,也就是更新数据库的命令
update-database
执行完成之后,如果成功会有提示:
表示已成功。
我们刷新下数据库,发现表已经按照我们预想的生成成功了:
对应外键关系也处理好了。
我们发现这里生成的数据表名称是带复数的,那么如何设置表名称和类名称一致呢,我们需要在这里加上这句代码就可以成功解决:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //这句是不要将EF生成的sql表名不要被复数 就是表名后面不要多加个S modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); }
总结:EFCode First主要用到了三条命令:
1.enable-migrations
2.add-migration temp(temp可任意取名字)
3.update-database