2

概述

我正在设计一种机制,用于在使用 ADO.NET 实体框架的 ASP.NET MVC 应用程序中生成动态控件。但是,我的问题与 MVC 无关,与实体框架无关。它是关于比较两个对象模型。

问题陈述

在我的应用程序中,用户必须能够与网页 A进行交互,以指定他想要向网页 B添加这样和这样的 HTML 控件。

当他接下来浏览网页 B时,他必须看到这些控件并且能够使用它们。

什么不是挑战

我已经编写了代码来生成控件。那是容易的部分。我使用了 Tag Builder、Partial Views、HtmlHelper 扩展和 Display & Editor 模板。

挑战 挑战在于实现由实体框架生成的数据库设计和对象模型,以保存有关需要生成的控件的元数据。

我想出了一个数据库设计,如下所示:

数据库图

您可以忽略UserPermissions表。它们与我们的讨论无关。

Entity Framework 基于上述数据库设计生成以下实体。

基于数据库设计的实体框架模型

让我们将我的数据库设计称为Design Option A

我本来想要一个看起来更像这样的设计:

我希望拥有的对象模型:更直观的选择

让我们将第二个设计称为设计选项B。

第二个选项的代码(精简版)如下所示:

namespace DynamicControls
{
    public class DynamicControlGroup
    {
        public long Id { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        public string Controller { get; set; }

        public IEnumerable<string> Actions { get; set; }

        public DateTime StartDate { get; set; }

        public DateTime? EndDate { get; set; }

        public User CreatedByUser { get; set; }

        public DateTime CreationDateTime { get; set; }

        public User LastModifiedBy { get; set; }

        public DateTime ModificationDateTime { get; set; }

        // Navigational
        public ICollection<DynamicControl<T>> DynamicControls { get; set; }
    }

    public class DynamicControl<T>
    {
        public long Id { get; set; } //db Id

        public string HtmlId { get; set; }

        public bool ValueRequired { get; set; }

        public virtual ControlType ControlType { get; protected set; }

        // Every control is capable of having a default value but of a different
        // type. Most controls have default values of type text (string). The
        // multi-select ones (checkboxes, multi-select lists, etc.) have a default
        // value of type IEnumerable<string>. So, I want to leave this generic.
        // But I am not that hung-up on this. I am fine if I am required to move
        // this property DefaultValue from the base class and make it a concrete 
        // (not generic) property for each individual child class.

        // Mostly I just want the heirarchy. And before that, I want to know
        // if it is a good idea to model this heirarchy. Or is it better to just
        // work with what my Entity Framework produced for my db?

        // Should I change my db? I can because I thought-up the design for
        // those tables.
        public virtual T DefaultValue { get; set; }

        // Navigational
        public DynamicControlGroup DynamicControlGroup { get; set; }
    }

    public class TextBox : DynamicControl<string>
    {
        public override ControlType ControlType
        {
            get
            {
                return DynamicControls.ControlType.TextBox;
            }
        }

        public string Label { get; set; }

        public int MaxLength { get; set; }
    }

    public class PasswordControl : TextBox
    {
        public override ControlType ControlType
        {
            get
            {
                return DynamicControls.ControlType.Password;
            }
        }
    }

    public class TextArea : TextBox
    {
        public override ControlType ControlType
        {
            get
            {
                return DynamicControls.ControlType.TextArea;
            }
        }

        public int Rows { get; set; }
    }

    public class DropDownList: DynamicControl<string>
    {
        public override ControlType ControlType
        {
            get
            {
                return ControlType.DropDownList;
            }
        }

        // I want something like this. That I should be able to say
        //
        // myDropDownListObject.Options...
        // 
        // You'll notice that given my current database design, I have
        // no direct way of accessing the options of a, say, drop down list.
        // To do that, I have to make a round-about Linq query.
        public ICollection<DynamicControlOption> Options { get; set; }
    }

    public class DynamicControlOption
    {
        public long Id { get; set; } // db Id

        public string OptionHtmlId { get; set; }

        public string OptionValue { get; set; }

        public string OptionText { get; set; }

        // Navigational property
        public DynamicControl<IEnumerable<string>> TheControlWhoseOptionIAm { get; set; }
    }

    public class User
    {
    }

    public class Permission
    {
    }

    public enum ControlType
    {
        TextBox,
        TextArea,
        Password,
        RadioButton,
        Checkbox,
        DropDownList,
        MultiSelectList,
        DatePicker,
        TimePicker,
        DateTimePicker
    }
}

我的问题 1) 我觉得我更喜欢设计选项 B。我感觉对吗?

2) 我知道我可以使用设计选项 A一样好,但它会涉及一些迂回的方式来做一些事情。例如,要获取下拉列表的所有选项,Design Option A中的 DropDownList 类没有导航属性。我将不得不编写一个循环的 Linq 查询来做到这一点。

3)是否有可能让实体框架接近生成设计选项 B?如何?为了实现这一目标,我需要对我的数据库设计进行哪些更改?

4

1 回答 1

1

现在我们正在我们公司从事这样的项目......如果我正确理解了你的意思,如果我是你......我实现了继承结构作为我的数据库设计,如下所示。现在你的类是继承,但你的数据库设计不是。

我已删除TextBox中的Id,并将ControlId同时作为 PK 和 FK。(不仅仅是FK)。

实际上,ControlId 是TextBoxPKDynamicControl的FK以及PasswordControlTextArea 的这种方式

现在 TextBox中的ControlId不是Identity。它从DynamicControl获取它的 ControlId

在此处输入图像描述

我也接受设计选项 B。我总是比使用设计选项 A更舒服。在我的想法中这是真实的主要结构

于 2013-05-03T13:07:20.383 回答