【问题标题】:Get nested data and sharp into DTO with nested DTO使用嵌套 DTO 获取嵌套数据并锐化到 DTO
【发布时间】:2019-04-02 06:50:48
【问题描述】:

总的来说,我是 EF、Linq 和 C# 的新手,我一直坚持开发以下内容。 我无法将数据映射到这样的结构中:

Id,
Actions [
  Action1,
  Action2,
  Action3
]

我有 2 个这样的 DTO 类:

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

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

我已经将对 DB 的调用分离到名为 BusinessLogic 的文件中,我这样做是这样的:

    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;
    }

我收到以下错误:

LINQ to Entities 无法识别方法 'Project.Core.Models.TestDTO2[] ToArrayTestDTO2' 方法,并且该方法无法转换为存储表达式。

【问题讨论】:

    标签: entity-framework linq dto


    【解决方案1】:

    你不能完全执行这个查询,最好做两个简单的查询,然后在客户端处理它们的结果:

    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();
    

    【讨论】:

    • 谢谢,这完全符合我的需要。例如,如果我没有匹配的动作,我无论如何都有空的 TestDTO2 数组。有没有可能省略?还有如何用更多属性填充 main 。谢谢。
    • 如果我在这里添加新属性: var main = db.Table1.Select(x => new { x.Id, x.Title }).ToList();然后我在线收到错误消息: var actions = db.Table2.Where(x => main.Contains(x.TestId))... main.Contains 与将 int 转换为匿名类型有冲突。
    【解决方案2】:

    是的,您不能使用任何不能在 EF 中翻译 sql 的 c# 方法。 实际上,您需要获取一个列表,然后将其转换为您的 DTO

     db.Table1
       .Join(db.Table2,
       a => a.Id,
       b => b.TestId,
       (a, b) => new
       {
          a.Id,
          b
       })
       .GroupBy(k => k.Id, v => v).ToList()
       .Select(a=>new TestDTO
           {
             TestId = a.Id,
             Actions = a.Select(b=>
             new TestDTO2
               {
                  TestActionId = b.TestActionId,
                  StartDate = b.StartDate
               }.ToArray()
             }).ToList()
    

    【讨论】:

    • 您好:TestId = a.Id,我收到错误,a 没有公开任何属性。
    猜你喜欢
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    相关资源
    最近更新 更多