【问题标题】:Joining tables from two databases using entity framework使用实体框架连接来自两个数据库的表
【发布时间】:2014-10-19 00:53:55
【问题描述】:

我正在开发一个 ASP.NET MVC 4 Web 应用程序。我使用Entity Framework 作为数据访问层,使用数据库优先方法(.edmx 文件)。

目前我在两个不同数据库中定义的连接表中遇到问题(即我有两个 .edmx 文件)。

例如,如果我想加入表,我正在执行以下查询:-

public ActionResult AutoComplete(string term)
{
   var tech = repository.AllFindTechnolog(term).Take(100);//Call to the first database
   var resources = repository.GetResources(tech.Select(a => a.IT360ID.Value).ToArray(), false);//call to the second database

   var query = from techItems in tech
         join resourcesItems in resources
         on techItems.IT360ID.Value equals resourcesItems.RESOURCEID // join based on db2ID
         orderby techItems.PartialTag
         select new //code goes here

   return Json(query, JsonRequestBehavior.AllowGet);
}

我将对数据库进行两次单独的调用,并在应用程序服务器内部进行一次连接,这不是面向性能的最佳解决方案。理想情况下,连接将完全发生在数据库引擎内部。

我知道存储过程将允许我纯粹在服务器上连接来自不同数据库的表,但我不想使用 SP,因为它会降低我的代码的可维护性和可测试性。

所以我正在寻找一种解决方案,我可以使用实体框架进行连接并产生单个数据库连接?

【问题讨论】:

  • 主要思想是,我们选择使用 Entity Framework 作为我们的数据访问层是因为它提供了以下主要功能:- 1. 数据访问代码作为整个应用程序。与存储过程相比,可测试性更强,开发时间更快。2、EF在数据库之上提供了一层,我们的产品可以在不同的数据库供应商上工作。正如我提到的,我们目前唯一直接依赖于数据库的功能是用于执行高级搜索的存储过程
  • 但是如果我想开始为不同的功能创建视图,那么我将失去 EF 提供的优势。所以让我重新构建我原来的问题是我目前使用两个单独的 sql 语句从两个数据库中检索相关数据的方法,然后在应用程序服务器上加入数据,这被认为是一个非常糟糕的设计?虽然我将有两个单独的查询,但与单个连接 sql 语句相比,它们的成本更低......
  • 我可能会为您提供解决方案,但我有一个问题:您在query 变量中选择了什么?您是从两种上下文中获取数据,还是仅从其中一种中获取数据(即仅获取tech 中存在于resources 中的项目)?
  • 另外,AllFindTechnologGetResources 的返回类型是什么?
  • @IronMan84 我将我的上下文命名为 context1 和 context2。在 context1 中我将返回 Technology 对象,而在 context2 中我将返回 Resource 对象。我正在做的是我将从 context1 返回第一个 context1.Technology 100 记录,这些记录以传递的术语开头。然后在每个 Technology 对象中都有一个名为 IT360 的字段,其中包含 context2 中记录的 ID。所以基本上我会在第一个存储库调用中选择 100 个 context1.Technology 对象,选择它们的 IT360 id,然后我将根据选择的 100 个 IT360 id 查询 context2.Resoure。然后加入他们

标签: asp.net-mvc entity-framework linq join entity-framework-5


【解决方案1】:

如果您想通过单个数据库调用来执行此操作,则必须在数据库中创建一个视图,该视图将来自不同数据库的 2 个表连接起来。创建视图后,您可以将其作为单个对象添加到 EF,您可以对其进行进一步操作和查询。视图基本上是一个表,它很容易维护并且很容易绑定到强类型模型

另一种方式,与您发布的类似,您可以查询单独的.edmx 文件,然后加入它们。 是的,对数据库有 2 次调用,但它不应该那么昂贵,并且可能不会注意到差异。

using(var db = new MyEntities())
using (var db2 = new MyEntities2())
{
   var one = db.Table1.AsEnumerable();
   var two = db2.Table2.AsEnumerable(); 

   var result = from o in one
                join t in two on o.Id equals t.Id
                // blah blah

}

【讨论】:

  • 但是为了防止 EF 异常告诉您不能在一个查询中使用两个上下文,您应该执行 db.Table1.AsEnumerable()db2.Table2.AsEnumerable()
  • 在我看来这是一个非常糟糕的主意:每次在一张表上调用 'AsEnumerable()' 时,EF 都会检索表的全部内容并将其加载到 RAM 中。
【解决方案2】:

@CSharper 的回答很接近。正如@Oliver 在 cmets 中提到的,IEnumerable 将表加载到应用程序内存中,如果您有一个大型数据库,则会导致崩溃。

解决方案是使用IQueryable,可以使用 LINQ 调用 - 这会生成更快的 SQL。

// This is a generic method, modify to your needs
public ActionResult Details(int? id)
   var one = db.Table1.AsQueryable();
   var two = db2.Table2.AsQueryable(); 

   // since you're using MVC EF, I assume you want to put this in a viewmodel 
   // (in this case ObjectCombined)
   // assume "id" is passed as parameter 
   Object1 result1 = (from o in one where one.id == id select o).Single();
   Object2 result2 = (from t in two where t.id == o.id select t).Single();
   ObjectCombined result = new ObjectCombined(result1, result2);
   return View(result);
}

【讨论】:

    【解决方案3】:

    我是否建议您考虑在数据库中使用synonym。例如,您可以在您的技术表所在的数据库中创建资源表的同义词。这将确保您不需要维护 2 个 EDMX 文件。相反,您可以拥有一个 EDMX 文件,您可以简单地将您的技术表连接到资源表的同义词,瞧——您正在路上。

    更新:请注意,如果您使用同义词,则需要对 EDMX 文件进行一些额外的工作,以使其在实体框架中工作。这是一个blog post,它是由一个让它工作的程序员发布的。这是她最初提出的stackoverflow 问题。

    编码愉快!!! :)

    【讨论】:

    • 我正在寻找的是一种更开箱即用的方法来支持从两个不同的数据库中使用实体框架连接数据库内的表..
    • @johnG - 如果不执行当前正在执行的操作,即选择每个表并连接结果集,则无法跨两个不同的上下文连接两个数据库表。唯一可以做到这一点的方法是,以某种方式在相同的上下文中选择两个表 - 这就是使用同义词的地方。
    • 那么在我的应用程序服务器内部进行连接并将两个数据库查询传递给每个数据库是否会被认为是一个非常糟糕的设计?我的意思是在实际情况下,通过采取类似的变通办法可以解决这些限制吗?
    • @johnG 我认为最终它将取决于应用程序本身,您是否愿意忍受必须执行两个需要执行的上下文的限制,这会对性能产生什么影响你的系统。我已经看到它是双向的,它只是在挑选你的毒药。我对同义词的一个论点是,如果您要从中选择的第二个数据库被移动到您需要编译和发布您的应用程序的一个实例中,您只需更改同义词即可。
    【解决方案4】:

    您可以创建视图或存储过程,然后您的 sql 语句可以进行跨数据库查询,只需确保您的凭据可以在两个数据库上进行 DML 或 DDL。否则尝试嵌套 using 实体,这将确保当您不在 using 语句中声明 db 实体时不会出现 linq 错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      相关资源
      最近更新 更多