【问题标题】:Soft/Logical Deletes vs No Referential Integrity vs ...?软/逻辑删除 vs 无参照完整性 vs ...?
【发布时间】:2010-12-08 10:32:29
【问题描述】:

下面是我的数据库结构的简化版本(在 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 会员商店。

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

[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 上):我以前从未真正这样做过。这似乎是“最简单”的答案,但我不确定它以后是否会回来咬我。

鉴于不强制执行这两个外键约束似乎是最简单的选择,我的实现是:

  1. ItemName 添加到[FavouriteSizes],并在用户喜欢某个尺寸时使用ItemSize.Item.ItemName 填充它
  2. 添加一个助手以在收藏项不再可用时显示通知 (FavouritedSize.Items Is Nothing),以便用户可以从他们的收藏列表中删除该项。
  3. 确保任何“评分最高的项目”类型的报告只撤回仍然存在的项目。

此实施是否会在未来引发问题?是否有足够充分的理由让我不遗余力地实施软删除,而不是仅仅不强制执行参照完整性(除了保留历史数据以供报告)?我是否错过了更适合的选项?

【问题讨论】:

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


    【解决方案1】:

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

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

    另外,我不知道你是否需要这个输入,但是看看你的架构,我可能会考虑稍微改变一下

    [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 - 但总的来说,我会说通过确保检查特定点来确保检查始终存在于所有查询中很容易完成 -作为审查过程的一部分。通常,它成为团队中的第二自然,并且确保检查可以忽略不计的额外努力。

    【讨论】:

    • 感谢额外的模式输入...我没有添加额外的尺寸表,因为尺寸信息是特定于商店的:一些商店使用“小 - 5 美元,大 - 15 美元”,其他使用“5 10 美元,10 美元 15 美元”,具体取决于商店出售的商品和商品。
    猜你喜欢
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    相关资源
    最近更新 更多