Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 如何编写需要子查询的Linq查询?_Entity Framework_Linq_Linq To Entities - Fatal编程技术网

Entity framework 如何编写需要子查询的Linq查询?

Entity framework 如何编写需要子查询的Linq查询?,entity-framework,linq,linq-to-entities,Entity Framework,Linq,Linq To Entities,我需要从数据库中提取一些关于支持票证的信息。每张票都与一个医疗成像系统相关联,每个系统可能有也可能没有与之相关的服务范围。如果有,可能会有多个服务范围条目,但只有一个是我们感兴趣的 我知道这是无效的Linq,但我真正想做的是以下 var tickets = cxt.SupportTickets .Select( t => new { ID = t.ID, Customer = t.Customer.Name, var cover = t.System.Cover

我需要从数据库中提取一些关于支持票证的信息。每张票都与一个医疗成像系统相关联,每个系统可能有也可能没有与之相关的服务范围。如果有,可能会有多个服务范围条目,但只有一个是我们感兴趣的

我知道这是无效的Linq,但我真正想做的是以下

var tickets = cxt.SupportTickets
  .Select( t => new {
    ID = t.ID,
    Customer = t.Customer.Name,
    var cover = t.System.CoverItems.FirstOrDefault(ci => // some query)
    CoverLevel = cover?.Level.Name,
    Expiry = cover?.Expiry.ToLongDateString()
  });
有没有办法做到这一点?我知道我可以重复
t.CoverItems.FirstOrDefault(…)
位来获取我想要从封面中获取的每一位数据,但是除了会产生非常糟糕的代码混乱之外,这将是非常低效的,因为它需要对每一张票证执行多次相同的子查询

我想把它分解成一个
foreach
循环,但是我不知道如何创建
tickets
集合。我不能创建一个空集合,然后向其中添加对象,因为它们是匿名类型,我不想考虑如何指定泛型类型


有人有什么想法吗?

您可以提高可读性:

var tickets = cxt.SupportTickets
  .Select(t => new { 
       Ticket = t, 
       CoverItem = t.System.CoverItems.FirstOrDefault(ci => // some query)
    })
  .Select(x => new {
    ID = x.Ticket.ID,
    Customer = x.Ticket.Customer.Name,
    CoverLevel = x.CoverItem?.Level.Name,
    Expiry = x.CoverItem?.Expiry.ToLongDateString()
  });

您可以使用查询符号来代替子句:

最后,我们将使用@TimSchmelter的答案,但对于类似的问题,您可以使用
let
。另一件事,我几乎可以肯定EF中不支持
ToLongDateString()
方法

我已经尝试过了(如果您想单独开发子查询,因为SoC原则):


为什么坚持使用linq查询?您可以创建存储过程并通过调用它EF@Kisame因为这将作为计划作业在LinqPad中运行,所以我需要一个独立的Linq查询。无论如何,把它作为存储过程的想法比我在最糟糕的噩梦中所能想象的任何Linq都要糟糕!无论这个查询在Linq中有多难,在SQLQ中都会有好几个数量级的难度。虽然这三个答案都很好,但我还是接受你的答案,因为这正是我在发布后提出的方法!我还认为它是最干净的语法,部分原因是我发现方法语法比fluent(个人观点)更容易阅读。谢谢你的建议,我已经忘记了
let
子句。我很少使用流利的语法(个人偏好),并且忘记了这是一个有显著好处的语法。但是,当我在LinqPad中尝试您的查询时,我得到一个错误
表达式树lambda可能不包含null传播运算符。
有什么想法吗?我没有在LinqPad中测试它,可能是正在使用的C版本。空条件运算符是因为C#6.0.LinqPad5(我正在使用)支持C#7,所以我认为不是这样。是的,我现在读到的可能是您正在使用的linq提供程序:谢谢链接,听起来就是这样
var query=from t in cxt.SupportTickets
          let cover = t.System.CoverItems.FirstOrDefault(ci => some query)
          select new {
                      ID = t.ID,
                      Customer = t.Customer.Name,
                      CoverLevel = cover?.Level.Name,
                      Expiry = cover?.Expiry//.ToLongDateString()
                     };
var innerQuery =  cxt.SupportTickets
                    .Where(artist => artist.coverId == SomeParameter)
                    .Select(artist => new {
                        artistId = artist.artistId,
                        artistCompleteName = artist.artistName,
                        artistMasterPiece = artist.CoverName
                    });

var tickets = cxt.SupportTickets
  .Where(
    t => innerQuery.Contains(t.coverId)
  )
  .Select( t => new {
    ID = t.ID,
    Customer = t.Customer.Name,
    var cover = t.System.CoverItems.FirstOrDefault()
    CoverLevel = cover?.Level.Name,
    Expiry = cover?.Expiry.ToLongDateString()
  });