如何创造“动态”的氛围数据库结构(EF Code-First)

发布于 2024-12-08 00:25:10 字数 9076 浏览 0 评论 0原文

我正在尝试使用实体框架代码优先来实现 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] 对,但这几乎不可能使用分页结果创建快速高效的填充。

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

此致! Lukasz


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

类别 1 =“食物”[属性 1 =“素食”,属性 2 =“卡路里”] ## - Product1 =“披萨”[“假”,“1500”] - Product1 =“沙拉”[“true”,“300”]

类别2 =“多媒体”[属性1 =“显示尺寸”,属性2 =“保修”] ## - 产品1 =“等离子电视”[“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。

任何人都可以给我帮助。先感谢您!

I'm trying to implement web application using Entity Framework Code-First.
I'll explain the problem on such example:

In my database there is a collection of products.

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

Each product has it's own type (food, drugs, multimedia, etc.). Also in my database'll be a collection of this types and it will be defined by the end-user and might be modified/increased in the future.

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

As you know, each product has it's own properties depends on the product's type. Lets say drugs may have

public bool PrescriptionOnly { get; set; }

and multimedia type may has

public Size DisplaySize { get; set; }

As I mentioned before types'll be defined by the end-user so count of properties and data type of each property is undefined right now. Moreover, user should be able to filter products by the specific values of properties (filtering model depends on the product type). And this all should be implemented using Code-First model.

To sum up I've got stuck because I don't know how to create such "dynamic" database structure with EF Code-First. I though about creating one string field inside Type class and save [key=value] pairs but this will make almost impossible to create fast and efficient filltering with paging results.

I'll be gratefull for any suggestion or solution to my problem.

Best regards!
Lukasz


I've created such sample code to visualise the problem. The database structure looks like this:

Category1 = "Food" [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();
    }
}

Now lets say I'm inside Multimedia category:

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

I know that this category has two properties: DisplaySize and Warranty
Lets say I would like to select all products (as IEnumerable) which are in Multimedia category (note that products may be inside more than one category).

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

Moreover, I must filter this set of products by the DisplaySize property. I would like to select those products which:

  • has NOT NULL DisplaySize property
  • DisplaySize == 55''

And here goes a problem: I don't know how to specify in LINQ to Entity to select such products because each product has its own collection of PropertyValue objects - NOT just one PropertyValue.

Could anyone give me a help. Thank you in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

脱离于你 2024-12-15 00:25:10

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

    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

OK. I think I've solved my problem.

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

Here is the good article about such selection:
http://weblogs.asp.net/salimfayad/archive/2008/07/09/linq-to-entities-join-queries.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文