每个层次结构的表有外键 - 最佳实践

时间:2016-12-21 15:05:17

标签: c# sql entity-framework tsql database-design

我试图弄清楚如何最好地在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保留在消费者一方(即FileCategoryPageStaticContentPageProductPage会不会更好?实体),并处理我的域层中的删除逻辑?或者为每种文件类型设置单独的表会更好吗?还是有另一种我没想到的方式?

0 个答案:

没有答案