简体   繁体   中英

Entity Framework LINQ equivalent of TSQL to include count of child records

Using Entity Framework and LINQ, how might I achieve this TSQL:

SELECT Children.ChildCount, Parent.*
FROM Parent
LEFT JOIN (SELECT ParentID, COUNT(ChildID) AS ChildCount FROM Child GROUP BY ParentID) AS Children 
ON Parent.ID = Children.ParentID

Note that this is just a small part of what is already a larger LINQ query that includes other related entities so using a RawSQL query is not an option. Also the Parent table has around 20 columns and I'm hoping not to have to specify each individually to keep the code maintainable.

EDIT : To clarify a couple of things, the model for the output of the query (very simplified) looks something like this:

public class MyEntity
{
    public int ID {get; set;}
    public string Name {get; set;}
    public int ChildCount {get; set;}
    // many other properties here including related records
}

So what I'm trying to do is get the ChildCount included in the result of the query so it is included in the EF entity.

You can use a Select Query to project the DB info onto an entity, something like:

var entity = db.Parent.Select(x => 
    new MyEntity
    {
        Id = x.Id,
        Name = x.Name,
        ChildCount = x.Children
            .Select(y => y.ParentId == x.Id)
            .Count()
    })
    .SingleOrDefault(x => x.Id == IDYouNeedToQuery);
}

What this should do is return you 1 instance of your MyEntity class with the Name, ID, and ChildCount properties filled in. Your SQL won't quite match what is generated but this should get you what you want. BTW you can also sub the SingleOrDefault line with a filter of another type, or no filter in which case the entity variable becomes a collection of MyEntity .

For further reading on this technique and how to use AutoMapper to make it super easy to set up, check out this post from Jon P Smith, who literally wrote the book on Entity Framework Core.

Hope this helps.

For anyone who comes across this at a later date, I ended up using AutoMapper as suggested by Nik P (I was already using AutoMapper anyway) to map from db entities to DTOs.

In effect, in my AutoMapper mapping I have:

     CreateMap<MyEntity, MyEntityDTO>()
           .ForMember(d => d.ChildCount, opt => opt.MapFrom(src => src.ChildEntity.Count()))

Then in my Service layer I call:

      IEnumerable<MyEntityDTO> results = await dbContext.MyEntities.ProjectTo<MyEntityDTO>(mapper.ConfigurationProvider).ToListAsync();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM