Entity Framework学习二:定义数据结构
也可以在微软网站查找完整对应列表:http://msdn.microsoft.com/en-us/library/cc716729(v=vs.110).aspx
2.配置数据结构
可以使用以下几种方式来配置
• Attributes
• Configuration Classes
• The DbModelBuilder API
2.1使用Attributes方式:
public class Person { public int PersonId { get; set; } [MaxLength(30)] public string FirstName { get; set; } [MaxLength(30)] public string LastName { get; set; } [StringLength(1, MinimumLength = 1)] [Column(TypeName = "char")] public string MiddleName { get; set; } }
创建出来的数据表结构如上,跟你在类中定义的Attribute是对应的。
2.2使用DbModelBuilder API
使用这种方法需要override DbContext下的OnModelCreating方法,使用此方法就不用再用上面的Attribute方法设置了.
public class Context:DbContext { public Context() : base("ConnectionString")//为配置文件中连接字符串名称 { } public DbSet<Person> People { get; set; } public DbSet<Company> Companies { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Person>().Property(p => p.FirstName) .HasMaxLength(30); modelBuilder.Entity<Person>().Property(p => p.LastName) .HasMaxLength(30); modelBuilder.Entity<Person>().Property(p => p.MiddleName) .HasMaxLength(1) .IsFixedLength() .IsUnicode(false); } }
这里有个问题,如果只有一个表,那么在重写里面代码不到,如果很多表,就会很多很乱,这时候我们增加Person类的PersonMap类来解决
public class PersonMap : EntityTypeConfiguration<Person> { public PersonMap() { Property(p => p.FirstName) .HasMaxLength(30); Property(p => p.LastName) .HasMaxLength(30); Property(p => p.MiddleName) .HasMaxLength(1) .IsUnicode(false) .IsFixedLength(); } }
这样定义以后我们只需要在DbContex的OnModelCreaing中注册就可以了。
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new PersonMap()); }
2.3定义关系
- 1对多关系
一个人可以有多个电话号码。我们创建Phone类
public class Phone { public int PhoneId { get; set; } public string PhoneNumber { get; set; } public int PersonId { get; set; } }在Phone中我们定义了PersonId作为外键。在Person类中定义ICollectionPhone> Phones,注意这里使用了virtual修饰,是为了延迟加载。在Person构造函数中初始化对象。
public class Person { public Person() { Phones = new HashSet<Phone>(); } public int PersonId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string MiddleName { get; set; } public virtual ICollection<Phone> Phones { get; set; } }那么接下来我们在前面定义的PersonMap类中定义Person可以包含多个Phone。代码如下(注意标记部分为新增代码):
public class PersonMap : EntityTypeConfiguration<Person> { public PersonMap() { Property(p => p.FirstName) .HasMaxLength(30); Property(p => p.LastName) .HasMaxLength(30); Property(p => p.MiddleName) .HasMaxLength(1) .IsUnicode(false) .IsFixedLength();this.HasMany(p => p.Phones) .WithRequired() .HasForeignKey(ph =>ph.PersonId); } }
接下来我们要在Contex中定义Dbset<Phone>.代码如下:
public class Context:DbContext { static Context() { Database.SetInitializer<Context>(null);//当Model发生改变时不自动创建数据库 } public Context() : base("ConnectionString")//为配置文件中连接字符串名称 { } public DbSet<Person> People { get; set; } public DbSet<Company> Companies { get; set; } public DbSet<Phone> Phones { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new PersonMap()); } }我们还要在数据库中创建表Phone已经Phone和Person的外键关联
以及要设置级联更新和级联删除,不然更新和删除是会报错。
- 多对多关系
考虑以下场景,一个公司可以有多位雇员,一个人也可以为多个公司工作。增加Company类
public class Company { public Company() { People = new HashSet<Person>(); } public int CompanyId { get; set; } public string Name { get; set; } public ICollection<Person> People { get; set; } } public class CompanyMap : EntityTypeConfiguration<Company> { public CompanyMap() { ToTable("Company"); } }
在Person类增加
public virtual ICollection<Company> CompanyList { get; set; }PersonMap类增加
HasMany(p => p.CompanyList) .WithMany(c => c.People) .Map(m => { m.ToTable("PersonCompany");//设置关联表名称 m.MapLeftKey("PersonId");// m.MapRightKey("CompanyId"); });
在Contex类增加如下标记的代码:
public class Context:DbContext { static Context() { Database.SetInitializer<Context>(null);//当Model发生改变时不自动创建数据库 } public Context() : base("ConnectionString")//为配置文件中连接字符串名称 { } public DbSet<Person> People { get; set; } public DbSet<Company> Companies { get; set; } public DbSet<Phone> Phones { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new PersonMap()); modelBuilder.Configurations.Add(new CompanyMap()); } }
接着我们要在数据库中增加表名为Company的数据表,结构如下:以及PersonCompany表:。注意这里有两个外键设置,分别对应People表中的PersonId和Company表中的CompanyId,并设置了级联删除关联。
下面是测试代码:
class Program { static void Main(string[] args) { Console.WriteLine("开始处理数据"); using (var context=new Context()) { var person = new Person { LastName = "Doe", FirstName = "John" }; person.CompanyList.Add(new Company { Name = "厂一" }); person.CompanyList.Add(new Company { Name = "厂二" }); context.People.Add(person); context.SaveChanges(); } Console.WriteLine("处理完毕"); Console.ReadKey(); } }
执行完以上代码可以发现在People表,Company表和PersonCompany表都增加了数据。删除People表或者Company表数据时会级联删除 PersonCompany表相关数据。
- 一对一关系
考虑如下场景,每个学生对应于一个人,增加Student类
public class Student { public int PersonId { get; set; } public Person Person { get; set; } public string CollegeName { get; set; } public DateTime EnrollmentDate { get; set; } } public class StudentMap : EntityTypeConfiguration<Student> { public StudentMap() { ToTable("Student");//表名为:Student HasRequired(s => s.Person) .WithRequiredDependent(p=> p.Student); //设置对应关系 HasKey(s => s.PersonId); //设置主键 Property(s => s.CollegeName) .HasMaxLength(50).IsRequired(); } }
public class Person { public Person() { Phones = new HashSet<Phone>(); CompanyList = new HashSet<Company>(); } public int PersonId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string MiddleName { get; set; } public virtual ICollection<Phone> Phones { get; set; } public virtual ICollection<Company> CompanyList { get; set; } public Student Student { get; set; } }
在Context类中增加:
public class Context:DbContext { static Context() { Database.SetInitializer<Context>(null);//当Model发生改变时不自动创建数据库 } public Context() : base("ConnectionString")//为配置文件中连接字符串名称 { } public DbSet<Person> People { get; set; } public DbSet<Company> Companies { get; set; } public DbSet<Phone> Phones { get; set; } public DbSet<Student> Students { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new PersonMap()); modelBuilder.Configurations.Add(new CompanyMap()); modelBuilder.Configurations.Add(new StudentMap()); modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); } }
测试代码:
using (var context=new Context()) { var person = new Person { FirstName = "张", LastName="三" }; person.Student =new Student { CollegeName = "test", EnrollmentDate = DateTime.Now }; context.People.Add(person); context.SaveChanges(); }