我试图弄清楚如何最好地在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
实体上。所以我用一个鉴别器做了一个Table Per Hierarchy配置:
Files
-----
Id
Discriminator
FileDataId
CategoryPageId
StaticPageId
ProductPageId
SortOrder
IsPrimary
ContentId
这是处理此问题的正确方法吗?一方面,我喜欢它,因为当一个页面被删除时,它将级联到文件并删除它们,而没有任何额外的域逻辑来捕获它。另一方面,我担心它会增加不必要的复杂性并可能导致性能问题。
我也遇到了TSQL不喜欢的多个级联路径的问题(我没有在上面显示它,但是我以与{{1}类似的方式打破了Content
个实体实体,所以当你删除Category页面时,它会同时级联到File表和Content表,然后再从Content表级联到File表。
仅拥有一个通用的File实体,将FK保留在消费者一方(即File
,CategoryPage
,StaticContentPage
和ProductPage
会不会更好?实体),并处理我的域层中的删除逻辑?或者为每种文件类型设置单独的表会更好吗?还是有另一种我没想到的方式?