EF6数据库优先映射一对一关系。

5

在我的数据库中,我通过在外键表上设置唯一约束来强制执行一对一关系。这被Sql Server Management Studio正确识别为一对一关系:

enter image description here

我的问题是EF6无法将其识别为一对一关系,并在Person类上生成一个集合:

enter image description here

我可以轻松修改 T4 模板,以便在表上有唯一键时不生成集合,如果 t4 模板中的 itemCollection 包含唯一键信息的话。但它们只包含外键信息。我想这是因为 edmgen 工具没有从数据库中提取这些信息。
有没有一种方法强制工具包括数据库中的所有约束,以便我可以在 t4 模板中使用这些信息?
3个回答

2

选项3:在外键上放置唯一约束或唯一索引。

外键的唯一性将该关系的基数限制为最多1。我测试并确认,在使用Sql Server和EF Core 5.0进行数据库优先场景时,这是正确的脚手架。

为什么选项3可能更可取

选项3适用于1到0..1和0..1到0..1关系。这意味着您可以在现有数据库上轻松使用它而无需更改它们。

当实体在链接之前可以独立存在时,0..1到0..1关系确实很自然。扩展上面的示例,如果我们允许系统用户帐户不与任何人相关联,并且我们还有尚未创建用户帐户的人,则可以通过0..1到0..1关系来最好地对其进行建模。

如果您确定需要1到0..1关系,则选项2仍然是一个很好的选择。您可以稍后迁移到选项3,但这将需要更多的工作。

附加说明

如果你正在实现一个 [0,1] 到 [0,1] 的关系,那么你的外键字段将是可空的。在可空外键上的唯一约束通常允许多行包含 NULL,因为 NULL 不是传统 SQL 中的值。然而,Sql Server 是一个例外,在外键中只允许一个行持有 NULL。
解决方案是在 Sql Server 上使用条件唯一索引而不是唯一约束。你的条件应该仅适用于在外键中具有非空值的行。
你可以使用以下 SQL 创建这样的索引。
CREATE UNIQUE INDEX IX_User_Person
ON User (PersonId) WHERE PersonId IS NOT NULL;

1
我认为最好的解决方案是重新考虑你的表和关系。
选项1: 如果这是一个一对一的关系,你能把所有内容放在一个表中吗?
选项2: 去掉PersonId列。如果这真的是一个一对一,甚至是一个“一对零或一”的关系,那么这些表应该共享一个主键。关系应该是Id和Id之间的。如果你这样做,EF6会正确地识别它。

谢谢您。对于1到0..1的情况,选项2是正确的,其中0..1端的主键也是外键。不幸的是,它不适用于0..1到0..1的关系,即任何实体独立存在并随后链接的情况,因为这些实体通常不会具有相等的主键。我不确定我们是否有一个好的解决方案来处理这种情况。 - Kevin A. Naudé
经过思考,我认为可能有一种适用于所有一对一关系的通用解决方案。我今天会尝试并发布我的发现。 - Kevin A. Naudé

-1

兄弟听我说。你是正确的。我也遇到了同样的问题。在一个列上同时使用主键和外键,不要将主键和外键分开成两个列。这肯定会解决你的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接