下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

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

作者:课课家教育     来源: http://www.kokojia.com点击数:1200发布时间: 2017-08-30 08:30:20

标签: 数据库Entity Framework数据库查询

  在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<PostText>().ToTable("CNBlogsText.dbo.blog_PostBody");

  生成的SQL语句:

2.跨数据库查询:    BlogDbContext的代码改为:    modelBuilder.Entity<PostText>().ToTable("CNBlogsText.dbo.blog_PostBody");    生成的SQL语句:

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

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

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

  生成的SQL语句:

试图欺骗一下EntityFramework,将表名改为:    modelBuilder.Entity<PostText>().ToTable("CNBlogsText].[dbo.blog_PostBody");    生成的SQL语句:

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

  这里通过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]"。

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

所以,当我们当表名改为"CNBlogsText].[dbo.blog_PostBody"时,"CNBlogsText].[dbo"就被转换为"[CNBlogsText]].[dbo]"。    不仅有代码有真相,而且有图有真相:

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

  更新:

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

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

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

  小编结语:

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

赞(20)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程