【问题标题】:How to create a "dynamic" database structure (EF Code-First)如何创建“动态”数据库结构(EF Code-First)
【发布时间】:2011-11-30 03:36:30
【问题描述】:

我正在尝试使用实体框架代码优先来实现 Web 应用程序。 我将在这样的示例中解释问题:

在我的数据库中有一系列产品。

public class Product
{
    public long Id { get; set; }
    public string Name { get; set; }
    public virtual Type type { get; set; }
    //..... Some other properties .....
}

每种产品都有自己的类型(食品、药品、多媒体等)。同样在我的数据库中将是这些类型的集合,它将由最终用户定义,并且将来可能会被修改/增加。

public class Type
{
    public long Id { get; set; }
    public string Name { get; set; }
    //..... Some other properties .....
}

如您所知,每种产品都有自己的属性,具体取决于产品的类型。假设药物可能有

public bool PrescriptionOnly { get; set; }

和多媒体类型可能有

public Size DisplaySize { get; set; }

正如我之前提到的,类型将由最终用户定义,因此属性的数量和每个属性的数据类型现在是未定义的。此外,用户应该能够通过属性的特定值过滤产品(过滤模型取决于产品类型)。而这一切都应该使用 Code-First 模型来实现。

总而言之,我被卡住了,因为我不知道如何使用 EF Code-First 创建这种“动态”数据库结构。我想在 Type 类中创建一个字符串字段并保存 [key=value] 对,但这几乎不可能使用分页结果创建快速有效的填充。

对于我的问题的任何建议或解决方案,我将不胜感激。

最好的问候! 卢卡斯


我创建了这样的示例代码来可视化问题。数据库结构如下:

Category1 = "食物" [Property1 = "ForVegetarian", Property2 = "卡路里"] ## - Product1 = "披萨" ["false", "1500"] - Product1 = "沙拉" ["true", "300"]

Category2 = "多媒体" [Property1 = "DisplaySize", Property2 = "Warranty"] ## - Product1 = "PlasmaTV" ["55''", "36m"] - Product1 = "LCDMonitor" ["24''", "12m"]

public class Property
{
    public long Id { get; set; }
    public string Name { get; set; }
}

public class ProductCategory
{
    public long Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Property> Properties { get; set; }
    public virtual ICollection<Product> Products { get; set; }
}

public class PropertyValue
{
    public long Id { get; set; }
    public virtual Property Property { get; set; }
    public string Value { get; set; }
}

public class Product
{
    public long Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<ProductCategory> Categories { get; set; }
    public virtual ICollection<PropertyValue> Properties { get; set; }
}

public class TestDataBase : DbContext
{
    public DbSet<ProductCategory> Categories { get; set; }
    public DbSet<Property> Properties { get; set; }
    public DbSet<PropertyValue> Values { get; set; }
    public DbSet<Product>   Products    { get; set; }
    public TestDataBase()
    { }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    { }
    public static readonly TestDataBase context = new TestDataBase();
}

public class TestDataBaseInitializer : DropCreateDatabaseIfModelChanges<TestDataBase>
{
    protected override void Seed(TestDataBase context)
    {
        ProductCategory cat1 = new ProductCategory
                               {
                                   Name = "Food",
                                   Properties = new List<Property>(),
                                   Products = new List<Product>()
                               };
        Property prop1_1 = new Property
                           {
                               Name = "ForVegetarian"
                           };
        Property prop1_2 = new Property
                           {
                               Name = "Calories"
                           };
        cat1.Properties.Add(prop1_1);
        cat1.Properties.Add(prop1_2);
        Product product1_1 = new Product
                             {
                                 Name = "Pizza",
                                 Categories = new List<ProductCategory>(),
                                 Properties = new List<PropertyValue>()
                             };
        product1_1.Categories.Add(cat1);
        PropertyValue val1_1_1 = new PropertyValue 
                                 {
                                     Property = prop1_1,
                                     Value = "false"
                                 };
        PropertyValue val1_1_2 = new PropertyValue
                                 {
                                     Property = prop1_2,
                                     Value = "1500"
                                 };
        product1_1.Properties.Add(val1_1_1);
        product1_1.Properties.Add(val1_1_2);
        cat1.Products.Add(product1_1);
        Product product1_2 = new Product
        {
            Name = "Salad",
            Categories = new List<ProductCategory>(),
            Properties = new List<PropertyValue>()
        };
        product1_2.Categories.Add(cat1);
        PropertyValue val1_2_1 = new PropertyValue
        {
            Property = prop1_1,
            Value = "true"
        };
        PropertyValue val1_2_2 = new PropertyValue
        {
            Property = prop1_2,
            Value = "300"
        };
        product1_2.Properties.Add(val1_2_1);
        product1_2.Properties.Add(val1_2_2);
        cat1.Products.Add(product1_2);
        //--------------------------------------------------------------------------------
        ProductCategory cat2 = new ProductCategory
                               {
                                   Name = "Multimedia",
                                   Properties = new List<Property>(),
                                   Products = new List<Product>()
                               };
        Property prop2_1 = new Property
                           {
                               Name = "DisplaySize"
                           };
        Property prop2_2 = new Property
                           {
                               Name = "Warranty"
                           };
        cat2.Properties.Add(prop2_1);
        cat2.Properties.Add(prop2_2);
        Product product2_1 = new Product
                             {
                                 Name = "PlasmaTV",
                                 Categories = new List<ProductCategory>(),
                                 Properties = new List<PropertyValue>()
                             };
        product2_1.Categories.Add(cat2);
        PropertyValue val2_1_1 = new PropertyValue
                                 {
                                     Property = prop2_1,
                                     Value = "55''"
                                 };
        PropertyValue val2_1_2 = new PropertyValue
                                 {
                                     Property = prop2_2,
                                     Value = "36m"
                                 };
        product2_1.Properties.Add(val2_1_1);
        product2_1.Properties.Add(val2_1_2);
        cat2.Products.Add(product2_1);
        Product product2_2 = new Product
        {
            Name = "LCDMonitor",
            Categories = new List<ProductCategory>(),
            Properties = new List<PropertyValue>()
        };
        product2_2.Categories.Add(cat2);
        PropertyValue val2_2_1 = new PropertyValue
        {
            Property = prop2_1,
            Value = "24''"
        };
        PropertyValue val2_2_2 = new PropertyValue
        {
            Property = prop2_2,
            Value = "12m"
        };
        product2_2.Properties.Add(val2_2_1);
        product2_2.Properties.Add(val2_2_2);
        cat2.Products.Add(product2_2);
        context.Properties.Add(prop1_1);
        context.Properties.Add(prop1_2);
        context.Properties.Add(prop2_1);
        context.Properties.Add(prop2_2);
        context.Values.Add(val1_1_1);
        context.Values.Add(val1_1_2);
        context.Values.Add(val1_2_1);
        context.Values.Add(val1_2_2);
        context.Values.Add(val2_1_1);
        context.Values.Add(val2_1_2);
        context.Values.Add(val2_2_1);
        context.Values.Add(val2_2_2);
        context.Categories.Add(cat1);
        context.Categories.Add(cat2);
        context.SaveChanges();
    }
}

现在假设我属于 多媒体 类别:

        var category = (from c in TestDataBase.context.Categories
                        where c.Name == "Multimedia"
                        select c).First();

我知道这个类别有两个属性:DisplaySizeWarranty 假设我想选择 多媒体 类别中的所有产品(如 IEnumerable)(请注意,产品可能在多个类别中)。

        var categoryProducts = (from c in TestDataBase.context.Categories
                                where c.Name == "Multimedia"
                                select c.Products).First();

此外,我必须通过 DisplaySize 属性过滤这组产品。我想选择以下产品:

  • 具有 NOT NULL DisplaySize 属性
  • 显示尺寸 == 55''

这里有一个问题:我不知道如何在 LINQ to Entity 中指定选择此类产品,因为每个产品都有自己的 PropertyValue 对象集合 - 而不仅仅是一个 PropertyValue .

谁能帮帮我。提前谢谢!

【问题讨论】:

  • 我不明白你的问题?您的意思是 ORM 或对象序列化之类的东西?
  • 不,我的意思是数据库设计(ADO.NET、EF、Code-First)以轻松实现我所描述的功能。

标签: entity-framework database-design entity-framework-4.1 ef-code-first database-schema


【解决方案1】:

好的。我想我已经解决了我的问题。

    var categoryProducts = (from p in category.Products
                                from c in p.Properties
                                where c.Property.Name == "DisplaySize" &&
                                      c.Value == "55''"
                            select p).ToList();

这是关于这种选择的好文章: http://weblogs.asp.net/salimfayad/archive/2008/07/09/linq-to-entities-join-queries.aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-22
    相关资源
    最近更新 更多