1.什麼是SaaS
SaaS系統,軟體即服務,租戶系統,相對于傳統軟體,SaaS不需要租戶購買伺服器,不需要安裝,也不需要花費大量的時間和成本去維護,隻需要購買使用權,租用即可
2.首先要有租戶表
/// <summary>
/// 租戶
/// </summary>
public class SysTenant
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
/// <summary>
/// 名字
/// </summary>
[MaxLength(50)]
public string Name { get; set; }
/// <summary>
/// 是否删除
/// </summary>
[DefaultValue(false)]
public bool IsDeleted { get; set; }
/// <summary>
/// 添加時間
/// </summary>
public DateTime CreateDate { get; set; } = DateTime.Now;
/// <summary>
/// 編碼
/// </summary>
[Required]
[MaxLength(20)]
public string Code { get; set; }
/// <summary>
/// 電話
/// </summary>
[Required]
[MaxLength(20)]
public string Phone { get; set; }
/// <summary>
/// 租戶類型(共享租戶、獨立租戶)
/// </summary>
[Required]
public ETenantType TenantType { get; set; }
/// <summary>
/// 所屬區域
/// </summary>
[MaxLength(20)]
public string Area { get; set; }
/// <summary>
/// 租戶狀态(待稽核、已稽核、啟用、禁用、取消)
/// </summary>
[Required]
public ETenantState TenantState { get; set; }
/// <summary>
/// Host
/// </summary>
[MaxLength(200)]
public string Host { get; set; }
/// <summary>
/// 備注
/// </summary>
[MaxLength(200)]
public string Remark { get; set; }
}
租戶類型(共享租戶、獨立租戶)
/// <summary>
/// 租戶類型(共享租戶、獨立租戶)
/// </summary>
public enum ETenantType
{
/// <summary>
/// 共享租戶
/// </summary>
[Description("共享租戶")]
Share =1,
/// <summary>
/// 獨立租戶
/// </summary>
[Description("獨立租戶")]
Independent =2
}
租戶狀态(待稽核、已稽核、啟用、禁用、取消)
/// <summary>
/// 租戶狀态(待稽核、已稽核、啟用、禁用、取消)
/// </summary>
public enum ETenantState
{
/// <summary>
/// 待稽核
/// </summary>
[Description("待稽核")]
WaitExamine = 1,
/// <summary>
/// 已稽核
/// </summary>
[Description("已稽核")]
ExamineFinish = 2,
/// <summary>
/// 啟用
/// </summary>
[Description("啟用")]
Enable = 3,
/// <summary>
/// 禁用
/// </summary>
[Description("禁用")]
Disable = 4,
/// <summary>
/// 取消
/// </summary>
[Description("取消")]
Cancel = 5
}
3.擷取請求的租戶Id,Host
public class TenantProvider : ITenantProvider
{
private readonly IHttpContextAccessor _accessor;
public TenantProvider(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
public string GetTenantId()
{
if (_accessor.HttpContext.User.FindFirst("TenantId") != null)
{
return _accessor.HttpContext.User.FindFirst("TenantId").Value;
}
else
{
return "";
}
//return "localhost:5001";
}
public string GetHost()
{
return _accessor.HttpContext.Request.Host.ToString();
//return "localhost:5001";
}
}
4.DBContext調用,并進行租戶過濾
public class JKCRMDBContext : IdentityDbContext<Admins>
{
private readonly ITenantProvider TenantProvider;
internal string TenantId => TenantProvider.GetTenantId();
public JKCRMDBContext(DbContextOptions<JKCRMDBContext> options, ITenantProvider tenantProvider) : base(options)
{
TenantProvider = tenantProvider;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
#region 租戶過濾器
string tenantId = "******";
//根據登入Token查詢租戶Id
if (!string.IsNullOrEmpty(TenantProvider.GetTenantId()))
{
tenantId = TenantProvider.GetTenantId();
}
else
{
#region 查詢租戶資訊
//根據Host查詢租戶Id
MySqlParameter parameter = new MySqlParameter("@Host", MySqlDbType.String);
var originalhost = TenantProvider.GetHost();//localhost:5001
var host = originalhost;
if (originalhost == "localhost:8080")
{
host = "localhost:5001";
}
parameter.Value = host;
var MySqlDataReader = DbHelperMySQL.ExecuteReader("select * from SysTenant where [email protected]", parameter);
while (MySqlDataReader.Read()) //開始讀資料
{
//對資料進行處理
tenantId = MySqlDataReader["Id"].ToString();
}
MySqlDataReader.Close();
#region 寫入一條記錄
//根據Host查詢租戶Id
MySqlParameter[] mySqlParameters = new MySqlParameter[]
{
new MySqlParameter("@Name", "使用者登入記錄Host"),
new MySqlParameter("@CreateDate", DateTime.Now),
new MySqlParameter("@OperationType", 1007),
new MySqlParameter("@OperationParameters", "OriginalHost:"+originalhost+",Host:"+host),
new MySqlParameter("@OperationInfo", "TenantId:"+tenantId)
};
var MySqlInsert = DbHelperMySQL.ExecuteSql("insert into OperationRecords (Name,CreateDate,OperationType,OperationParameters,OperationInfo) values (@Name,@CreateDate,@OperationType,@OperationParameters,@OperationInfo)", mySqlParameters);
#endregion
if (string.IsNullOrEmpty(tenantId) || tenantId == "******")
{
throw new Exception("所屬機構不存在,Host:"+ host);
}
#endregion
}
//開始過濾
modelBuilder.Entity<Customers>().HasQueryFilter(x => x.SysTenantId == Convert.ToInt32(tenantId));
modelBuilder.Entity<ManageMenu>().HasQueryFilter(x => x.SysTenantId == Convert.ToInt32(tenantId));
modelBuilder.Entity<ManageMenuButton>().HasQueryFilter(x => x.SysTenantId == Convert.ToInt32(tenantId));
#endregion
}
}
5.Startup的ConfigureServices
services.AddScoped<ITenantProvider, TenantProvider>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
6.每個涉及到業務的表都需要跟租戶表加主外鍵關系
#region 關系
/// <summary>
/// 租戶Id
/// </summary>
[Description(@"租戶Id")]
public int? SysTenantId { get; set; }
[ForeignKey("SysTenantId")]
public virtual SysTenant SysTenant { get; set; }
#endregion