sql-server - 软/逻辑删除 vs 无参照完整性 vs ...?

标签 sql-server asp.net-mvc-2 entity-framework-4

下面是我的数据库结构的简化版本(在 MVC 2 中构建一个概念验证站点,使用 Entity Framework 4 作为我的 ORM):

[Stores]
StoreID (PK)
StoreName

[Items]  
ItemID (PK)  
ItemName
Description
StoreID (FK)

[ItemSizes]
SizeID (PK)  
SizeName
Price
ItemID (FK)

[Users]
UserID (PK)
UserName

专卖店 出售 项目 ,其中有不同的 尺寸 . [Users]代表标准的 asp.net 成员(member)商店。

我想实现用户能够“收藏”和评价特定项目(和尺寸),所以我最初的冲动是实现几个基本的映射表:
[FavouriteSizes]
UserID (PK) (FK)
SizeID (PK) (FK)

[ItemRatings]
UserID (PK) (FK)
ItemID (PK) (FK)
Rating

但是,如果我强制执行参照完整性,当店主想要删除商品、商品大小甚至关闭他/她的整个商店时,我当然会遇到问题。

我确定的选项是:
  • 级联删除 :主要的缺点是用户下次登录时,他最喜欢的项目完全丢失
  • 软/逻辑删除 :在这种情况下我回避它们,因为当我过去使用它们时,不得不添加 WHERE IsActive表连接使每个查询变得繁琐。另外我相信(如果我错了,请纠正我)这会增加 EF4 中的一些复杂性,例如 Items.Includes("ItemSizes") .
  • 不强制参照完整性(仅在 [FavouriteSizes].SizeID FK 和 [ItemRatings].ItemID FK 上) : 我以前从来没有这样做过。这似乎是“最简单”的答案,但我不确定它以后是否会回来咬我。

  • 鉴于不强制执行这 2 个外键约束似乎是最简单的选择,我的实现将是:
  • 添加 ItemName[FavouriteSizes] ,并用 ItemSize.Item.ItemName 填充它当用户喜欢尺寸时
  • 如果收藏夹不再可用( FavouritedSize.Items Is Nothing ),则添加一个助手以显示通知,以便用户可以从他们的收藏夹列表中删除该项目。
  • 确保任何“评分最高的项目”类型的报告只撤回仍然存在的项目。

  • 这种实现会在 future 引起问题吗?是否有足够的理由让我不惜执行软删除而不是不强制执行参照完整性(除了保留历史数据以进行报告)?我是否错过了更适合的选项?

    最佳答案

    不执行参照完整性是一件有风险的事情,除非您绝对且完全确定除了您的应用程序之外没有任何人会在此表中填充数据(并且您的应用程序当然经过测试以确保其保持完整性)

    在实际场景中,我发现这种方法有风险,因为一旦系统投入生产,总会有其他应用程序出现的可能性,尤其是在某些紧急情况下的数据迁移工具/补丁/一些直接数据操作- 最终会操纵数据,并且在没有约束的情况下,他们将无法识别这种关系,并且可能最终会输入不正确的数据。

    此外,我不知道您是否需要此输入,但是查看您的架构,我可能会考虑稍作更改

    [Stores]
    StoreID (PK)
    StoreName
    
    [Items]  
    ItemID (PK)  
    ItemName
    Description
    StoreID (FK)
    
    [Sizes]
    SizeID (PK)  
    SizeName
    
    [ItemSizes]
    ItemID (PK)
    SizeID (PK)  
    Price
    
    [Users]
    UserID (PK)
    UserName
    

    注意:我已经拆分了您的 [ItemSizes]表成[Sizes][ItemSizes] .

    通过这种方式,您可以收藏一个项目或一个尺寸(如您目前正在做的那样),甚至是特定尺寸的项目。
    [FavouriteSizes]
    UserID (PK) (FK)
    SizeID (PK) (FK)
    IsActive
    
    [FavouriteItemSizes]
    UserID (PK) (FK)
    ItemID (PK) (FK)
    SizeID (PK) (FK)
    IsActive
    
    [ItemRatings]
    UserID (PK) (FK)
    ItemID (PK) (FK)
    Rating
    IsActive
    

    总而言之,添加 IsActive字段,甚至到您的收藏夹和评级表 - 除了您的主表 - 使用 WHERE IsActive检查和制作收藏夹/评级是软的 - 在删除项目/项目大小/大小时删除,然后在显示您的收藏夹/评级时显示附加逻辑,以表明不存在较早添加的评级/收藏给用户,似乎对我来说更好的选择。

    我不是特别确定 IsActive 检查如何与 EF 一起使用 - 还没有使用 EF - 但总的来说,我会说通过确保检查特定点来确保检查始终存在于所有查询中很容易完成 - 作为一部分审查过程。通常,它成为团队中的第 2 种性质,并且确保检查可以忽略不计的额外努力。

    关于sql-server - 软/逻辑删除 vs 无参照完整性 vs ...?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4383533/

    相关文章:

    c# - 单击一次安装 System.Data.SqlServerCe 出现问题?

    python - 通过 pyodbc 连接到 Azure SQL 数据库

    asp.net-mvc-2 - 如何在 View 和另一个 View 模型之间传递数据?

    asp.net-mvc-2 - 调用 EditorFor(...) 时隐藏公共(public)属性的编辑器标签?

    entity-framework - Entity Framework 4:选择单个记录

    sql-server - 没有关系/有关系的数据库设计,我应该使用外键吗?

    sql - 选择列上的 MAX,然后从依赖于第一个值的列中选择 MAX

    asp.net-mvc-2 - 无法将类型 'double?' 隐式转换为 'double'

    transactions - EF4 Code First、TDD、CRUD 和事务

    c# - 如何从 EF DbUpdateException 中获取一些附加信息