отображение T из DbSet <T>во внутреннее представление Dabase с использованием EF - PullRequest
0 голосов
/ 03 апреля 2019

Я новичок в .NET и Entity Framework, просто вопрос по отображению. Допустим, у нас есть класс Recipes, у которого свойство Ingredient, поэтому у нас есть два класса Recipes и Ingredient.

и мывыполните отображение следующим образом:

public DbSet<Recipe> Recipes { get; set; }

, чтобы EF проверила свойства рецепта и создала таблицу рецептов, а в конечном итоге нашла ингредиент как свойство и создала таблицу ингредиентов.пока что это кажется простым, но это очень простая структура, поэтому мы знаем, что рецепты содержат Ingredient, поэтому мы делаем не просто

public DbSet<Recipe> Recipes { get; set; }
public DbSet<Ingredient> Ingredient { get; set; } //duplicated 

, а изображаем, что в сложном приложении мы могли быесть сотни классов, поэтому, когда мы делаем

public DbSet<T> T{ get; set; }
public DbSet<U> U{ get; set; }
public DbSet<V> V{ get; set; }
...

T может содержать U в качестве свойства, а U может содержать V в качестве свойства, поэтому нам просто нужно кодировать как:

public DbSet<T> T{ get; set; }

так что я запутался, мы должны включить все классы в DbContext?если мы сделаем это, будут дублированные объявления, но если мы этого не сделаем, мы можем потерять отображение.так что я думаю, что мы просто делаем tat для всех классов и ожидаем, что EF будет достаточно умным, чтобы игнорировать дублирующиеся вещи?

Ответы [ 3 ]

0 голосов
/ 03 апреля 2019

Вы должны знать, что ваш dbContext представляет вашу базу данных. DbSets представляют таблицы в базе данных

В каркасе сущностей столбцы таблиц представлены не виртуальными свойствами ваших классов. Виртуальные свойства представляют отношения между таблицами (один ко многим, многие ко многим, ...)

Ваша база данных будет иметь Recipes и Ingredient. Каждый Recipe будет иметь ноль или более Ingredients, в то время как каждый Ingredient используется в нуле или более Recipes: прямое отношение «многие ко многим».

У вас будут таблицы Recipes и Ingredients, поэтому ваш dbContext будет иметь DbSets для них:

class MyDbContext : DbContext
{
    public DbSet<Recipe> Recipes {get; set;}
    public DbSet<Ingredient> Ingredients {get; set;}
}

class Recipe
{
    public int Id {get; set;}  // primary key
    ...                        // other columns

    // every Recipe has zero or more ingredients (many-to-many)
    public virtual ICollection<Ingredient> Ingredients {get; set;}
}

class Ingredient
{
    public int Id {get; set;}  // primary key
    ...                        // other columns

    // every Ingredient is used in zero or more Recipes( many-to-many)
    public virtual ICollection<Recipe> Recipes {get; set;}
}

Поскольку я использовал virtual с обеих сторон, Рецепты и Ингредиенты, структура сущностей может обнаружить, что я разработал многие ко многим. Entity Framework даже создаст для меня соединительную таблицу, мне не нужно ее объявлять.

// Fetch all Desserts with their Bitter ingredients
var desertsWithoutSugar = myDbContext.Recipes
    .Where(recipe => recipy.Type == RecipyType.Dessert)
    .Select(recipe => new
    {
        // select only the properties that I plan to use:
        Id = recipe.Id,
        Name = recipe.Name,
        ...
        // not needed: you know the value: Type = recipe.Type

        Ingredients = recipe.Ingredients
           .Where(ingredient => ingredient.Taste == Taste.Bitter)
           .Select(ingredient => new
           {
               // again: only the properties you plan to use
               Id = ingredient.Id,
               Name = ingredient.Name,
           })
           .ToList(),
     })

Платформа сущностей знает о вашем отношении «многие ко многим» и достаточно умна, чтобы обнаружить, что (групповое) соединение необходимо с тремя таблицами, включая таблицу соединений.

Если вы хотите создать отношение один-ко-многим, например, Школу со своими учениками, вы объявляете virtual ICollection только с одной стороны. Другая сторона получает внешний ключ. Это столбец в вашей таблице, и, следовательно, не виртуальный

class School
{
    public int Id {get; set;}
    ...                     

    // every School has zero or more Students (one-to-many)
    public virtual ICollection<Student> Students {get; set;}
}
class Student
{
    public int Id {get; set;}
    ...   

    // Every Student studies at one School, using foreign key
    public int SchoolId {get; set;}
    public virtual School School {get; set;}
}
public SchoolContext : DbContext
{
    public DbSet<School> Schools {get; set;}
    public DbSet<Student> Students {get; set;}
}

По моему опыту, поскольку я использую Entity Framework, мне больше не нужно делать (Group-) соединение, я использую коллекции:

Дайте мне все школы со своими учениками

var Result = dbContext.Schools
    .Where(school => ...)
    .Select(school => new
    {
        Id = school.Id,
        ...

        Students = school.Students
            .Where(student => ...)
            .Select(student => new
            {
                 Id = student.Id,
                 ...
            })
            .ToList(),
    });

И аналогичные: дайте мне всех учеников школы, в которой они учатся

0 голосов
/ 03 апреля 2019

Как вы уже сказали, EF найдет тип Ingredient среди свойств Recipe и создаст таблицу Ingredients. Это означает, что таблица Ingredients будет создана, даже если вы пропустите public DbSet<Ingredient> Ingredient { get; set; }. Однако то, что вам не нужно public DbSet<Ingredient> Ingredient { get; set; }, не означает, что у вас его не должно быть. Вы можете свободно включать его, и это не принесет никакого вреда и не создаст дубликатов.

Добавление public DbSet<Ingredient> Ingredient { get; set; } к вашему DbContext позволяет получить доступ к Ingredient записям непосредственно из контекста:

MyContext context = ...
var ingredients = context.Ingredients;

В противном случае вам потребуется получить доступ к Ingredient записям через свойство Recipes:

MyContext context = ...
var recipe = context.Recipes...;
var ingredients = recipe.Ingredients;

Резюме: Когда следует включать класс в DbContext?

  • Когда на класс не ссылается ни один другой класс, который является частью DbContext. Добавление класса к DbContext обеспечит его сопоставление.

  • Когда вы хотите иметь доступ к записям этого класса непосредственно из экземпляра DbContext. Например. var ingredients = context.Ingredients.

  • Когда вы хотите убедиться, что класс будет отображен, и не хотите полагаться на него, на который ссылается какой-либо другой сопоставленный класс.

Итак, чтобы ответить на ваш вопрос «Должны ли мы включить все классы в DbContext?» : Можно, и это совершенно нормально подходит. Таким образом, вы будете уверены, что все классы (которые вы хотите отобразить) будут отображены, не полагаясь на них, на которые ссылается какой-либо другой класс.

0 голосов
/ 03 апреля 2019

EF достаточно умен, чтобы не создавать дублирующиеся таблицы, лучше всего включить все DbSet<>.

Если у вас есть класс с именем Ingredient и вы указываете на него ссылку в Recept, будет только одна таблица с именем Ingredient, и у вас не может быть двух таблиц с одинаковым именем, поэтому дублированные таблицы не будут быть созданным, даже если вы тоже хотели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...