导读:所谓的EF的Databasefirst工作模式,是目前我们(不涉及社会领域)用的最广的一种模式,也是本次ITOO开发所采用的工作模式。本篇博客,就分析在项目中通过Database First模式去实现多租户的一个过程。

 

一、DBFirst模式下的研究分析

先看这种模式下生成的各个文件:

   

说明:之所以通过EF可以实现对于数据库的操作,主要依靠两个文件:edmx(概念模型描述、存储模型描述、映射关系描述),实体对象类(DBFirst下的表一和表二类)

 

误区:改掉数据库连接串,则实现对连接数据库的操作。

 

说明:这种方法再DB模式下是完全失效的。它失效的原因,需要回归到ORM框架的工作原理去解释。我们有一个很重要的映射文件存在于edmx文件中,当我们更改数据库连接串时,通过配置文件读取到的映射文件,并不是连接串中的数据库。先看下面 例子:

 

上面的图片,是我在研究为什么改掉了数据库连接串还是无法实现对库读写操作的时候做的demon。OldModel,是我用最开始提供建库代码的模板数据库运用DBFrist模式创建的,NewModel,则是我使用通过代码生成的数据库创建的DBFrist模型。

 

有意思的是:打开这两个文件下的每一个文件,几乎全都是一样的,除了App.config里面的连接串不一样和应用程序中的web.config里面的连接串不一样。

 

所以,我们最初的解决方案是,直接在上下文中,即熟知的public partialclass TestCrateDatabaseEntities : DbContext 类,更改构造函数去实现App.config里面的连接,即:

 

我们试图通过这样的方式,去回避构造函数对于配置文件的读取,即:

<span style="font-family:KaiTi_GB2312;font-size:18px;"><connectionStrings>
<add name="TestCrateDatabaseEntities"connectionString="metadata=res://*/DBFrist.csdl|res://*/DBFrist.ssdl|res://*/DBFrist.msl;provider=System.Data.SqlClient;providerconnection string="data source=ANGEL\ANGELSQLSERVER;initialcatalog=TestCrateDatabase;persist security info=True;userid=sa;password=xia0626;MultipleActiveResultSets=True;App=EntityFramework""providerName="System.Data.EntityClient" />
</connectionStrings></span>

 

但结果是:失败了

 

二、原因思考

1, ORM框架中的映射文件,在Code Firtst模式中,通过mapping类的形式出现,在DBFirst模式中,这个映射文件,去哪儿了?

2, 如果,我们的实体对象类完全一致,各个数据库,除了数据库名称不一样,表结构、字段等完全一致,为什么我们明明更改了数据库连接地址,依然失败了?

3, 除了数据库的连接地址,相同的数据库生成的DBFirst下的ADO数据模型,真的完全一致吗?

4,在web.config里面配置的连接,不更改可不可以?没有这个配置,又可不可以?

 

看上面例子中的区别(将edmx文件作为XML格式打开):

 

OldModel:

 

 

NewModel:

 

可以看出,这一关键的文件,表面上一致,事实上很多地方都不一样。我们虽然更改了数据库连接串,但对于edmx文件中的命名空间等对应关系,并没有更改。我们拿着新数据库的连接串 读取的却是最初生成代码的数据库的映射关系。所以,我们失败了!备注:在这个文件中有很多地方都存在命名空间,并不是圈出来的才是。另外在设计器中也有,但那个文件并不影响操作,具体原因请思考设计器的作用,和EF操作数据库的流程。

三、解决方案

第一个思路:

既然原因是由于edmx 的描述文件不一样,那就改成一样的:

方案一:

引入IO流,将edmx文件作为XML文件进行操作,先获取到已经存在于此文件的数据库命名,然后用新数据库名称去替换,然后重新写回edmx文件。(实现了对于新库的操作)

问题一:已存在数据库名称的获取(每次连接数据库时都将名称存入线程缓存里面),但是很多很多个用户操作系统,怎么办,怎么区分?             ——废弃

解决方案:使用正则表达式,匹配指定字符串。原因:每个数据库的名称前半截的字符串都是一样的,只是后面6位企业号不一样。使用正则表达式完全可以匹配替换。(可以实现)

 

问题二:在DBFirst模式下,EF必须读取edmx文件,而edmx文件只有一个(可以由多个edmx文件共同描述一个对象,这里是针对多用户操作,而不是多表操作),那么当用户A在改这个文件的时候,用户B、C………同时操作数据库,怎么办?(以下解决方案,都未能最终证实,仅是理论上的想法和尝试)

解决方案一:程序在硬盘的级别是无法执行的,每个用户更改后的edmx文件,都存起来,在需要的时候,从内存读取。可是,这个读取的入口在哪里?在未被修改的上下文类中,通过构造函数,继承基类,再通过基类的构造函数去读取,那么,1,更改基类的构造函数(基类源码在分享资料中);2,不继承基类,直接在上下文类的构造函数中写。(还未进行测试)

 

第二个思路:

在java中,ORM框架的实现之一是Hibernate,在使用hibernate的时候,是通过一个XML文件手写映射关系,在.NET中,可不可以在edmx中,手写映射关系,去除掉具体的命名空间?????(未深入尝试,hibernate引入的dtd和edmx引入的schema有冲突,具体的协调方案还未研究出来)

 

第三个思路:

在edmx文件中,将所有涉及到具体数据库指向的值,都设置为变量(edmx文件的实质就是一个XML文件,可以用到XML文件的操作方式,基本上都可以用)。在读取映射文件之前,通过给变量赋值的方式,确定具体的数据库映射。

 

……

 四、总结

思考:是否可以通过负载均衡去解决当前的高并发问题?????我认为是不能的。所以DBFirst留下的问题,都得继续研究测试。。。。。

posted on 2016-02-15 20:58  何红霞  阅读(346)  评论(0编辑  收藏  举报