1.示例项目概览
第一步,添加EntityFramework到项目中,一条命令搞定。打开Nuget控制台,输入如下语句:
PM> install-package entityframework
2.建立实体
首先,为各实体公共属性提取出来放在基类EntityBase中,所有实体继承自EntityBase。
public class EntityBase { //主键Id public int Id { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime CreateTime { get; set; } public EntityBase() { CreateTime = DateTime.Now; } }
Student实体代码如下:
public class Student:EntityBase { public string Name { get; set; } public DateTime? Birthday { get; set; } public string Phone { get; set; } public string Email { get; set; } public string Address { get; set; } }
Teacher实体代码:
public class Teacher:EntityBase { public string Name { get; set; } public string Phone { get; set; } public string Email { get; set; } public string Subject { get; set; } public int StudentCount { get; set; } }
3.实体配置
同样,为了节省码量,实体配置也建一个基类MapBase<T>,所有实体配置类(继承自EntityBase)都继承基类EntityBase<T>,方便配置。
public class MapBase<T>:EntityTypeConfiguration<T> where T:EntityBase { public MapBase(string tableName=null) { //表名配置 tableName = tableName ?? typeof (T).Name; ToTable(tableName); //关键配置(int 自增主键) HasKey(m => m.Id) .Property(m => m.Id) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); } }
表名默认为实体为,主键为int自增。
Student和Teacher实体的配置:
public class StudentMap:MapBase<Student> { public StudentMap() { //属性配置 Property(m => m.Name) .HasMaxLength(20) .IsRequired(); Property(m => m.Address) .HasMaxLength(200) .IsRequired(); Property(m => m.Email) .IsUnicode(false) .HasMaxLength(255); Property(m => m.Phone) .IsUnicode(false) .HasMaxLength(11) .IsRequired(); } }
public class TeacherMap:MapBase<Teacher> { public TeacherMap() { Property(m => m.Name) .HasMaxLength(20) .IsRequired(); Property(m => m.Phone) .IsUnicode(false) .IsRequired(); Property(m => m.Email) .IsUnicode(false) .HasMaxLength(255); Property(m => m.Subject) .HasMaxLength(50); } }
继承了EntityBase之后,主键的配置和表名的映射都由基类实现。这里说一下Fluent配置:IsUnicode(false)表示配置数据库字段类型为varchar,string类型的属性默认映射到数据库是nvarchar类型,更多Fluent相关的知识园子也很多,不多介绍。
4.EF数据操作上下文
实体配置完后,开始配置DbContext。
public class CodeFirstDbContext:DbContext { /// <summary> /// 数据库连接配置 /// </summary> public CodeFirstDbContext() :base("name=codeFirstConnectionStr") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { //EF之前的写法 //modelBuilder.Configurations.Add(new StudentMap()); //modelBuilder.Configurations.Add(new TeacherMap()); //EF6之后的写法 modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly()); //加载当前运行的程序集配置 //modelBuilder.Configurations.AddFromAssembly(typeof (MapBase<>).Assembly); //指定程序集加载配置 base.OnModelCreating(modelBuilder); } }
EF6之后简化了model build,可以直接利用Configurations.AddFromAssembly()加载配置信息,不用再一一添加。
另外,ctor方法中的name=codeFirstConnectionStr中的codeFirstConnectionStr是数据连接字符串的名称,数据库连接配置如下:
<connectionStrings> <add name="codeFirstConnectionStr" providerName="System.Data.SqlClient" connectionString="server=.;database=CodeFirst_Demo;uid=sa;pwd=123456"/> </connectionStrings>
5.生成数据库,操作EF上下文
到这里,所有相关的配置都完成了,接下来就是生成数据库并做相关操作了。
class Program { static void Main(string[] args) { using (var ctx=new CodeFirstDbContext()) { ctx.Database.CreateIfNotExists(); ctx.Set<Student>().Add(new Student() { Name = "张三", Address = "深圳南山", Birthday =DateTime.Now.AddYears(-20), Email = "[email protected]", Phone = "13888888888" }); ctx.SaveChanges(); } using (var ctx = new CodeFirstDbContext()) { ctx.Set<Teacher>().Add(new Teacher() { Name = "李四", Email = "[email protected]", Phone = "13899999999", Subject = "软件工程:从入门到住院" }); ctx.SaveChanges(); } Console.Read(); } }
生成之后的数据库是这样的:
数据也写了进去:
5.小结
这个示例非常简单,并没有涵盖EF的所有相关知识,比如导航属性、并发配置、数据迁移等。在实际的项目中,DbContext并不会直接暴露出去,还会用Reponsitory或Service作基础方法的封装,又或结合DDD放在基础设施层。
时间: 2024-11-08 23:05:33