<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      什么是多租戶


      網(wǎng)上有好多解釋,有些上升到了架構(gòu)設(shè)計(jì),讓你覺得似乎非常高深莫測,特別是目前流行的ABP架構(gòu)中就有提到多租戶(IMustHaveTenant),其實(shí)說的簡單一點(diǎn)就是再每一張數(shù)據(jù)庫的表中添加一個(gè)TenantId的字段,用于區(qū)分屬于不同的租戶(或是說不同的用戶組)的數(shù)據(jù)。關(guān)鍵是現(xiàn)實(shí)的方式必須對(duì)開發(fā)人員來說是透明的,不需要關(guān)注這個(gè)字段的信息,由后臺(tái)或是封裝在基類中實(shí)現(xiàn)數(shù)據(jù)的篩選和更新。

      基本原理


      從新用戶注冊時(shí)就必須指定用戶的TenantId,我的例子是用CompanyId,公司信息做為TenantId,哪些用戶屬于不同的公司,每個(gè)用戶將來只能修改和查詢屬于本公司的數(shù)據(jù)。

      接下來就是用戶登錄的時(shí)候獲取用戶信息的時(shí)候把TenantId保存起來,asp.net mvc(不是 core) 是通過 Identity
      2.0實(shí)現(xiàn)的認(rèn)證和授權(quán),這里需要重寫部分代碼來實(shí)現(xiàn)。

      最后用戶對(duì)數(shù)據(jù)查詢/修改/新增時(shí)把用戶信息中TenantId,這里就需要設(shè)定一個(gè)Filter(過濾器)和每次SaveChange的插入TenantId

      如何實(shí)現(xiàn)

      第一步,擴(kuò)展?Asp.net Identity user 屬性,必須新增一個(gè)TenantId字段,根據(jù)Asp.net Mvc
      自帶的項(xiàng)目模板修改IdentityModels.cs 這個(gè)文件
      1 // You can add profile data for the user by adding more properties to your
      ApplicationUser class, please visithttp://go.microsoft.com/fwlink/?LinkID=317594
      to learn more. 2 public class ApplicationUser : IdentityUser 3 { 4 public
      async Task<ClaimsIdentity>
      GenerateUserIdentityAsync(UserManager<ApplicationUser> manager,string
      authenticationType) 5 { 6 // Note the authenticationType must match the one
      defined in CookieAuthenticationOptions.AuthenticationType 7 var userIdentity =
      await manager.CreateIdentityAsync(this, authenticationType); 8 // Add custom
      user claims here 9 userIdentity.AddClaim(new Claim("
      http://schemas.microsoft.com/identity/claims/tenantid", this
      .TenantId.ToString()));10 userIdentity.AddClaim(new Claim("CompanyName", this
      .CompanyName));11 userIdentity.AddClaim(new Claim("EnabledChat", this
      .EnabledChat.ToString()));12 userIdentity.AddClaim(new Claim("FullName", this
      .FullName));13 userIdentity.AddClaim(new Claim("AvatarsX50", this.AvatarsX50));
      14 userIdentity.AddClaim(new Claim("AvatarsX120", this.AvatarsX120)); 15 return
      userIdentity;16 } 17 public async Task<ClaimsIdentity>
      GenerateUserIdentityAsync(UserManager<ApplicationUser> manager) 18 { 19 //
      Note the authenticationType must match the one defined in
      CookieAuthenticationOptions.AuthenticationType 20 var userIdentity = await
      manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
      21 // Add custom user claims here 22 return userIdentity; 23 } 24 25
      [Display(Name ="全名")] 26 public string FullName { get; set; } 27 [Display(Name =
      "性別")] 28 public int Gender { get; set; } 29 public int AccountType { get; set;
      }30 [Display(Name = "所屬公司")] 31 public string CompanyCode { get; set; } 32
      [Display(Name ="公司名稱")] 33 public string CompanyName { get; set; } 34
      [Display(Name ="是否在線")] 35 public bool IsOnline { get; set; } 36 [Display(Name =
      "是否開啟聊天功能")] 37 public bool EnabledChat { get; set; } 38 [Display(Name = "小頭像")]
      39 public string AvatarsX50 { get; set; } 40 [Display(Name = "大頭像")] 41 public
      string AvatarsX120 { get; set; } 42 [Display(Name = "租戶ID")] 43 public int
      TenantId {get; set; } 44 } 45 46 47 48 public class ApplicationDbContext :
      IdentityDbContext<ApplicationUser>49 { 50 public ApplicationDbContext() 51 :
      base("DefaultConnection", throwIfV1Schema: false) =>
      Database.SetInitializer<ApplicationDbContext>(null); 52 53 public static
      ApplicationDbContext Create() =>new ApplicationDbContext(); 54 55 56 } View Code
      ?

        第二步 修改注冊用戶的代碼,注冊新用戶的時(shí)候需要選擇所屬的公司信息



      ?

      ?
      1 [HttpPost] 2 [AllowAnonymous] 3 [ValidateAntiForgeryToken] 4 public
      async Task<ActionResult> Register(AccountRegistrationModel viewModel) 5 { 6
      var data = this._companyService.Queryable().Select(x => new ListItem() { Value
      = x.Id.ToString(), Text = x.Name }); 7 this.ViewBag.companylist = data; 8 9
      // Ensure we have a valid viewModel to work with 10 if (!this
      .ModelState.IsValid)11 { 12 return this.View(viewModel); 13 } 14 15 // Try to
      create a user with the given identity 16 try 17 { 18 // Prepare the identity
      with the provided information 19 var user = new ApplicationUser 20 { 21
      UserName = viewModel.Username, 22 FullName = viewModel.Lastname + "." +
      viewModel.Firstname,23 CompanyCode = viewModel.CompanyCode, 24 CompanyName =
      viewModel.CompanyName,25 TenantId=viewModel.TenantId, 26 Email =
      viewModel.Email,27 AccountType = 0 28 29 }; 30 var result = await this
      .UserManager.CreateAsync(user, viewModel.Password);31 32 // If the user could
      not be created 33 if (!result.Succeeded) 34 { 35 // Add all errors to the page
      so they can be used to display what went wrong 36 this.AddErrors(result); 37 38
      return this.View(viewModel); 39 } 40 41 // If the user was able to be created
      we can sign it in immediately42 // Note: Consider using the email verification
      proces 43 await this.SignInAsync(user, true); 44 45 return this
      .RedirectToLocal();46 } 47 catch (DbEntityValidationException ex) 48 { 49 //
      Add all errors to the page so they can be used to display what went wrong 50
      this.AddErrors(ex); 51 52 return this.View(viewModel); 53 } 54 }
      AccountController.cs
      第三步 讀取登錄用戶的TenantId 在用戶查詢和新增修改時(shí)把TenantId插入到表中,這里需要引用
      Z.EntityFramework.Plus,這個(gè)是免費(fèi)開源的一個(gè)類庫,功能強(qiáng)大 1 public StoreContext() 2 : base("
      Name=DefaultConnection") { 3 //獲取登錄用戶信息,tenantid 4 var claimsidentity =
      (ClaimsIdentity)HttpContext.Current.User.Identity; 5 var tenantclaim =
      claimsidentity?.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid
      "); 6 var tenantid = Convert.ToInt32(tenantclaim?.Value); 7 //
      設(shè)置當(dāng)對(duì)Work對(duì)象進(jìn)行查詢時(shí)默認(rèn)添加過濾條件 8 QueryFilterManager.Filter<Work>(q => q.Where(x =>
      x.TenantId == tenantid)); 9 //設(shè)置當(dāng)對(duì)Order對(duì)象進(jìn)行查詢時(shí)默認(rèn)添加過濾條件 10
      QueryFilterManager.Filter<Order>(q => q.Where(x => x.TenantId == tenantid)); 11
      }12 13 public override Task<int> SaveChangesAsync(CancellationToken
      cancellationToken)14 { 15 var currentDateTime = DateTime.Now; 16 var
      claimsidentity = (ClaimsIdentity)HttpContext.Current.User.Identity; 17 var
      tenantclaim = claimsidentity?.FindFirst("
      http://schemas.microsoft.com/identity/claims/tenantid"); 18 var tenantid =
      Convert.ToInt32(tenantclaim?.Value); 19 foreach (var auditableEntity in this
      .ChangeTracker.Entries<Entity>()) 20 { 21 if (auditableEntity.State ==
      EntityState.Added || auditableEntity.State == EntityState.Modified) 22 { 23 //
      auditableEntity.Entity.LastModifiedDate = currentDateTime; 24 switch
      (auditableEntity.State)25 { 26 case EntityState.Added: 27
      auditableEntity.Property("LastModifiedDate").IsModified = false; 28
      auditableEntity.Property("LastModifiedBy").IsModified = false; 29
      auditableEntity.Entity.CreatedDate = currentDateTime; 30
      auditableEntity.Entity.CreatedBy = claimsidentity.Name; 31
      auditableEntity.Entity.TenantId = tenantid; 32 break; 33 case
      EntityState.Modified:34 auditableEntity.Property("CreatedDate").IsModified =
      false; 35 auditableEntity.Property("CreatedBy").IsModified = false; 36
      auditableEntity.Entity.LastModifiedDate = currentDateTime; 37
      auditableEntity.Entity.LastModifiedBy = claimsidentity.Name; 38
      auditableEntity.Entity.TenantId = tenantid; 39 //if (auditableEntity.Property(p
      => p.Created).IsModified || auditableEntity.Property(p =>
      p.CreatedBy).IsModified)40 //{ 41 // throw new
      DbEntityValidationException(string.Format("Attempt to change created audit
      trails on a modified {0}", auditableEntity.Entity.GetType().FullName));42 //} 43
      break; 44 } 45 } 46 } 47 return base.SaveChangesAsync(cancellationToken); 48
      }49 50 public override int SaveChanges() 51 { 52 var currentDateTime =
      DateTime.Now;53 var claimsidentity =
      (ClaimsIdentity)HttpContext.Current.User.Identity;54 var tenantclaim =
      claimsidentity?.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid
      "); 55 var tenantid = Convert.ToInt32(tenantclaim?.Value); 56 foreach (var
      auditableEntityin this.ChangeTracker.Entries<Entity>()) 57 { 58 if
      (auditableEntity.State == EntityState.Added || auditableEntity.State ==
      EntityState.Modified)59 { 60 auditableEntity.Entity.LastModifiedDate =
      currentDateTime;61 switch (auditableEntity.State) 62 { 63 case
      EntityState.Added:64 auditableEntity.Property("LastModifiedDate").IsModified =
      false; 65 auditableEntity.Property("LastModifiedBy").IsModified = false; 66
      auditableEntity.Entity.CreatedDate = currentDateTime; 67
      auditableEntity.Entity.CreatedBy = claimsidentity.Name; 68
      auditableEntity.Entity.TenantId = tenantid; 69 break; 70 case
      EntityState.Modified:71 auditableEntity.Property("CreatedDate").IsModified =
      false; 72 auditableEntity.Property("CreatedBy").IsModified = false; 73
      auditableEntity.Entity.LastModifiedDate = currentDateTime; 74
      auditableEntity.Entity.LastModifiedBy = claimsidentity.Name; 75
      auditableEntity.Entity.TenantId = tenantid; 76 break; 77 } 78 } 79 } 80
      return base.SaveChanges(); 81 } DbContext.cs
      ?

      經(jīng)過以上3步就實(shí)現(xiàn)一個(gè)簡單的多租戶查詢數(shù)據(jù)的功能。

      希望對(duì)大家有用。

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          小情侣第一次啪啪全程偷拍 | 色淫视频 | 露娜用孙悟空的金箍棒戳哪 | 精品无码人妻 | 亚洲欧美第一在线 | 丰满女老板大胸老板bd高清 | 韩国一区二区在线黄 | 日本妞干网| 一起草在线视频 | 中文字幕在线好乱1234 |