创建“空白解决方案”,名为 GiveCase 。
在解决方案里,添加ASP.NET5 Empty模板项目,名为 GiveCase.Web 。
实体基类:
1 /// <summary> 2 /// 实体 抽象基类 3 /// </summary> 4 /// <typeparam name="TKey">主键类型</typeparam> 5 public abstract class EntityBase<TKey> 6 { 7 /// <summary> 8 /// 主键 9 /// </summary> 10 public TKey Id { get; set; } 11 }
角色实体类
1 /// <summary> 2 /// 角色 实体类 3 /// </summary> 4 public class Role:EntityBase<int> 5 { 6 /// <summary> 7 /// 角色名 8 /// </summary> 9 public string Name { get; set; } 10 11 /// <summary> 12 /// 角色描述 13 /// </summary> 14 public string Description { get; set; } 15 16 /// <summary> 17 /// 用户集合 导航属性 18 /// </summary> 19 public virtual ICollection<User> Users { get; set; } 20 }
用户实体类:
1 /// <summary> 2 /// 用户 实体类 3 /// </summary> 4 public class User : EntityBase<int> 5 { 6 /// <summary> 7 /// 用户名 8 /// </summary> 9 public string Name { get; set; } 10 11 /// <summary> 12 /// 密码 13 /// </summary> 14 public string Password { get; set; } 15 16 /// <summary> 17 /// 角色Id 外键 18 /// </summary> 19 public int RoleId { get; set; } 20 21 /// <summary> 22 /// 角色 导航属性 23 /// </summary> 24 public virtual Role Role { get; set; } 25 }
打开project.json,在 "dependencies": {}中,添加:
"EntityFramework.Commands": "7.0.0-beta8", "EntityFramework.SqlServer": "7.0.0-beta8"
在"commands": {}中,添加:
"ef": "EntityFramework.Commands"
注: 如果你不需要手动迁移数据库,可以不要用安装 EntityFramework.Commands及配置其commands。
数据库上下文类:
1 /// <summary> 2 /// 数据库上下文类 3 /// </summary> 4 public class EFContext : DbContext 5 { 6 public DbSet<Role> Roles { get; set; } 7 public DbSet<User> Users { get; set; } 8 9 protected override void OnModelCreating(ModelBuilder modelBuilder) 10 { 11 #region 角色属性 12 modelBuilder.Entity<Role>().Property(r => r.Name).IsRequired(); 13 modelBuilder.Entity<Role>().Property(r => r.Description).HasMaxLength(300); 14 #endregion 15 16 #region 用户属性 17 modelBuilder.Entity<User>().Property(u => u.Name).IsRequired(); 18 modelBuilder.Entity<User>().Property(u => u.Password).IsRequired(); 19 #endregion 20 21 #region 配置关系 22 modelBuilder.Entity<Role>().HasMany(r => r.Users).WithOne(u => u.Role) 23 .ForeignKey(u => u.RoleId).WillCascadeOnDelete(); 24 #endregion 25 } 26 }
注: 配置属性及关系,这里采用是Fluent API方式,你可以在实体类代码中采用Data Annotations特性标注方式。
添加config.json,其代码:
{ "Data": { "Connection": { "ConnectionString": "Server=.;Database=GiveCase;User ID=sa;Password=123456;" } } }
修改Startup.cs中的方法:
1 public IConfigurationRoot Configuration { get; set; } 2 3 public Startup(IApplicationEnvironment appEnv) 4 { 5 var builder = new ConfigurationBuilder() 6 .SetBasePath(appEnv.ApplicationBasePath) 7 .AddJsonFile("config.json"); 8 9 Configuration = builder.Build(); 10 } 11 12 public void ConfigureServices(IServiceCollection services) 13 { 14 services.AddEntityFramework().AddSqlServer() 15 .AddDbContext<EFContext>(options => options 16 .UseSqlServer(Configuration["Data:Connection:ConnectionString"])); 17 }
在VS中的“程序包管理器控制台”(在dos也行)下,进入到项目根目录。
执行: dnx ef migrations add FristMigration
命令执行成功后,项目结构就填加了Migrations文件夹,里面会有ModelSnapshot文件。
此时并没有创建数据库,再执行: dnx ef database update
这样两步骤(添加数据库迁移,更新到数据库)就完成数据库创建。
打开project.json ,在"dependencies": {}中,添加:
"Microsoft.Framework.CodeGeneration": "1.0.0-beta8", "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-beta8",
在"commands": {}中,添加:
"gen": "Microsoft.Framework.CodeGeneration"
在VS中的“程序包管理器控制台”(在dos也行)下,进入到项目根目录。
我们添加Home控制器,执行: dnx gen controller -name HomeController
此时项目结构就添加Controllers和Views文件夹等,也添加了Microsoft.AspNet.Mvc程序集。
如何生成T4(GRUD)模板的控制器?
添加Role控制器,执行: dnx gen controller -name RoleController -m Role -dc EFContext
这样控制器代码,增删改查方法有了,相应的视图也生成了。
我们已经生成的代码,最好封装一下持久化操作。先不用泛型封装,添加接口:
1 public interface IRoleRepository : IDisposable 2 { 3 //IEnumerable和IQueryable 4 //二者在EF都会延迟加载,不同的是: 5 //IEnumerable是数据加载到内存,刷选在内存中的数据上执行 6 //IQueryable是查询和刷选在数据源中执行 7 8 //TODO:复杂条件查询和异步方法 9 10 //IQueryable<Role> GetRoles(); 11 IEnumerable<Role> GetRoles(); 12 Role GetRole(int? id); 13 void Create(Role role); 14 void Update(Role role); 15 void Delete(int? id); 16 }
其实现代码:
1 public class RoleRepository : IRoleRepository 2 { 3 private EFContext db; 4 public RoleRepository(EFContext _db) 5 { 6 db = _db; 7 } 8 9 public IEnumerable<Role> GetRoles() 10 { 11 return db.Roles.ToList(); 12 } 13 14 public Role GetRole(int? id) 15 { 16 return db.Roles.Single(m => m.Id == id); 17 } 18 19 public void Create(Role role) 20 { 21 db.Roles.Add(role); 22 db.SaveChanges(); 23 } 24 25 public void Delete(int? id) 26 { 27 db.Roles.Remove(db.Roles.Single(m => m.Id == id)); 28 db.SaveChanges(); 29 } 30 31 public void Update(Role role) 32 { 33 db.Update(role); 34 db.SaveChanges(); 35 } 36 37 //public void Save() 38 //{ 39 // db.SaveChanges(); 40 //} 41 42 #region 释放资源 43 private bool disposed = false; 44 protected virtual void Dispose(bool disposing) 45 { 46 if (!disposed) 47 { 48 if (disposing) { db.Dispose(); } 49 } 50 disposed = true; 51 } 52 public void Dispose() 53 { 54 Dispose(true); 55 System.GC.SuppressFinalize(this); 56 } 57 #endregion 58 }
工作单元的目的,保证多个数据仓库一起操作保持一致。先创建接口:
1 public interface IUnitOfWork 2 { 3 //TODO:事务,异步 4 void SaveChanges(); 5 }
其实现:
1 public class UnitOfWork : DbContext, IUnitOfWork 2 { 3 public new void SaveChanges() 4 { 5 base.SaveChanges(); 6 } 7 }
基类封装:
1 public class BaseRepository 2 { 3 protected IUnitOfWork UnitOfWork { get; set; } 4 5 protected EFContext db 6 { 7 get { return (EFContext)UnitOfWork; } 8 } 9 10 public BaseRepository(IUnitOfWork _unitOfWork) 11 { 12 if (_unitOfWork == null) 13 { 14 throw new ArgumentNullException("_unitOfWork"); 15 } 16 17 UnitOfWork = _unitOfWork; 18 } 19 20 public void Save() 21 { 22 db.SaveChanges(); 23 } 24 25 protected virtual DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class 26 { 27 return db.Set<TEntity>(); 28 } 29 30 protected virtual void SetEntityState(object entity, EntityState entityState) 31 { 32 db.Entry(entity).State = entityState; 33 } 34 }
篇幅有些长了,下一章再说控制器基类封装,依赖注入,界面展示……