我的EF6代码优先模型似乎非常低效,但我不知道如何改进它。我错过了什么吗?

时间:2016-09-19 05:00:34

标签: c# sql asp.net entity-framework relational-database

我目前正在使用实体框架6使用代码优先方法在asp.net中建模两个类。用户可以创建一个Widget,其中Widget最多包含五个WidgetOptions。选项主要是字符串,但是存在与其他用户需要交互的元数据(因此它们不仅仅是字符串的集合)。目前,我的课程看起来像这样:

Widget {
    public string Name {g;s;}
    ... //more fields
    public string ICollection<WidgetOption> Options {g;s;}
}

WidgetOption {
    public string Option {g;s;}
    ... //more fields
}

这显然看起来很简单,但这是我的想法。因此,当前用户在UI中创建窗口小部件时,控制器正在从用户输入的字符串创建WidgetOptions列表,将WidgetOptions分配给窗口小部件,然后保存到数据库上下文。如:

Create(WidgetFormViewModel vm) {
    var options = vm.WidgetOptions.Select(wo => new WidgetOption(wo)).ToList();
    var widget= new Widget { 
        Options = options,
        // ... other fields from vm
    };
    _context.Widgets.Add(widget);
    _context.SaveChanges();
    return RedirectToAction("Index", "Home");
}

问题是许多用户可能会重复WidgetOption字符串。例如,许多用户可能会将选项命名为“红色”以使Widget变为红色(虽然这可能看起来很奇怪,但实际情况更有意义)。实体框架目前正在将类建模为在Widget中没有引用WidgetOption的列,以及具有Id,Option和Widget_Id列的WidgetOption。

因此,如果两个用户使用“红色”WidgetOption创建一个Widget,则会在WidgetOption表中创建两行。每个都有一个唯一的Id,每个都有相应的Widget_Id。这似乎在空间方面效率很低,但我可能是错的(因为它没有我认为浪费的空间那么多)。我想,即使我有一个单独的表只有唯一的WidgetOption字符串,我仍然需要一个将Widget连接到Many WidgetOptions的关系表。如果关系表中的WidgetOption_Id远小于字符串本身,那么这可能比当前模型更有效,对吧?除此之外,我将不得不搜索用户输入的每个字符串以查看它是否已创建。所以我会牺牲存储速度。

我不确定我是否过度思考这个问题,但我觉得很奇怪有一个WidgetOptions重复的表格。如果只有少数独特的选项字符串,则多对多关系更有意义,而当前模型如果每个选项字符串都是唯一的则有意义。看起来正确的选择只能通过弄清楚这种规模的哪一端在实践中发生来解决。

1 个答案:

答案 0 :(得分:0)

以这种方式重写您的WidgetWidgetOption个实体:

Widget {
    public string Name {g;s;}
    ... //more fields
    public virtual ICollection<WidgetOption> WidgetOptions {g;s;}
}

WidgetOption {
    public string Option {g;s;}
    ... //more fields
    public virtual ICollection<Widget> Widgets {g;s;}
}

它会告诉实体框架定义many-to-manyWidget之间的WidgetOption关系。我相信这应该照顾困扰你的问题。但是,可能需要稍加更改代码才能添加WidgetOptions