Entity Framework不能进行跨数据库查询的原因是什么?

    作者:课课家教育更新于: 2017-05-18 10:44:29

      在EntityFramework中,我们可以通过ToTable("表名")指定表名进行映射,EntityFramework会根据指定的表名构建SQL语句,如果在这里加上数据库名和Schema名(也就是ToTable("数据库.dbo.表名")),是不是可以实现跨数据库查询呢?

      于是,我们根据这个思路进行了试验,结果发现了EntityFramework不能进行跨数据库查询的秘密:EntityFramework会对ToTable()中指定的表名进行处理,加上中括号,如果没有指定Schema名,会在表名前加上[dbo],比如:ToTable("表名"),SQL语句中的表名是[dbo].[表名]。而在加“中括号”时的不正确有处理,成为了罪魁祸首。

      后来仔细想想,从理论来讲,实现跨数据库查询应该不难啊,与非跨数据库查询相比,只是多了个数据库名,比如下面的非跨数据库查询语句:

      SELECT[Text]FROMdbo.blog_PostBodyWHEREID=3560

      跨数据库查询语句:

      SELECT[Text]FROMCNBlogsText.dbo.blog_PostBodyWHEREID=3560

      我们试图组装一些特殊字符串骗过EntityFramework,都没成功。目前我们在用Reflector在EntityFramework的代码中寻找凶手,只有找到了凶手,知道了作案手段,才能知道是否有可能解决这个问题。

      下面用代码爆一下料:

      BlogDbContext的代码:

      我们试图组装一些特殊字符串骗过EntityFramework,都没成功。目前我们在用Reflector在EntityFramework的代码中寻找凶手,只有找到了凶手,知道了作案手段,才能知道是否有可能解决这个问题。    下面用代码爆一下料:    BlogDbContext的代码:

      LINQtoEntities查询代码:

    LINQtoEntities查询代码:

      1.这是非跨数据库查询的情况,生成的SQL语句如下:

      1.这是非跨数据库查询的情况,生成的SQL语句如下:

      指定的表名是blog_PostBody,SQL语句中变成了[dbo].[blog_PostBody]。

      2.跨数据库查询:

      BlogDbContext的代码改为:

      modelBuilder.Entity().ToTable("CNBlogsText.dbo.blog_PostBody");

      生成的SQL语句:

    2.跨数据库查询:    BlogDbContext的代码改为:    modelBuilder.Entity<PostText>().ToTable(

      CNBlogsText.dbo被整个加在了中括号中,正确的应该是[CNBlogsText].[dbo].[blog_PostBody]。

      试图欺骗一下EntityFramework,将表名改为:

      modelBuilder.Entity().ToTable("CNBlogsText].[dbo.blog_PostBody");

      生成的SQL语句:

    试图欺骗一下EntityFramework,将表名改为:    modelBuilder.Entity<PostText>().ToTable(

      多出了半个中括号,欺骗失败...

      这里通过Reflector对EntityFramework的代码进行分析,找出了真相。

      真相如下:

      1.对于“CNBlogsTex.dbo.blog_PostBody"字符串,EntityFramework对其进行了拆分,拆分为:Schema名称(CNBlogsTex.dbo)与数据库表名称(blog_PostBod)。

      这部分是在System.Data.Entity.ModelConfiguration.Utilities.ObjectExtensions的ParseQualifiedTableName()方法中处理的,Reflector出来的代码如下:

     这部分是在System.Data.Entity.ModelConfiguration.Utilities.ObjectExtensions的ParseQualifiedTableName()方法中处理的,Reflector出来的代码如下:

      2.方括号的添加(CNBlogsTex.dbo变为[CNBlogsTex.dbo],blog_PostBod变为[blog_PostBod])是在System.Data.SqlClient.SqlDdlBuilder的AppendIdentifier(stringidentifier)方法中处理的,Reflector出来的代码如下:

     2.方括号的添加(CNBlogsTex.dbo变为[CNBlogsTex.dbo],blog_PostBod变为[blog_PostBod])是在System.Data.SqlClient.SqlDdlBuilder的AppendIdentifier(stringidentifier)方法中处理的,Reflector出来的代码如下:

      所以,当我们当表名改为"CNBlogsText].[dbo.blog_PostBody"时,"CNBlogsText].[dbo"就被转换为"[CNBlogsText]].[dbo]"。

      不仅有代码有真相,而且有图有真相:

    所以,当我们当表名改为

      知道了真相,目前只能望真相心叹,能不能解决这个问题还是未知数...

      更新:

      killkill的一句回复让“心叹”变成了“兴奋”,那种程序员特有的,一般人享受不到的兴奋...

      原来要欺骗的不是EntityFramework,而且是SQLServer,用SQLServer的同义词(SYNONYM)可以轻松搞定这个问题,创建同义词的SQL语句如下:

      CREATESYNONYM[dbo].[CNBlogsText__blog_PostBody]FOR[CNBlogsText].[dbo].[blog_PostBody]

      小编结语:

      更多内容尽在课课家教育!

课课家教育

未登录