Linq извлекает родительский объект

Я использую entityframework, и родительский объект MyObject уже существует в моем контексте (и загружены дочерние элементы).

    public class MyObject
    {
        public int id { get; set; }
        public string name { get; set; }
        public IEnumerable<Child> child { get; set; }
    }

    public class Child
    {
        public int id { get; set; }
        public string name { get; set; }
        public IEnumerable<Child2> child2 { get; set; }
    }

    public class Child2
    {
        public int id { get; set; }
        public string name { get; set; }
    }

Я хочу создать условие для свойства Child2 с сохранением экземпляра родительского объекта.

var myFiletredMyObject = myObject.child.Where(c => c.child2.Any(c2 => c2.id == 1)); Это возвращает мне коллекцию объектов Child, как я могу получить родителя: MyObject?

Отредактировано, извините за это

Hyrozzz 29.05.2019 12:48

Что ж, в соответствии с вашей структурой класса я не вижу способа добиться этого, поскольку Child понятия не имеет о своем родительском объекте. Но разве myObject уже не тот объект, который вам нужен?

MakePeaceGreatAgain 29.05.2019 12:49

@HimBromBeere На самом деле я хочу сделать это, чтобы в родительском объекте оставался только один дочерний элемент.

Hyrozzz 29.05.2019 12:52

Почему у вас есть два класса дочерних моделей?

Fakhar Ahmad Rasul 29.05.2019 12:54

Что ж, var object=myObject; Готово.

bolkay 29.05.2019 12:56

@FakharAhmadRasul Я не понимаю этого, потому что мне нужно 2 ребенка? Это 2 "*-n" отношения sql

Hyrozzz 29.05.2019 12:57

@bolkayВы должны перечитать вопрос или объяснить мне, как вы можете сделать условия, которые я хочу сделать

Hyrozzz 29.05.2019 13:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Учитывая, что EntityFramework вернет список моделей из базы данных, вы можете отфильтровать свой объект EF следующим образом.

var filterResult = myObject.Where(x => x.child.Any(a=>a.child2.Any(c2 => c2.id == 1))).ToList();

Результат фильтра будет иметь тип МойОбъект.

если ваш объект типа МойОбъект вы можете использовать тернарный оператор для применения критериев.

var filterResult = myObject.child.Where(a => a.child2.Any(c2 => c2.id == 1)).ToList().Count > 0 ? myObject : null;

Если вы рассматриваете myObject как IEnumerable (как DataSet для EF), это решение является хорошим. и может быть обходным путем, если я не найду другого решения. В моем случае myObject уже является типом MyObject (из предыдущего запроса)

Hyrozzz 29.05.2019 13:01

Он просто возвращает мой исходный объект (myObject) без применения условий

Hyrozzz 29.05.2019 13:35

если условие удовлетворяет, он вернет исходный объект. В противном случае он вернет ноль

Muhammad Nasir 29.05.2019 13:50
Ответ принят как подходящий

Если вы следовали Первые соглашения кода фреймворка сущностей, то вы должны были записать отношения между вашими таблицами как виртуальные свойства.

In entity framework, the columns of your tables are represented by non-virtual properties; the virtual properties represent the relations between your tables (one-to-many, many-to-many).

Более того: лучше описывать «один ко многим» как ICollection<...>, а не IEnumerable<...>. Это позволяет вам запросить количество дочерних элементов и добавить дочерний объект, что-то, что инфраструктура сущностей может легко преобразовать в SQL.

Итак, с небольшим изменением в вашем коде, изменения, которые дадут вам ту же базу данных (ну, я немного переименовал свойства, чтобы упростить в моем примере)

public class Parent
{
    public int id { get; set; }
    public string name { get; set; }

    // every Parent has zero or more Children (one-to-many)
    public virtual ICollection<Child> Children { get; set; }
}

public class Child
{
    public int id { get; set; }
    public string name { get; set; }

    // every Child is the child of exactly one Parent, using a foreign key
    public int ParentId {get; set;}
    public virtual Parent Parent {get; set;}

    // every Child has zero or more Child2 (one-to-many)
    public virtual ICollection<Child2> Children2 { get; set; }
}

public class Child2
{
    public int id { get; set; }
    public string name { get; set; }

    // every Child2 belongs to exactly one Child, using foreign key
    public int ChildId {get; set;}
    public virtual Child Child {get; set;}
}

И DbContext:

public class FamilyDbContext
{
    public DbSet<Parent> Parents {get; set;}
    public DbSet<Child> Children {get; set;}
    public DbSet<Child2> Children2 {get; set;}
}

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

Из-за нечетного множественного числа Child вы можете получить странное имя таблицы: Childs. Чтобы предотвратить это, вы можете использовать свободный API. Добавьте в свой DbContext:

public override void OnModelCreating(DbModelBuilder modelBuilder);
{
    // configure the one-to-many between Parent and Child using the foreign key:
    modelBuilder.Entity<Parent>()
        .HasMany(parent => parent.Children)
        .HasRequired(child => child.Parent)
        .HasForeignKey(child => child.ParentId);

    // configure the one-to-many between Child and Child2 using foreign key
    // make sure that the table gets a proper name
    modelBuilder.Entity<Child>().ToTable("Children")
         .HasMany(child => child.Children2)
         .HasRequired(child2 => child2.Child)
         .HasForeignKey(child2 => child2.ChildId);

    // the one-to-many relations are configured. Set the last table name
    modelBuilder.Entity<Child2>().ToTable("Children2");
}

Вернуться к вашему вопросу

Если вы настроили свои классы так, как предполагалась структура сущностей, ваш запрос будет простым:

var myFilteredChildrenWithTheirParents = dbContext.Children
    .Where(child => ...)
    .Select(child => new
    {
        // select only the Child properties you really plan to use:
        Id = child.Id,
        Name = child.Name,

        Parent = new
        {   // again: select only the Parent properties you plan to use:
            Id = parent.Id,
            Name = parent.Name,
        },

        // no need for the foreign key, you already selected the value in Parent
        // ParentId = child.ParentId,
});

Я создал EntityFramework на основе модели, поэтому это соглашение уже соблюдается. Я просто хотел поставить очень (слишком) простой кейс со своими 3 классами. Спасибо за ваш ответ, это то, что я искал, отлично!

Hyrozzz 29.05.2019 13:40

Другие вопросы по теме