#entity-framework #database-design #entity-framework-4.1 #ef-code-first #database-schema
#entity-framework #database-design #entity-framework-4.1 #ef-code-first #база данных-схема
Вопрос:
Я пытаюсь реализовать веб-приложение, используя сначала код Entity Framework. Я объясню проблему на таком примере:
В моей базе данных есть коллекция продуктов.
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. Я думал о создании одного строкового поля внутри класса типов и сохранении пар [ключ = значение], но это сделает практически невозможным быстрое и эффективное заполнение результатами подкачки.
Я буду благодарен за любое предложение или решение моей проблемы.
С наилучшими пожеланиями! Lukasz
Я создал такой пример кода, чтобы визуализировать проблему. Структура базы данных выглядит следующим образом:
Категория1 = «Еда» [Свойство1 = «Для вегетарианцев», Свойство2 = «Калории»] ## — Продукт1 = «Пицца» [«false», «1500»] — Продукт1 = «Салат» [«true», «300»]
Category2 = «Мультимедиа» [Свойство1 = «displaySize», Свойство2 = «Гарантия»] ## — 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 и Warranty
Допустим, я хотел бы выбрать все продукты (как 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. я не понимаю вашего вопроса? вы имеете в виду что-то вроде ORM или сериализации объектов?
2. Нет, я имею в виду дизайн базы данных (ADO.NET , EF, Code-First) для легкого достижения функциональности, которую я описал.
Ответ №1:
ОК. Я думаю, что я решил свою проблему.
var categoryProducts = (from p in category.Products
from c in p.Properties
where c.Property.Name == "DisplaySize" amp;amp;
c.Value == "55''"
select p).ToList();
Вот хорошая статья о таком выборе:
http://weblogs.asp.net/salimfayad/archive/2008/07/09/linq-to-entities-join-queries.aspx