Я использую 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
?
Что ж, в соответствии с вашей структурой класса я не вижу способа добиться этого, поскольку Child
понятия не имеет о своем родительском объекте. Но разве myObject
уже не тот объект, который вам нужен?
@HimBromBeere На самом деле я хочу сделать это, чтобы в родительском объекте оставался только один дочерний элемент.
Почему у вас есть два класса дочерних моделей?
Что ж, var object=myObject;
Готово.
@FakharAhmadRasul Я не понимаю этого, потому что мне нужно 2 ребенка? Это 2 "*-n" отношения sql
@bolkayВы должны перечитать вопрос или объяснить мне, как вы можете сделать условия, которые я хочу сделать
Учитывая, что 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 (из предыдущего запроса)
Он просто возвращает мой исходный объект (myObject) без применения условий
если условие удовлетворяет, он вернет исходный объект. В противном случае он вернет ноль
Если вы следовали Первые соглашения кода фреймворка сущностей, то вы должны были записать отношения между вашими таблицами как виртуальные свойства.
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 классами. Спасибо за ваш ответ, это то, что я искал, отлично!
Отредактировано, извините за это