Search code examples
entity-frameworklinqdto

Get nested data and sharp into DTO with nested DTO


I'm newbie to EF, Linq and C# in general, I'm stuck with developing following. I cannot map data into structure like this:

Id,
Actions [
  Action1,
  Action2,
  Action3
]

I have 2 DTO classes like this:

public class TestDTO
{
    public int TestId { get; set; }
    public TestDTO2[] Actions { get; set; }
}

and

public class TestDTO2
{
    public int TestActionId { get; set; }
    public DateTime? StartDate { get; set; }
    ...
}

I've separated calls to DB into file called BusinessLogic, I'm doing it like this:

    public IQueryable<TestDTO> GetNested(Filter filter)
    {
        var query =
                    from a in db.Table1.AsQueryable()
                    select new TestDTO
                    {
                        TestId = a.Id,
                        Actions = (
                            from b in db.Table2.AsQueryable()
                            where a.Id == b.TestId 
                            select new TestDTO2
                            {
                                TestActionId = b.TestActionId,
                                StartDate = b.StartDate
                            }
                        ).ToArray()
                    };
        return query;
    }

I'm getting following error:

LINQ to Entities does not recognize the method 'Project.Core.Models.TestDTO2[] ToArrayTestDTO2' method, and this method cannot be translated into a store expression.


Solution

  • You can't perform exactly this query, it is better to make two simple queries and then process their results on client side:

    var main = db.Table1.Select(x => new { x.Id, x.Title }).ToList();
    var mainIds = main.Select(x => x.Id).ToList();
    var actions = db.Table2.Where(x => mainIds.Contains(x.TestId)).Select(x => new 
    { 
        x.TestId,
        x.TestActionId, 
        x.StartDate
    }).ToList();
    
    var result = main.Select(x => {
        var actions = actions.Where(y => y.TestId == x.Id).Select(y => new TestDTO2
                      {
                          TestActionId = y.TestActionId,
                          StartDate = y.StartDate
                      }).ToArray();
        return new TestDTO 
        { 
            TestId = x.Id, 
            Title = x.Title, 
            Actions = actions.Length == 0 ? null : actions
        };
    }).ToList();