经过很长一段时间的守护世界树模式,在6月还是7月的某一天,在下是终于把注册的时候给每一个注册用户创建一个数据库,登陆的时候可以使用这个数据库的技能点上了。
EF这个东西有三种模式,CodeFirst,ModelFirst,DBFirst,这里就不详细说了,反正我也没仔细研究过,就是随意的学了学然后去使用。
在我看来EF这个架构有三部分组成:数据库、代码、实体模型。实际上我觉得只用代码和数据库这两个东西就行了,实体模型翻译到VS中依然是以类的形式存在的,只不过是微软给了我们一个图形化的编辑界面,方便使用罢了。
这三个东西先有的谁,就是什么first。唯一有点去别的是codefirst和modelfirs这两种模式大部分情况是用来创建数据库的,而DBfirst已经存在数据库,是为了方便使用EF。
好了,我对EF理解就这些了,但是这跟多租户有什么关系呢?
并没有。。。。。。凑点字数不容易啊。。。。。。
事实上在我实现的多租户效果中,并没有什么高端的技术,使用codefirst创建数据库,然后把创建的库的这个连接字符串保存到一个后台管理端的数据库中,等到使用的时候在把数据库连接字符串取出来,然后传给EF让他使用DBfirst进入就行了。
说起来原理还是不怎么难的,只要理清楚一整条逻辑,剩下的就是敲代码了。
首先要写好一套codefirst模式下使用的数据库代码,就随便粘两个吧。一个数据库上下文,一个实体。
using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Web; namespace ITOO.Authority.Model { public class ITOO_AuthorityEntities : DbContext { public ITOO_AuthorityEntities(string ConncectionString) : base(ConncectionString) { this.Database.CreateIfNotExists(); } public virtual DbSet<TA_AllUsers> TA_AllUsers { get; set; } public virtual DbSet<TA_Database> TA_Database { get; set; } public virtual DbSet<TA_Dictionary> TA_Dictionary { get; set; } public virtual DbSet<TA_Organization> TA_Organization { get; set; } public virtual DbSet<TA_Resource> TA_Resource { get; set; } public virtual DbSet<TA_Role> TA_Role { get; set; } public virtual DbSet<TA_RoleResource> TA_RoleResource { get; set; } public virtual DbSet<TA_User> TA_User { get; set; } public virtual DbSet<TA_UserResource> TA_UserResource { get; set; } public virtual DbSet<TA_UserRole> TA_UserRole { get; set; } } }在数据库上下文的类中,我们要修改构造函数,DBContext的构造函数有很多种重载,一般我们使用的全都是传给他一个数据库连接字符串,然后DBContext根据这个字符串去链接数据库,但是codefirst模式下,如果你的字符串连接不到这个数据库,那么他就会根据你的数据库连接字符串中的IP,数据库名称,等信息去创建一个库,这个就是我们要的。
在这里,上下文这个类是为了创建数据库用的,你的数据库中有哪些表,就是下面一个一个的DbSet。那么我们的表都有了,表中的列肯定也要写对吧,EF会根据实体的代码去生成列。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ITOO.Authority.Model { using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; public partial class TA_Resource { public TA_Resource() { this.TA_RoleResource = new HashSet<TA_RoleResource>(); this.TA_UserResource = new HashSet<TA_UserResource>(); } [Key] public System.Guid ResourceId { get; set; } public Nullable<System.Guid> PId { get; set; } [StringLength(50)] public string ResourceName { get; set; } [StringLength(100)] public string Url { get; set; } public Nullable<short> POpen { get; set; } [StringLength(100)] public string Icon { get; set; } [StringLength(500)] public string Css { get; set; } [StringLength(500)] public string JavaScript { get; set; } [StringLength(100)] public string Type { get; set; } public Nullable<short> IsUse { get; set; } [StringLength(500)] public string Description { get; set; } public Nullable<short> Checked { get; set; } public Nullable<short> SeqNo { get; set; } public virtual ICollection<TA_RoleResource> TA_RoleResource { get; set; } public virtual ICollection<TA_UserResource> TA_UserResource { get; set; } } }
这个就是上面说的实体,里面有主键,外键,数据类型等等信息,这个大伙上网查,反正挺简单的。然后建库的方法就一句话,是的没看错就一句话。
ITOO_AuthorityEntities newDB = new ITOO_AuthorityEntities(connectionString);因为数据库的字符串是要有专门的系统后台管理端的数据库表来管理的,所以这个connectionString要通过参数的形成传过来,这样我们就能在try-catch没有出错的情况下,这个connectionString就能继续传给保存的数据库的方法中,之后登陆的时候就能查了。
切出去看了一下,够长了,登陆下篇再说
以上