定义实体框架1:1关联

时间:2009-01-24 00:09:27

标签: .net visual-studio entity-framework ado.net

我正在尝试在实体框架模型中定义两个实体之间的1:1关联(一个映射到表,另一个映射到视图 - 使用DefinedQuery)。 在设计器中尝试为此定义映射时,它会让我选择(1)表或视图来将关联映射到。我应该选择什么?我可以选择这两个表中的任何一个,但后来我被迫从该表(或视图)中为每个关系结束选择一列。我希望能够从一个表中选择一个列作为关联的一端,另一个表中的列作为关联的另一端,但是没有办法做到这一点。

在这里,我选择映射到“DW_ WF_ClaimInfo”视图,它迫使我从该视图中选择两列 - 一个用于关系的每一端。

我也尝试在XML中手动定义映射,如下所示:

<AssociationSetMapping Name="Entity1Entity2" TypeName="ClaimsModel.Entity1Entity2"
     StoreEntitySet="Entity1">
  <EndProperty Name="Entity2">
    <ScalarProperty Name="DOCUMENT" ColumnName="DOCUMENT" />
  </EndProperty>
  <EndProperty Name="Entity1">
    <ScalarProperty Name="PK_DocumentId" ColumnName="PK_DocumentId" />
  </EndProperty>
</AssociationSetMapping>

但是这给了: 错误2010:MetadataWorkspace中不存在作为此MSL的一部分指定的列“DOCUMENT”。 好像它仍然希望两列都来自同一个表,这对我来说没有意义。

此外,如果我为每一端选择相同的密钥,例如:

<AssociationSetMapping Name="Entity1Entity2" TypeName="ClaimsModel.Entity1Entity2"
     StoreEntitySet="Entity1">
  <EndProperty Name="Entity2">
    <ScalarProperty Name="DOCUMENT" ColumnName="PK_DocumentId" />
  </EndProperty>
  <EndProperty Name="Entity1">
    <ScalarProperty Name="PK_DocumentId" ColumnName="PK_DocumentId" />
  </EndProperty>
</AssociationSetMapping>
然后我得到:

Error 3021: Problem in Mapping Fragment starting at line 675: Each of the following
columns in table AssignedClaims is mapped to multiple conceptual side properties:
  AssignedClaims.PK_DocumentId is mapped to
    <AssignedClaimDW_WF_ClaimInfo.DW_WF_ClaimInfo.DOCUMENT,
    AssignedClaimDW_WF_ClaimInfo.AssignedClaim.PK_DocumentId>

我没有得到什么?

9 个答案:

答案 0 :(得分:6)

您必须选择包含外键的表。下一步是从实体中删除该外键,因为它已经使用您刚刚创建的关系表示。

示例:

table A
-------
A_ID int
B_ID int


table B
-------
B_ID int

在这种情况下,您将在设计器中选择表A,因为它包含外键。此外,您还需要从A实体中删除B_ID。

答案 1 :(得分:0)

我正在处理遗留应用,因此添加额外的主键对我来说不是一个选择。我必须做的是将其映射为1:(0或1)而不是1:1以使其工作。例如,如果我有两个表,则表示Customer和CustomerDetails都有一个名为CustomerID的主键。要创建关联,我必须将其设置为1客户可以与(0或1)CustomerDetails记录相关联。 Eveytime您插入客户,请务必同时插入CustomerDetails以便维持1:1。

答案 2 :(得分:0)

我同意这种设置方式似乎违反直觉。对于那些太慢(像我一样)的人来说,得到一个答案: 根据下面的论坛帖子,我记得我们正在处理一个实体,而不是直接处理一个表。该关联位于实体(可以对表进行建模,但不必)。

http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/2823634f-9dd1-4547-93b5-17bb8a882ac2/

实体框架正在将 PROPERTIES TABLE COLUMNS 相关联。这就是为什么我们必须删除 ENTITY 上的“外键” PROPERTY (注意:我们不删除表格列)。要在代码中引用该列(使用 ENTITY 建模表A和表B的给定示例),您将编写如下内容:

variable_A = tableAs.A_ID
variable_B = tableAs.tableBs.B_ID

第二个分配是使用实体中定义的关联来获取数据。表A中没有名为“B_ID”的 PROPERTY

这就是假设我理解正确:)。现在至少对我来说是正确的知识产权。

: - 丹

答案 3 :(得分:0)

首先在数据库中创建一个外键,然后从数据库创建关联或更新模型。

答案 4 :(得分:0)

在实体框架中,在概念设计中应该没有外键。我相信现在允许在EF4(有一些调整),但在EF3.5中,它不能是完成。

要解决此问题,只需删除EF设计器中代表外键的所有属性。不要删除主键!

如果您接着“关联结束未映射..”错误,请参阅(我的回答)this post

答案 5 :(得分:0)

当我尝试在主键上连接的两个表之间进行一对一时,我收到了同样的错误。 (不,我没有设计数据库)。因此,删除FK的解决方案不起作用 - FK也是PK,因此您不会删除它。作为一个实验,我将关联的一侧改为0..1,并且看,模型编译没有错误。我使用的是EF3.5

答案 6 :(得分:0)

简单来说,我做了以下几点:

  1. 在列上创建包含主键(PK)的表。
  2. 在列上创建带外键(FK)的视图。 反之亦然。
  3. 在edmx Diagram Designer中,创建了一个Association。
  4. 编译代码。
  5. 在XAML元数据代码中,具有PK的父实体将显示子视图实体,可以将其关联以绑定项目。

答案 7 :(得分:0)

经过一整天的努力,我明白了!事实上,我发现有两种不同的方法可以解决这个问题,假设我遇到了同样的问题Craig。

首先,driAn的回答并没有真正的帮助(再一次,如果Craig遇到同样的问题),因为问题是表A中没有单独的外键。表A的主键完全相同表B的主键!特别是在我的情况下,我使用的是视图和表,而不是两个表:

table A
-------
A_ID int
col1 int
col2 int

view A_extra
-------
A_ID int
col3 int

所以,以下是我找到的解决方案:

<强> 1。映射到两个不同的实体,但使用hack。因此,driAn的答案的全部问题是我们没有单独的外键列要映射到,我们可以从属性中删除(我们可以' t从属性中删除它,因为它是视图A_extra的主键!)。因此,一旦你意识到hack是非常简单的:编辑A_extra并简单地创建一个A_ID副本并使其成为替代外键:

table A
-------
A_ID int
col1 int
col2 int

view A_extra
-------
A_ID int
A_FK_ID int        
col3 int

A_FK_ID在视图的SQL中简单地定义为'A_ID as A_FK_ID',它将始终具有与A_ID完全相同的值。

现在,对于实体框架,这是一个非常熟悉的场景。只需创建1对1关联,将关联映射到A_extra,并将表A中的属性A_ID映射到A_FK_ID,将A_extra中的属性A_ID映射到A_ID。现在你不再按照EF那样让同一列完成双重任务!然而,有趣的是,A_FK_ID将始终与A_extra中的A_ID相同。

现在您有一个到A_extra的导航属性,并且可以访问col3,就像您期望的那样。更好的是,您仍然可以原生地更新table_A,因为EF看到它是一个表(如果您从这个组合中创建了一个视图并将其导入EF,则无法对其进行本机更新)。

<强> 2。将表和视图映射到单个实体。您不需要对此解决方案进行破解,并且它更可取,因为您不必通过导航属性来获取col3。

要获得此配置,请将A和A_extra添加到EF。将col3从A_extra复制并粘贴到A中,这样你现在将未映射的属性“col3”放在A中,而在A_extra中没有任何内容。现在转到A的映射并添加A_extra作为要映射到的视图(以便实体“A”现在映射到表“A”和视图“A_extra”)。将属性col3(在实体A中)映射到列col3(在视图A_extra中)。 现在,您可以通过以下方式向EF展示如何加入两者来创建单个实体:将A_extra中的A_ID列映射到实体A中的属性ID。如果您注意到,现在您已将两个列映射到相同的财产。这没关系,因为它们代表相同的东西,而且正是EF知道加入该列的方式。

现在,要完成清理工作,您必须删除设计器中的浮动实体“A_extra”。 (您可能希望确保它不再映射到查看A_extra只是为了确保它不会带走A_extra的商店映射 - 我希望它不会因为实体A现在映射到它)。现在,您应该能够从实体A构建和访问col1,col2和col3!

很酷的是你可以将数据更新到col1和col2,因为它们被映射到一个表(A),但EF会阻止你更新col3,因为它被映射到一个视图(A_extra) 。这比在数据库中创建A组合视图并导入它更方便,因为EF会阻止您更新任何列,因为它们都是从视图中获取的。

哇,我很高兴我终于工作了。希望我的解决方案帮助你们!

-Robert

答案 8 :(得分:-3)

没有得到答案,但是使用Entity Framework,我总是在每个表中创建一个主键(即使我不需要它)。示例:

  • 表客户将CustumerID作为主键
  • 表产品将ProductID作为主键
  • 表顺序当然使用CustomerID + ProductID作为主键。好吧,我还创建了一个本地主键:OrderID。