手机版

利用EF6简单实现多租户的应用

时间:2021-08-20 来源:互联网 编辑:宝哥软件园 浏览:

什么是多租户

网上有好多解释,有些上升到了架构设计,让你觉得似乎非常高深莫测,特别是目前流行的雄激素结合蛋白架构中就有提到多租户(IMustHaveTenant),其实说的简单一点就是再每一张数据库的表中添加一个TenantId的字段,用于区分属于不同的租户(或是说不同的用户组)的数据。关键是现实的方式必须对开发人员来说是透明的,不需要关注这个字段的信息,由后台或是封装在基类中实现数据的筛选和更新。

基本原理

从新用户注册时就必须指定用户的TenantId,我的例子是用公司Id,公司信息做为TenantId,哪些用户属于不同的公司,每个用户将来只能修改和查询属于本公司的数据。

接下来就是用户登录的时候获取用户信息的时候把TenantId保存起来,asp.net mvc(不是核心)是通过身份2.0实现的认证和授权,这里需要重写部分代码来实现。

最后用户对数据查询/修改/新增时把用户信息中TenantId,这里就需要设定一个过滤器(过滤器)和每次保存更改的插入TenantId

如何实现

第一步,扩展Asp.net身份用户属性,必须新增一个TenantId字段,根据Asp.net最有价值球员自带的项目模板修改IdentityModels.cs这个文件

//您可以通过向应用程序用户类添加更多属性来为用户添加配置文件数据,请访问http://go.microsoft.com/fwlink/?LinkID=317594了解更多信息。公共类应用程序用户:标识用户{公共异步taskcaleimsidentity generate useridentitysync(user managed application user manager,string authenticationType) { //请注意,验证类型必须与CookieAuthenticationOptions中定义的类型匹配身份验证类型变量用户身份=等待管理器CreateIdentityAsync(此,authenticationType);//在此添加自定义用户声明用户身份.添加声明(新声明(' http://模式。微软。' com/identity/理赔/tenantid ',这TenantId。ToString()));用户身份。添加索赔(新索赔('公司名称,这公司名称));用户身份。添加声明(新声明(“启用什么”,这个启用图表。ToString()));用户身份。添加索赔(新索赔('全名,这。全名);用户身份。添加索赔(新索赔(' AvatarsX50 ',这化身sx50));用户身份.添加索赔(新索赔(' AvatarsX120 ',这头像sx120));返回user identity } public async taskcaleimsidentity generateuseridentitysync(用户管理器应用程序用户管理器){//请注意,验证类型必须与CookieAuthenticationOptions中定义的类型匹配身份验证类型变量用户身份=等待管理器CreateIdentityAsync(此,DefaultAuthenticationTypes .应用程序CooKie);//在此添加自定义用户声明返回用户身份}[显示(名称='全名)]公共字符串全名{ get设置;}[显示(名称='性别)]public int Gender { get;设置;} public int AccountType { get设置;}[显示(名称='所属公司)]公共字符串CompanyCode { get设置;}[显示(名称='公司名称)]公共字符串CompanyName { get设置;}[显示(名称='是否在线)]public bool ISonline { get;设置;}[显示(名称='是否开启聊天功能)]public bool EnabledChat { get;设置;}[显示(名称='小头像)]公共字符串AvatarsX50 { get设置;}[显示(名称='大头像)]公共字符串AvatarsX120 { get设置;}[显示(名称='租户ID ')]public int TenantId { get;设置;} }公共类ApplicationDbContext : IdentityDbContextApplicationUser { public ApplicationDbContext(): base('默认连接',throwifv 1 schema 3360 false)=Database .setinitializeapplicationdbcontext(null);公共静态ApplicationDbContext Create()=new ApplicationDbContext();}第二步修改注册用户的代码,注册新用户的时候需要选择所属的公司信息

[httpset][AllowAnonymous][validateantforgretoken]public async tasactionresult Register(AccountRegistrationModel viewModel){ var data=this ._companyService .可查询()。选择(x=新列表项(){值=x.Id.ToString(),文本=x . Name });这个ViewBag.companylist=数据;//确保我们有一个有效的视图模型来处理if(!这个模型状态。IsValid){ 0返回这个。视图(视图模型);} //尝试创建具有给定身份的用户尝试{ //使用提供的信息准备身份var user=新应用程序用户{ UserName=viewModel .用户名,全名=视图模型。姓氏"."视图模型.名字,公司代码=视图模型公司代码,公司名称=视图模型.公司名称,TenantId=viewModel .TenantId,Email=viewModel .电子邮件,帐户类型=0 };定义变量结果=等待。创建异步(用户,视图模型。密码);//如果无法创建用户,如果(!结果。成功){ //将所有错误添加到页面,以便可以使用它们来显示这次的错误。添加错误(结果);归还这个。视图(视图模型);} //如果用户能够被创建,我们可以立即登录//注意:考虑使用电子邮件验证过程等待SignInAsync(用户,真);归还这个RedirectToLocal();} catch(DbEntityValidationException ex){//将所有错误添加到页面中,以便可以使用它们来显示这是哪里出错了。添加错误(例如);归还这个。视图(视图模型);} }AccountController.cs第三步读取登录用户的TenantId在用户查询和新增修改时把TenantId插入到表中,这里需要引用

Z.实体框架。另外,这个是免费开源的一个类库,功能强大

公共存储上下文(): base(' Name=DefaultConnection '){//获取登录用户信息,tenantid var claim sidentity=(claim sidentity)HttpContext .当前用户身份;var tenantclaim=claimsidentity?查找第一个(' http://)模式。微软。com/identity/claims/tenantid’;var tenantid=Convert .ToInt32(租赁索赔?价值);//设置当对工作对象进行查询时默认添加过滤条件查询过滤器管理器.FilterWork(q=q。其中(x=x . TenantId==TenantId));//设置当对命令对象进行查询时默认添加过滤条件查询过滤器管理器.FilterOrder(q=q。其中(x=x . TenantId==TenantId));}公共覆盖task int SaveChangeSasync(cancelatoken cancelatoken){ var CurrentDateTime=DateTime .现在;var claim sidentity=(claim sidentity)HttpContext .当前用户身份;var tenantclaim=claimsidentity?查找第一个(' http://)模式。微软。com/identity/claims/tenantid’;var tenantid=Convert .ToInt32(租赁索赔?价值);foreach (var auditableEntity在这种情况下更换跟踪器。EntriesEntity()){ if(auditableEntity).状态==实体状态.添加了|| auditableEntity .状态==实体状态.已修改){ //auditableEntity .实体lastpmodified date=CurrentDateTime;开关(可审计实体.State) { case EntityState .添加了:可审计实体。属性(“最后修改日期”).is modified=false auditableentity .属性(“最后修改者”).is modified=false auditableentity .实体CreatedDate=currentdatetime auditableentity .实体CreatedBy=claimsidentity .名称;可审计实体.实体。TenantId=tenantid打破;案例实体状态。已修改:可审计实体。属性(“创建数据”).is modified=false auditableentity .属性(“CreatedBy”).is modified=false auditableentity .实体lastpmodified date=CurrentDateTime;可审计实体.实体LastModifiedBy=claimsidentity .名称;可审计实体.实体。TenantId=TenantId//if(AuditableEntity).属性(p=p .已创建).IsModified || auditableEntity .属性(p=p.CreatedBy).IsModified) //{ //抛出新的DbEntityValidationException(字符串。格式('尝试在修改后的{0}上更改创建的审核跟踪' ',可审核实体。实体。GetType().全名);//} break;} } }返回基数SaveChangesAsync(cancelatitoken);}公共覆盖int save changes(){ var currentDateTime=DateTime .现在;var claim sidentity=(claim sidentity)HttpContext .当前用户身份;var tenantclaim=claimsidentity?查找第一个(' http://)模式。微软。com/identity/claims/tenantid’;var tenantid=Convert .ToInt32(租赁索赔?价值);foreach (var auditableEntity在这种情况下更换跟踪器。EntriesEntity()){ if(auditableEntity).状态==实体状态.添加了|| auditableEntity .状态==实体状态.已修改){ auditableEntity .实体lastpmodified date=CurrentDateTime;开关(可审计实体.State) { case EntityState .添加了:可审计实体。属性(“最后修改日期”).is modified=false auditableentity .属性(“最后修改者”).is modified=false auditableentity .实体CreatedDate=currentdatetime auditableentity .实体CreatedBy=claimsidentity .名称;可审计实体.实体。TenantId=tenantid打破;案例实体状态。已修改:可审计实体。属性(“创建数据”).is modified=false auditableentity .属性(“CreatedBy”).is modified=false auditableentity .实体lastpmodified date=CurrentDateTime;可审计实体.实体LastModifiedBy=claimsidentity .名称;可审计实体.实体。TenantId=tenantid打破;} } }返回基数saveChanges();}DbContext.cs经过以上3步就实现一个简单的多租户查询数据的功能。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

版权声明:利用EF6简单实现多租户的应用是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

相关文章推荐