B\S备忘录28——EF强行多租户效果?谁来进谁的库

  上一次是解决了谁来建谁的库的问题,也就是注册,那么注册的人是要登陆我们的系统的,如何让用户进来就看到属于他的东西呢?

  这个就算属于登陆的问题了。

  我们在上一篇博客中说过,建库的数据库连接字符串我们可以存到系统后台管理端,那么我们可以建立一套关系,比如一个用户属于一个企业,而这个企业,有一套我们给分配的数据库。这种关系可以被我们用外键的形式记录在数据库中。

  这样我们在登陆的时候就可以仅仅根据用户名就能查出用户属于的数据库,然后再拿出属于用户的链接字符串,并且使用它。

  那么问题就简单了,怎么使用这个字符串呢?

  EF的CodeFirst模式有一个机制,如果给他的链接字符串可以链接到数据库,那么他就能连上数据库并且可以做操作,如果没有就会像上一篇博客一样建一套新的数据库。但是这里我没有使用CodeFirst模式来实现,主要的问题是我要解决的问题有些特殊。

  一个系统使用同一个库,但是每开发者的数据库操作权限是不一样的,他们已经使用了DBfirst建立了数据库映射,并且只映射了自己要操作的表。如果这个时候要改为CodeFirst模式的话,会进行大量的改动,并且让每个开发者都有了对整套数据库的操作权限。

  好吧,反正也没什么别的好用的,就DBFirst吧- -。

  接下来的问题是如何改造DBFirst,让它接受我们的传参。

  首先上来肯定是想到CodeFirst那种形式,对DBContext的构造函数进行重写。

public ITOO_AuthorityEntities(string conn)
            : base(conn)
        {
        }
  但是在这么执行之后呢,当我们传入数据库参数的时候,会报错,大概的意思就是EF的验证过不去,现在的你要链接的数据库进行了改动之类的话。

B\S备忘录28——EF强行多租户效果?谁来进谁的库_第1张图片
  这个问题我也是查了好久终于是发现了一些算是解决方法的方法。。。

  再来说一个EF的机制,如果你的链接字符串是普通的字符串的话,也就是我们平时写的那种IP啊,数据库名啊,什么的。那么EF会使用CodeFirst进行处理,这个时候,再看一下我们的实体的代码。

public partial class TA_AllUsers
    {
        public System.Guid AllUsersid { get; set; }
        public string UserCode { get; set; }
        public string Password { get; set; }
        public string Tel { get; set; }
        public string Email { get; set; }
        public string UserType { get; set; }
    
        public virtual TA_Database TA_Database { get; set; }
    }
  是这个样子的,我们可以看见,现在的实体与上一篇的实体,标签不见了,那么再使用CodeFirst进行连接的话,会默认对数据库进行验证,因为没有了标签所以会验证失败。

  好了,怎么解决这个问题呢?

  机制的我把目光瞄向了一开始生成DBFirst映射时自动生成的字符串,既然他自动读取这个字符串,我直接把它给传过去不就行了吗?

  然后我的代码就成了这个样子- -

public ITOO_AuthorityEntities(string conn)
            : base("metadata=res://*/ITOOModel.csdl|res://*/ITOOModel.ssdl|res://*/ITOOModel.msl;provider=System.Data.SqlClient;provider connection string='" + conn + "MultipleActiveResultSets=True;App=EntityFramework'")
        {
        }
  居然成功了。。。所以我就说是强行多租户吧。。。

  然而还有一点点瑕疵,就是每次我刷新数据库映射的时候,都要重新写一遍这里的构造函数,查了一下t4模板这个东西发现改另外一个地方就行了:****.Context.tt

  将里面的构造函数模板改成上面写的样子,比如

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
    public <#=code.Escape(container)#>(string conn)
        : base("metadata=res://*/ITOOModel.csdl|res://*/ITOOModel.ssdl|res://*/ITOOModel.msl;provider=System.Data.SqlClient;provider connection string='" + conn + "MultipleActiveResultSets=True;App=EntityFramework'")
    {
<#
  这样就不用每次都改了~

以上


你可能感兴趣的:(BS)