【发布时间】:2022-06-14 01:14:50
【问题描述】:
给定一个包含对其父级(邻接列表)的引用的数据模型:
class Foo
{
public int Id { get; set; }
virtual Foo Parent { get; set; }
}
如何保证不会向数据库提交循环引用?
好的:
a
b
c
不行:
a
b
c
a
我可以通过设置隔离级别(设置为可序列化)来做到这一点吗?这最好在数据库本身中使用某种触发器来完成吗?我应该为我的分层数据使用不同的模型吗?
【问题讨论】:
-
“我可以通过设置隔离级别(设置为可序列化)来做到这一点吗?” - 事务隔离级别更关注低级不一致的读取,而不是违反自定义
CHECK约束。 -
"最好在数据库中使用某种触发器来完成这项工作?" - 您应该完全避免在表上触发触发器,因为它们会破坏
OUTPUT子句,更不用说使用它们会带来巨大的痛苦,因为它们不是声明性的:而是将CHECK约束与自定义 UDF 一起用于非平凡的约束表达式- 但请注意在 CHECK 约束中在 UDF 中使用查询的性能影响(请注意,我通常避免触发器的建议不适用于VIEW对象上的触发器)。 -
“给定一个包含对其父级(邻接列表)的引用的数据模型”-您发布的
class Foo没有显示邻接列表,并且您还没有定义您的关键列-所以我不知道 EF 如何将其转换为CREATE TABLE语句 - 但无论如何:虽然 EF 和 EF Core 确实支持模式迁移并从 C# 类定义创建数据库设计,但它仍然远不如做的灵活和富有表现力手动数据库设计,这意味着如果我遇到你的情况,这个问题没有实际意义,因为我不会依赖 EF 来创建约束。 -
@Dai 感谢您的 cmets,我在问题中的 DataModel 中添加了一个 Key 属性。因此,如果事务隔离级别不起作用,我应该避免触发器,并且 UDF 具有性能影响,并且您不会使用 EFCore 创建约束,您将如何处理这种情况?你会使用不同的数据模型(嵌套集吗?)?某种锁定系统,然后在代码中进行父/子分析?使用仅在父/子关系有效时才允许更新的原始 SQL 查询?
-
您可以在事务中保存更改,然后执行递归查询 (CTE) 以验证最终的数据库记录集,并在出错时回滚。作为最终测试,以确保多个用户无法更改不同的记录并创建循环。
标签: c# sql entity-framework-core hierarchical-data adjacency-list