Dan*_*Eli 7 sql orm database-design entity-framework foreign-keys
在表格中包括祖父母+外围钥匙有什么好处和责任.
例如,如果我的对象模型如下所示.(非常简化,所以它不适用于层级递归表.)
a {aId, bCollection, ...}
b {bId, cCollection, ...}
c {cId, dCollection, ...}
d {dId}
Run Code Online (Sandbox Code Playgroud)
想到的两个数据模型选项是:
选项1:
a {pkA, ...}
b {pkB, fkA, ...}
c {pkC, fkB, ...}
d {pkD, fkC, ...}
Run Code Online (Sandbox Code Playgroud)
选项2:
a {pkA, ...}
b {pkB, fkA, ...}
c {pkC, fkB, fkA, ...}
d {pkD, fkC, fkB, fkA, ...}
Run Code Online (Sandbox Code Playgroud)
选项1更加规范化,插入和更新将更容易,但我可以看到查询变得非常复杂,特别是有很多关系和/或复合键.
选项2使插入和更新变得复杂,但提取报告将更容易.此外,数据库将更大,但我并不真正关心它,因为它无论如何都很小.
但与那些与ORM类实体框架相关的问题相比,这些问题相当微不足道.我倾向于选项2,因为我想直接从父母那里访问孙子,如下所示:
Class A { id, bCollection, cCollection, dCollection, ... }
Class B { id, cCollection, dCollection, ... }
Class C { id, dCollection, ... }
Class D { id, ...}
Run Code Online (Sandbox Code Playgroud)
实体框架4.0是否优雅地处理这种情况?这两种选择的优缺点是什么?我还应该考虑另一种选择吗?
或者更简单的说,一个人如何谷歌这个问题?!?
另外一个注意事项:像你们中的许多人一样,必须对选项A有很大的帮助,但我知道我已经阅读了一篇msdn文章,该文章详细介绍了为什么选项B更好.不幸的是,我找不到它.:(
提前感谢您的想法.
我会避免选择B像瘟疫一样.无论是选择基本上是更复杂的比其他的查询,但第二个选项是多少更难以维持,并迫切需要规范化到选项A.
对于查询选项A,您所谈论的只是添加简单连接.由于这不是递归关系,因此您必须已经预先知道查询可以"深入"多少级别,因此您不必担心它是脆弱的或只是为潜在案例的子集工作.
比较选择您最深层的情况,您正在寻找深层嵌套节点的顶级父级:
选项A:
select
a.id
from d
join c on c.id = d.c_id
join b on b.id = c.b_id
join a on a.id = b.a_id
where d.id = @id
Run Code Online (Sandbox Code Playgroud)
选项B:
select a_id from d where id = @id
Run Code Online (Sandbox Code Playgroud)
选项A 更复杂吗?是的,但它不应该成为任何人弄清楚正在发生什么的挑战.
至于与EF4的兼容性,这不是问题.您可以以线性方式向上导航父母链,以获得您想要的祖父母.您可以在代码或查询中执行此操作; 任何一个都可以正常工作:
在代码中:
var entity = context.D.Where(d => d.Id == 4).First();
var grandParent = entity.C.B.A;
Run Code Online (Sandbox Code Playgroud)
在查询中(使用LINQ和连接):
var grandparent = (from d in context.D
join c in context.C on d.CId == c.Id
join b in context.B on c.BId == b.Id
join a in context.A on b.AId == a.Id
where d.Id == id
select a // or a.Id).First();
Run Code Online (Sandbox Code Playgroud)
在查询中(使用导航属性):
var grandparent = (from d in context.D
where d.Id == id
select d.C.B.A // or d.C.B.A.Id).First();
Run Code Online (Sandbox Code Playgroud)