如何创建“动态”数据库结构(EF Code-First)

时间:2011-10-03 18:37:11

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

我正在尝试使用Entity Framework Code-First实现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 =“Calories”] ##     - Product1 =“Pizza”[“false”,“1500”]     - Product1 =“Salad”[“true”,“300”]

     

Category2 =“Multimedia”[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();

我知道此类别有两个属性: DisplaySize 保修 假设我想选择多媒体类别中的所有产品( IEnumerable )(请注意,产品可能位于多个类别中)。

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

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

  • 具有NOT NULL DisplaySize 属性
  • DisplaySize == 55''

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

有人能给我一个帮助。提前谢谢!

1 个答案:

答案 0 :(得分:0)

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

    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