将两个不同的实体映射到同一个表?

时间:2011-02-23 16:14:42

标签: entity-framework entity-framework-4

我的数据库中有一个包含很多字段的表。 大部分时间我都需要所有这些字段。然而,有一种情况,我只需要一些字段,而且我正在加载大量的行。

我想要做的是手动添加实体,然后简单地将其映射到原始表,但删除我不需要的列。我把这一切都搞定了,但我得到了一个相当不言自明的错误:

  

映射片段的问题   ... EntitySets'FmvHistoryTrimmed'和   'FMVHistories'都映射到   表'FMVHistory'。他们的主要钥匙   可能会发生碰撞。

还有其他方法可以解决这个问题吗?同样,大部分时间都使用了所有列,因此我不想减少原始实体并将“额外”字段放入复杂类型中。

2 个答案:

答案 0 :(得分:34)

您无法将两个常规实体映射到同一个表中。你有几个选择:

  1. 使用表格拆分。
  2. 使用投影到非实体类型的自定义查询(如@Aducci建议的那样)
  3. 使用QueryView
  4. 使用数据库视图或直接使用DefiningQuery
  5. 表格拆分

    Table splitting允许您将表映射为1:1关系的两个实体。第一个实体将仅包含您需要的PK和字段子集。第二个实体将包含所有其他字段和PK。两个实体都将包含彼此的导航属性。现在,如果您只需要字段子集,则可以查询第一个实体。如果您需要所有字段,您将查询第一个实体并将navifation属性包含到第二个实体。如果需要,您还可以延迟加载第二个实体。

    <强> QueryView

    QueryView是直接在映射(MSL)中定义的ESQL查询,它被映射到新的只读实体类型。您可以使用QueryView定义完整实体到子实体的投影。必须在EDMX中手动定义QueryView(它在设计器中不可用)。据我所知,CodeView在Code中不可用,但它实际上与自定义投影到非实体类型相同。

    <强> DefiningQuery

    DefiningQuery是直接在您的存储模型(SSDL)中定义的自定义查询。定义查询通常在映射到数据库视图时使用,但您可以将其用于任何自定义SQL SELECT。您将查询结果映射到只读实体类型。必须在EDMX中手动定义DefiningQuery(在设计器中不可用)。它在Code中也不是直接可用的,但实际上与在SqlQuery上调用DbDatabase相同。 DefiningQuery的问题在于,一旦在SSDL中手动定义它,就无法使用数据库中的更新模型,因为此操作会替换完整的SSDL并删除您的查询定义。

答案 1 :(得分:8)

我会在数据库上创建一个仅包含所需数据的视图,并将View添加到您的实体数据模型中。

如果您不想修改数据库,可以创建一个Linq to entities或ESQL语句,仅使用您需要的信息投射到POCO类。

public IQueryable<SimpleObject> GetView(DBContext context)
{
    return  (from obj in context.ComplexObjects
            select new SimpleObject() { Property1 = obj.Property1,
                                        Property1 = obj.Property2
                                      }); 
}