EF Code First多个Context上下文,使用一个DB数据库,附带identity数据表扩展。使用MySQL或者SqlServer
EF实际使用过程中,常常会出现多个Context上下文单位情况,有时候多个DB数据库持久化,有时候也会用一个DB数据持久化。如果是用云DB持久化,多个DB数据库就会增加成本。
新建一个如下结构的解决方案 Model1中放identity及扩展表
Model2放自定义的DBContext
WebApp来测试持久化 引用Model1和Model2
一、Model1NuGet安装EF (MySQL)
1、 Pomelo.EntityFrameworkCore.MySql
2、Pomelo.EntityFrameworkCore.MySql.Design
3、Microsoft.EntityFrameworkCore.Tools
如果是SqlServer则安装1、Microsoft.EntityFrameworkCore
2、Microsoft.EntityFrameworkCore.SqlServer
由于EF的强大功能,正文的具体实现过程都一样(就是数据链接字符串有一点区别)。
Model2修改csproj安装EF,将Model1csproj的ItemGroup复制到Model2中
二、新建identity用户角色实体类和数据库上下文
用户类和角色类
public class ApplicationUser : IdentityUser
{
//扩展用户属性
}
public class ApplicationRole : IdentityRole
{
//扩展角色属性
}
数据库上下文
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
Model2中添加实体类及数据库上下文
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
三、在appsettings.json文件中配置数据库连接字符串
"ConnectionStrings": {
"DefaultConnection": "Server=127.0.0.1;database=MoreContestTest;uid=root;password=pwd123456;TreatTinyAsBoolean=true"
},
注意TreatTinyAsBoolean=true 最好加上 原因:bool类型字段对应到ef会生产bit字段。如果不在连接字符串中添加TreatTinyAsBoolean=true 插入数据的时候会报Unable to cast object of type 'System.Boolean' to type 'System.Int16这个错
SqlServer链接字符串
"ConnectionStrings": {
"DefaultConnection": "Server=WIN-01406120129\\SQLEXPRESS;Database=MoreContestTest;Trusted_Connection=True;MultipleActiveResultSets=true"
},
四、在Startup文件中注册数据库上下文服务和对identity进行相关设置
services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<BloggingContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
现在数据库上下文连接字符串 全部指向了一个数据库
五、迁移(在程序包管理控制台中)
首先是Model1 默认项目必须选中Model1
1、输入Enable-Migrations
2、输入Add-Migration Initial -Context ApplicationDbContext建立快照
由于有多个上下文必须添加-Context ApplicationDbContext指定上下文
3、输入 Update-Database -Context ApplicationDbContext 升级数据库
4、完成之后 查看数据库生成情况
5、继续首先是Model2 默认项目必须选中Model2
按顺序执行下面三条指令
Enable-Migrations
Add-Migration Initial -Context BloggingContext
Update-Database -Context BloggingContext
这时候Model2中定义的表就追加到数据库中了
那么这样定义 究竟能不能用呢?
六、我们现在测试一下 Model1数据库写入情况
1、在webApp项目中添加Model1Test控制器
#region 依赖注入
private readonly RoleManager<ApplicationRole> _roleManager;
private readonly UserManager<ApplicationUser> _userManager;
public Model1TestController(
UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager)
{
_roleManager = roleManager;
_userManager = userManager;
}
#endregion
public async Task<IActionResult> IndexAsync()
{
ApplicationUser user = new ApplicationUser
{
UserName = "Admin"
};
var result = await _userManager.CreateAsync(user, "123456");
if (result.Succeeded)
{
return Content("yes");
}
return Content("no");
}
现在访问一下对应的地址 看能否正常写入数据
写入成功 到数据库中查看数据是否写入成功
2、继续测试写入Model2数据库写入情况
private BloggingContext _context;
public Model2TestController(BloggingContext context)
{
_context = context;
}
public async Task<IActionResult> IndexAsync()
{
Blog blog = new Blog
{
Url = "Test"
};
await _context.AddAsync(blog);
int x =await _context.SaveChangesAsync();
if (x > 0)
{
return Content("ok");
}
return Content("no");
}
现在访问一下对应的地址 看能否正常写入数据
写入正常
七、测试一下 Model1的自定义表 然后添加一个控制器 测试混合写入
1、在Model1中添加TableTest1实体类
public class TablesTest1
{
public int TablesTest1Id { get; set; }
public string TablesTest1Name { get; set; }
}
2、ApplicationDbContext中添加映射
public DbSet<TablesTest1> TablesTest1 { get; set; }
3、在Model1中启动迁移
Add-Migration Initial1 -Context ApplicationDbContext
Update-Database -Context ApplicationDbContext
表成功追加到数据库中
最后测试写入
5、新建MoreContest控制器
private ApplicationDbContext _applicationDbContext;
private BloggingContext _bloggingContext;
private readonly RoleManager<ApplicationRole> _roleManager;
private readonly UserManager<ApplicationUser> _userManager;
public MoreContestController(
UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager,
ApplicationDbContext applicationDbContext,
BloggingContext bloggingContext)
{
_roleManager = roleManager;
_userManager = userManager;
_applicationDbContext = applicationDbContext;
_bloggingContext = bloggingContext;
}
public async Task<IActionResult> AddAsync()
{
//使用Identity
ApplicationUser user = new ApplicationUser
{
UserName = "Admin2"
};
var result = await _userManager.CreateAsync(user, "123456");
//使用ApplicationDbContext
Blog blog = new Blog
{
Url = "Test2"
};
_bloggingContext.Add(blog);
int x = _bloggingContext.SaveChanges();
//使用BloggingContext
TablesTest1 tablesTest1 = new TablesTest1
{
TablesTest1Name = "tablesTest2"
};
_applicationDbContext.Add(tablesTest1);
int y = _applicationDbContext.SaveChanges();
if (result.Succeeded && x>0 && y>0)
{
return Content("ok");
}
return Content("no");
}
现在访问一下对应的地址 看能否正常写入数据
全部写入成功