SQL中的高级嵌套(层次结构)

时间:2014-03-28 10:29:07

标签: sql entity-framework hierarchical-data

我已经在层次结构,树,组合键和SQL中的更多问题上阅读了很多帖子,但我无法找到所需的信息。我正在使用EF6和SQL,C#。

案例: enter image description here

让我说我有以下型号。所以应用程序可以在每个平台上(或者只在其中的一个或两个平台上。应用程序将是一个基类,如果从代码说起,OSX和Windows和PlatformX会使他不知所措。)。但是,应用程序可以针对每个平台进行审核,并且审核可以适用于多个平台。因此,我试图建立一个不需要将评论分成3个不同表格的数据库。

有人在sql数据库中如何对此进行建模有一个很好的例子吗?或者这不可能吗?

一些必需的查询将是:   - 获取应用程序的所有指定类型(OSX,winodws等..)?   - 获取应用程序类型的所有评论。   - 获取应用程序的所有评论。   - 通过审核获取所有申请。 (然后我可以找出它是哪种类型吗?)

1 个答案:

答案 0 :(得分:1)

据我所知,ApplicationOSXWindowsPlatformX的基础实体。

我的第一句话是,如果您的~Value字段是每个组件的平台特定字段,例如

-----------  ------------------
| Windows |  | OSX            |
-----------  -----------------|
| WinApi  |  | SupportsMobile |
| TempDir |  | WrittenLang    |
-----------  ------------------

然后你可能想为Application创建一个表,它的主键是一个标识字段。建议其他实体为单独的表,但会使用Application的主键作为自己的主键,即一对一的关系。

如果您的情况不符合以上条件且您的表格将包含Value1Value2Value3以及相同的数据类型,那么我强烈建议您合并所有将类分成一个表并添加整数标志Platform。因此,您最终只能使用两个表来简化您的工作,并且不会截断功能。

然而,对于这两种情况,使用Review的案例解决方案是相同的。我建议你将Application表连接到Review表,这样可以节省你很多时间。

您的所有查询问题:是的,您可以执行所有查询。

修改

好的,让我告诉你我的愿景。

应用程序( ApplicationId ,名称,价格,命名空间)
OSX( ApplicationId * ,OSXValue1,OSXValue2,OSXValue3)
Windows( ApplicationId * ,WindowsValue1,WindowsValue2,WindowsValue3)
PlatformX( ApplicationId * ,XValue1,XValue2,XValue3)
查看( ReviewId ,ApplicationId *,FullName,ReviewText)

NB 请注意,我使用PascalCase作为字段名称。这是使用EF的一个很好的约定,因为字段将映射到属性名称(按照惯例),并且不会破坏.NET应用程序中的整体命名。

ApplicationId表中的Application是一个标识字段,是主键。在表OSXWindowsPlatformX中定义ApplicationId字段,将其定义为主键,并在ApplicationId中引用Application字段的外键每个人的表。

这是你存储它的方式。

从实体框架开始 按如下方式定义您的类

public class Application {
    private ICollection<Review> _Reviews;
    public Int64 ApplicationId { get; set; }
    /*Other fields*/
    public Windows Windows { get; set; }
    public Osx Osx { get; set; }
    public PlatformX PlatformX { get; set; }
    public ICollection<Review> Reviews {
        get { return _Reviews = _Reviews ?? new List<Review>(); }
        set { _Reviews = value; }
    }
}

public class Osx {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    [ForeignKey("Application")]
    public Int64 ApplicationId { get; set; }
    /*Other fields*/
    public Application Application { get; set; }
}

public class PlatformX {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    [ForeignKey("Application")]
    public Int64 ApplicationId { get; set; }
    /*Other fields*/
    public Application Application { get; set; }
}

public class Windows {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    [ForeignKey("Application")]
    public Int64 ApplicationId { get; set; }
    /*Other fields*/
    public Application Application { get; set; }
}

public class Review {
    public Int64 ReviewId { get; set; }
    public Int64 ApplicationId { get; set; }
    /*Other fields*/
    //Convention will catch up the ApplicationId field automatically
    public Application Application { get; set; }
}

在这里,您可以通过数据注释定义一些非显而易见的功能,例如:与常规TableName +&#39; Id&#39;不匹配的键。此外,您还指出ApplicationId字段不是使用DatabaseGeneratedAttribute自动生成的。

以下查询获取类型为OsxWindows

的所有应用程序的列表
var context = new DemoContext();
var res = context.Osx.Select(x=>x.Application).Union(context.Windows.Select(x=> x.Application));

这是对应用程序的查询及其类型

var res2 = context.Reviews.Select(x => new {
    x.Application,
    IsOsx = x.Application.Osx != null,
    IsWindows = x.Application.Windows != null,
    IsPlatformX = x.Application.PlatformX != null
});

您可以根据对象中的布尔值找出类型。