【问题标题】:Entity Framework: Doing JOINs without having to creating Entities实体框架:无需创建实体即可进行 JOIN
【发布时间】:2015-03-16 15:40:34
【问题描述】:

刚开始使用实体框架(代码优先),我不得不说我在加载相当复杂的 SQL 数据时遇到了很多问题。例如,假设我有以下表格,其中存储了哪些动物属于世界上的哪些地区,并且动物也被分类。

Table: Region
Id: integer
Name string

Table AnimalCategory
Id integer
Name: string
RegionId: integer  -- Refers back Region

Table Animal
Id integer
AnimalCategoryId integer -- Refers back AnimalCategory

假设我想使用实体框架创建一个查询,该查询将加载特定区域的所有动物。最简单的做法是创建 3 个实体 Region、AnimalCategory 和 Animal 并使用 LINQ 加载数据。

但是假设我对加载任何 AnimalCategory 信息不感兴趣并定义一个 Entity 类来表示 AnimalCategory 以便我可以执行 JOIN。如何使用实体框架做到这一点?即使有许多映射功能,我仍然认为这是不可能的。

在非实体框架解决方案中,这很容易通过在 SP 中使用 INNER JOIN 或内联 SQL 来实现。那么我在实体框架中有哪些选择?我是否应该用这些无用的表污染我的数据模型,以便我可以进行 JOIN?

【问题讨论】:

  • 污染在哪里?您要么将动物直接与区域相关联(具有多对多关系,可能 => 您不需要中间实体,即使您的数据库中存在中间表),或者您想要一个中间 AnimalCategory。在 Sql 中,对于这种情况,您需要 AnimalCategory 表。这是污染吗?
  • 如果你必须定义一个实体只是为了做一个JOIN,那就是污染。想象一下,您无法控制它在数据库中的存储方式。您只是数据的消费者,您感兴趣的只是区域和与该区域关联的动物列表。你不关心中间的任何事情。那么为什么要定义实体类并使它们对您的应用程序层可见呢?现在您可以说您的数据库实体/模型与您的应用程序域模型不同,并且它们之间发生了另一种转换。这一切都很好,但有潜在的重复。
  • 如果这些表没用,那么我不知道为什么它们会放在首位!如果您无论如何都打算将这些表用于内联 SQL 或 SP 中的内部联接,那么为什么不通过 EntityFramework 使用它们呢?目前还不清楚您对 EF 的期望。如果没有这些实体,您将无法确定哪种动物属于哪个地区。你能解释一下如何在没有这些表的情况下使用内联 SQL 来完成吗?
  • Nilesh,这很简单。您只需执行 SELECT a.* FROM Animal a INNER JOIN AnimalCategory ac ON a.AnimalCategoryId = ac.Id WHERE ac.RegionId = @RegionId。我对“无用”这个词的使用我想有点强。这些中间表可能对其他消费者有用,但我们只是说为了我的应用程序,除了执行 JOIN 的目的之外,根本不使用这些中间表。我的观点是,似乎 Entity Framework 迫使我创建这些实体只是为了做那个 JOIN。

标签: entity-framework orm entity


【解决方案1】:

我猜这是一个选择问题。 EF 选择支持与透明联结表的多对多关联,即联结表只有两个关联实体的外键。他们只是没有选择以类似的方式支持这种不太常见的“跳过一对多对多”场景。

我可以想象为什么。

首先,在多对多关联中,联结表只不过是:联结,关联。但是,在一对多(或多对一)关联链中,任何涉及的表都只是一个关联是例外的。在你的例子中......

Animal → AnimalCategory → Region

...AnimalCategory只有有一个主键 (Id) 和一个外键 (RegionId)。不过那将毫无用处:Animal 本身也可能有一个RegionId。没有理由支持没有意义的数据模型。

您所追求的是一个模型,其中中间的表确实携带信息 (AnimalCategory.Name),但您希望将其映射为透明连接表,因为特定的类模型不'不需要这些信息。

您的重点似乎是读取数据。但 EF 必须支持所有 CRUD 操作。这里的问题是:如何处理插入?假设Name 是必填字段。没有办法提供它的价值。

另一个问题是这样的语句...

region.Animals.Add(animal);

...可能意味着两件事:

  1. 添加一个Animal 和一个 AnimalCategory,后者指的是Region
  2. 添加一个 Animal 引用 现有 AnimalCategory - 无法选择哪一个。

EF 不想选择某些默认行为。你必须自己做出选择,所以你不能不访问AnimalCategory

【讨论】:

  • 这很好,格特。对于完整的 CRUD 支持,我想您必须定义插入/更新所需的所有必要实体。那么通常使用 EF 的人是否会定义 db/persistence 模型和单独的应用程序模型?听起来这几乎是为了从应用程序逻辑代码中隐藏某些数据库实现细节的必要条件。
  • 不是通常,不是。但它已经完成了。我会在适当的时候自己做,但我更喜欢在可行的情况下使用 EF 类。另请参阅stackoverflow.com/q/18109547/861716
猜你喜欢
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多