前言
EF 实体对象模型的创建
public class S_User { public S_User(){this.S_Logs = new List<S_Log>();} public long ID { get; set; } public long RoleID { get; set; } public string UserName { get; set; } public string UserPwd { get; set; } public string IsUse{ get; set; } public string Phone{ get; set; } public string Email{ get; set; } public string Remark { get; set; } public virtual S_Role S_Role { get; set; } public virtual ICollection<S_Log> S_Logs { get; set; } }
2. 接下来是日志类S_Log,与此关联的对象有S_User,即一条日志只属于某一个用户。因此S_Log的代码如下:
public class S_Log { public long ID { get; set; } public long UserID { get; set; } public DateTime OperationDate { get; set; } public string OperationMenu{ get; set; } public string OperationType{ get; set; } public string Detail{ get; set; } public virtual S_User S_User { get; set; } }
3. 接下来是角色类S_Role,与此关联的对象有S_User和S_Menu,即一个角色可以包含多个用户,一个角色用户可以操作多个菜单页面。
因此S_Role代码如下:
public class S_Role { public S_Role(){ this.S_Users = new List<S_User>();} public long ID { get; set; } public string RoleName { get; set; } public string Remark { get; set; } public virtual ICollection<S_User> S_Users { get; set; } public virtual ICollection<S_Menu> S_Menus { get; set; } }
4. 接下来是菜单类S_Menu,与此类关联的对象有S_Role,即一个菜单页面可以被多个角色用户操作。但是S_Menu采用的是树级结构的方式,
一个父级菜单包含多个子菜单,一个子菜单只属于某一个父级菜单。即子菜单的PID是父级菜单的ID,因此S_Menu的PID因该是S_Menu中ID
的外键,由于顶级的父级菜单是没有父级菜单的,所以我们可以设置PID为可空类型,S_Menu的代码如下:
public class S_Menu { public long ID { get; set; } public string MenuName { get; set; } public string Icon { get; set; } public string Link { get; set; } public string IsUse { get; set; } public int Level { get; set; } public int SerialNO { get; set; } public Nullable<long> PID { get; set; } public string Remark { get; set; } public virtual ICollection<S_Role> S_Roles { get; set; } public virtual S_Menu Parent { get; set; } public virtual ICollection<S_Menu> Children { get; set; } }
5. 接下来是字典类S_TypeInfo,由于没有与之关联的对象,因此,我们只需简单定义属性就可以呢。S_TypeInfo的代码如下:
public class S_TypeInfo { public long ID { get; set; } public string Type { get; set; } public string Name { get; set; } public string Value { get; set; } public string Remark { get; set; } }
6. 注意:一对多关系中,我们需要对外键的实体进行构造函数进行重载,比如角色中包含多个用户,public S_Role(){this.S_Users = new
List<S_User>();}。多对多关系就不用进行此操作呢。还有一点就是外键必须显示的设置,比如RoleID。因为后面在Fluent API映射数据时
,配置文件中需要用到。
EF 实体上下文的创建
public class EFDbContext : DbContext { public EFDbContext() : base("EFDbContext") { } public EFDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { } public DbSet<S_Log> S_Logs { get; set; } public DbSet<S_Menu> S_Menus { get; set; } public DbSet<S_Role> S_Roles { get; set; } public DbSet<S_TypeInfo> S_TypeInfos { get; set; } public DbSet<S_User> S_Users { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new S_LogMap()); modelBuilder.Configurations.Add(new S_MenuMap()); modelBuilder.Configurations.Add(new S_RoleMap()); modelBuilder.Configurations.Add(new S_TypeInfoMap()); modelBuilder.Configurations.Add(new S_UserMap()); modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); //表中都统一设置禁用一对多级联删除 modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); //表中都统一设置禁用多对多级联删除 base.OnModelCreating(modelBuilder); } }
Fluent API 配置数据库映射
public class S_UserMap : EntityTypeConfiguration<S_User> { public S_UserMap() { // Primary Key this.HasKey(t => t.ID); // Properties this.Property(t => t.UserName).IsRequired().HasMaxLength(20); this.Property(t => t.UserPwd).IsRequired().HasMaxLength(25); this.Property(t => t.IsUse).IsRequired().HasMaxLength(2); this.Property(t => t.Phone).IsOptional().HasMaxLength(11); this.Property(t => t.Email).IsOptional().HasMaxLength(25); this.Property(t => t.Remark).IsOptional().HasMaxLength(20); // Table & Column Mappings this.ToTable("S_User"); this.Property(t => t.ID).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); this.Property(t => t.UserName).HasColumnName("UserName"); this.Property(t => t.UserPwd).HasColumnName("UserPwd"); this.Property(t => t.IsUse).HasColumnName("IsUse"); this.Property(t => t.Phone).HasColumnName("Phone"); this.Property(t => t.Email).HasColumnName("Email"); this.Property(t => t.Remark).HasColumnName("Remark"); this.Property(t => t.RoleID).HasColumnName("RoleID"); // Relationships this.HasRequired(t => t.S_Role).WithMany(t => t.S_Users).HasForeignKey(d => d.RoleID); } }
public class S_RoleMap : EntityTypeConfiguration<S_Role> { public S_RoleMap() { // Primary Key this.HasKey(t => t.ID); // Properties this.Property(t => t.RoleName).IsRequired().HasMaxLength(20); this.Property(t => t.Remark).IsRequired().HasMaxLength(200); // Table & Column Mappings this.ToTable("S_Role"); this.Property(t => t.ID).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); this.Property(t => t.RoleName).HasColumnName("RoleName"); this.Property(t => t.Remark).HasColumnName("Remark"); // Relationships this.HasMany(t => t.S_Menus) .WithMany(t => t.S_Roles) .Map(m => { m.ToTable("S_RoleMenu"); m.MapLeftKey("RoleID"); m.MapRightKey("MenuID"); }); } }
public class S_MenuMap : EntityTypeConfiguration<S_Menu> { public S_MenuMap() { this.HasKey(t => t.ID); // Properties this.Property(t => t.MenuName).IsRequired().HasMaxLength(20); this.Property(t => t.Icon).IsRequired().HasMaxLength(20); this.Property(t => t.Link).IsRequired().HasMaxLength(20); this.Property(t => t.IsUse).IsOptional().HasMaxLength(2); this.Property(t => t.Remark).IsOptional().HasMaxLength(200); // Table & Column Mappings this.ToTable("S_Menu"); this.Property(t => t.ID).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); this.Property(t => t.MenuName).HasColumnName("MenuName"); this.Property(t => t.Icon).HasColumnName("Icon"); this.Property(t => t.Link).HasColumnName("Link"); this.Property(t => t.IsUse).HasColumnName("IsUse"); this.Property(t => t.Level).HasColumnName("Level"); this.Property(t => t.SerialNO).HasColumnName("SerialNO"); this.Property(t => t.PID).HasColumnName("PID"); this.Property(t => t.Remark).HasColumnName("Remark"); // Relationships this.HasOptional(t => t.Parent) .WithMany(t => t.Children) .HasForeignKey(d => d.PID); } }
初始化数据库
public class InitializerUserData : CreateDatabaseIfNotExists<EFDbContext> { protected override void Seed(EFDbContext context) { //添加默认角色 S_Role role = new S_Role(); role.ID = NewID.NewComb(); role.RoleName = "管理员"; role.Remark = "管理系统所有操作"; //添加默认用户 long RoleID = role.ID; S_User user = new S_User(); user.ID = NewID.NewComb(); user.RoleID = RoleID; user.UserName ="admin"; user.UserPwd=DESEncrypt.Encrypt("123"); user.IsUse="是"; user.Phone="12345678901"; user.Email="demo@hotmail.com"; user.Remark = "系统管理员账户"; user.S_Role = role; context.S_Roles.Add(role); context.S_Users.Add(user); context.SaveChanges(); } }
2. DatabaseInitializer的代码如下:
public static class DatabaseInitializer { public static void Initialize() { Database.SetInitializer(new InitializerUserData()); using (var db = new EFDbContext()) { db.Database.Initialize(false); } } }
3. 注意:数据的初始化有三种方式,本示例选择CreateDatabaseIfNotExists,也就是如果数据库不存在我们就进行创建,如果数据库存在,
我们就只能通过数据迁移来进行对数据库的修改操作。
4. 在web工程的asp.net mvc 项目中的Global.asax添加对Initializer工程的引用,添加对数据库初始化操作的注册。如下显示:
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); DatabaseInitializer.Initialize(); } }
备注