Entity Framework Core compare two child collection properties

Viewed 62

I am using EF Core and stuck in a scenario where I need to fetch all the Parent table records that has child records matching the given child records. Example:

Parent Table

Id Name
1 P1
2 P2
3 P3

Child Table

Id ParentId Name Age Address
1 1 C1 20 abc
2 1 C2 25 xyz
3 2 C1 20 qqq
4 2 C2 25 wer
5 3 C3 30 tyu

I need Linq to get all parents which matches below search parameters.

All prents with Child records same as: Child: [ {C1,20}, {C2,25}]

So, it should return the Parent P1 and P2 as result. I am trying EqualityComparer but getting not translated error from EF. Any help is appreciated.

2 Answers

I don't think EF supports this. I didn't find a direct solution when I was in the same situation (multi-column primary key on the child table). My workaround was to add artificial (computed+stored) string column to the child table that combined all the PK parts, after that you should be able to do:

var childrenKeys = new List<string>();
/* .... fill it with children keys you are interested in ... */
var parents = dbContext.Parents
    .Where(x => x.Children.Any(xx => childrenKeys.Contains(xx.NameAndAge))
    .ToList();

Only other option I know of is to switch to client side evaluation and filter it yourself.

EDIT: I've changed my answer as your comment provided me information I didn't have. I believe you might be searching for this:

var childrenConditions = new List<Child>()
{
    new Child() 
    {
        Name = "C1",
        Age = 20
    },
    new Child() 
    {
        Name = "C2",
        Age = 25
    },
}

var children = context.Children.Include(child => child.Parent);
var groupedChildren = children.GroupBy(child => child.Parent.Id);
var rightParents = new List<Parent>();

foreach(var group in groupedChildren)
{
    var respectsConditions = true;
    foreach(var condition in childrenConditions)
    {
        if ((group.Select(child => 
            child.Name != condition.Name ||
            child.Age != condition.Age)).Any())
        {
            respectsConditions = false;
            break;
        }
    }
    
    if (respectsCondition) 
    {
        rightParents.Add(group.First().Parent);
    }
}

At the end of the algorithm, 'rightParents' will be a collection containing the parents you're searching for.

Related