Entity Framework Code First 中使用 Fluent API 笔记。
在做MVC+EF CodeFirst 的Demo时,碰到的问题,
在组册用户时,要让用户输入确认密码,但是数据库中又不需要保存这个字段,解决方案很多了,这里我列出通过EF Code First的解决方案。
UserInfo实体
public class UserInfoModel { [UIHint("HiddenInput")] public int UserId { get; set; } [Display(Name = "用户名")] public string UserName { get; set; } [Display(Name = "密码")] [DataType(DataType.Password)] public string UserPwd { get; set; } [Display(Name = "确认密码")] [DataType(DataType.Password)] public string ConfirmUserPwd { get; set; } public string Email { get; set; } public DateTime RegisterDate { get; set; } [Display(Name = "备注")] public string Memo { get; set; } public virtual RoleInfoModel Role { get; set; } }
//UserInfo的Fluent API 配置类 public class UserInfoConfiguration : EntityTypeConfiguration<UserInfoModel> { public UserInfoConfiguration() { HasKey(c => c.UserName); Property(c => c.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); //通过Map也可以忽略 //Map(l => //{ // l.Properties(x => new { x.UserId, x.UserName, x.UserPwd, x.Email, x.RegisterDate, x.Memo }); //}); Ignore(c => c.ConfirmUserPwd); //忽略这个属性 } }
关于EntityTypeConfiguration<TModel>.Map(),这个方法很强大。
定义:
public class EntityTypeConfiguration<TEntityType> : StructuralTypeConfiguration<TEntityType> where TEntityType : class { //……省略N行 public EntityTypeConfiguration<TEntityType> Map(Action<EntityMappingConfiguration<TEntityType>> entityMappingConfigurationAction); //…… }
具体使用在以下5个方面:
1.可以实现同一个实体映射到不同的表,也就是分割实体。
现有StudentInfo实体类如下:
public class Student { public Student() { } public string StudentId { get; set; } public string StudentName { get; set; } public bool Sex { get; set; } public DateTime Birthday { get; set; } public string Email { get; set; } public string QQ { get; set; } public string MobilePhone { get; set; } public string FixedPhone { get; set; } public byte[] Photo { get; set; } }
public class StudentConfig : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Student> { public StudentConfig() { HasKey(c => c.StudentId); Map(c => { c.Properties(l => new { l.StudentName, l.Sex, l.QQ, l.FixedPhone, l.MobilePhone }); c.ToTable("StudentBasicInfo"); }); Map(c => { c.Properties(l => new { l.Photo }); c.ToTable("StudentPhoto"); }); } }
生成的数据库表:
2.可以实现多个实体映射到同一个表。
现有student和studentphoto实体类:
public class Student { public Student() { }
public string StudentId { get; set; }
public string StudentName { get; set; } public bool Sex { get; set; } public DateTime Birthday { get; set; } public string Email { get; set; } public string QQ { get; set; } public string MobilePhone { get; set; } public string FixedPhone { get; set; }
public StudentPhoto Photo { get; set; }
} public class StudentPhoto {
public string StudentId { get; set; }
public byte[] Photo { get; set; }
public Student student { get; set; }
}
public class StudentConfig : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Student> { public StudentConfig() { HasKey(c => c.StudentId);
HasRequired(c => c.Photo).WithRequiredDependent(c => c.student);
ToTable("student"); } } public class StudentPhotoConfig : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<StudentPhoto> { public StudentPhotoConfig() { HasKey(c => c.StudentId); ToTable("student"); } }
要实现这个功能要注意以下几点:
1.实体之间要有一对一的关系(实体中绿色字体)2.实体之间要有完全相同的主键(实体中红色字体)3.配着类中要指明一对一的关系(StudentConfig 类中红色字体)4.相同的表名。(ToTable("student");)
生成的数据库表:
3.可以实现每个层次结构一张表 (TPH) 继承
4.可以实现每个类型一张表 (TPT) 继承
5.可以实现每个具体类型一张表 (TPC) 继承