下面是我的数据库结构的简化版本(使用Entity Framework 4作为我的ORM在MVC 2中构建概念验证站点):
[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):我以前从未实际执行此操作。这似乎是“最简单”的答案,但我不确定它是否会在以后回来咬我。 鉴于不强制执行这两个外键约束似乎是最简单的选择,我的实现将是:
ItemName
添加到[FavouriteSizes]
,并在用户收藏大小时使用ItemSize.Item.ItemName
填充FavouritedSize.Items Is Nothing
),以便用户可以从收藏夹列表中删除该项目。这种实施是否会引发问题?有足够的理由说明为什么我应该去实现软删除而不是仅仅执行引用完整性(除了保留报告的历史数据)?我错过了一个更适合的选择吗?
答案 0 :(得分:2)
不强制执行参照完整性是一件很危险的事情,除非你完全确定没有,但你的应用程序将填充此表中的数据(并且您的应用程序当然经过测试以确保它保留了诚信)
在实际情况中,我发现这种方法存在风险,因为一旦系统投入生产,总有可能会出现其他应用程序,特别是数据迁移工具/补丁/一些直接数据操作一些紧急情况 - 最终操纵数据并且在没有约束的情况下,他们将无法识别关系,并可能最终放入不正确的数据。
此外,我不知道你是否需要这个输入,但看看你的架构,我可能会考虑稍微改变
[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 - 但总的来说,我会说确保检查始终存在于所有查询中,这很容易通过确保检查特定点来完成 - 作为审核流程的一部分。通常,它在团队中成为第二天性,并且需要额外的努力来确保检查可以忽略不计。