我试图找出如何最好地在SQL中建模以下场景。 我正在使用C#和Entity Framework。
我有多个需要文件的不同实体。 这是一些伪代码定义方案:
CategoryPage {
string Name;
Content Content;
CategoryImage Image;
}
StaticContentPage {
string Name;
Content Content;
BannerImage Banner;
}
ProductPage {
string Name;
Content Content;
ProductImage[] Images;
}
Content {
string Value;
ContentFile[] Files;
}
File {
FileData Data;
}
CategoryImage : File {
CategoryPage Category;
}
BannerImage : File {
StaticContentPage Page;
}
ProductImage : File {
ProductPage Product;
int SortOrder;
bool IsPrimary;
}
ContentFile : File {
Content Content;
}
FileData {
byte[] Data;
}
内容被分解为一个单独的实体,因为我想拥有更高级的功能,例如变更跟踪/历史记录,并希望它对任何内容部分都可以使用相同的功能。 任何内容部分所需的其他文件(图像,PDF下载等)都可以上传到该内容部分。
据我了解,外键应该位于依赖于另一个的实体中。 上面所有带有文件/图像的实体都不需要它们( CategoryPage
是完全有效的,没有图像, ProductPage
可能没有添加任何图像, Content
部分可能不需要任何其他文件),所以我想出了FK应该在File
实体上。 所以我用一个鉴别符做了一个表每个层次结构的配置:
Files
-----
Id
Discriminator
FileDataId
CategoryPageId
StaticPageId
ProductPageId
SortOrder
IsPrimary
ContentId
这是处理此问题的正确方法吗? 一方面,我之所以喜欢它,是因为当页面被删除时,它会级联到文件中并删除它们,而无需任何其他域逻辑来捕获它。 另一方面,我担心它会增加不必要的复杂性并可能导致性能问题。
我也遇到了TSQL不喜欢的多个级联路径的问题(我没有在上面显示,但是我将Content
实体分解为与File
实体类似的方式,因此当您删除Category页面时,它会级联到File表和Content表,然后再次从Content表到File表)。
拥有一个通用的File实体,将FK保持在消费者方面(即CategoryPage
, StaticContentPage
, ProductPage
和Content
实体),并处理我的域层中的删除逻辑,会更好吗? 还是为每种文件类型使用单独的表会更好? 还是我没有想到的另一种方式?