天天看點

SaaS系統 .netcore webapi

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
           

繼續閱讀