EntityFramework - 在不加载其他列的情况下将ID加载到级别

时间:2013-02-28 21:34:46

标签: c# linq entity-framework

我有3个实体:横幅,包和文件。

One Banner有很多包,一个包有很多文件。

我需要获取所有横幅的所有文件ID。我尝试了以下方法:

  IList<BannerModel> banners = context.Banners
    .OrderBy(x => Guid.NewGuid())
    .Take(count)       
    .Select(x => 
      new BannerModel {
        Images = x.Packs.SelectMany(p => p.Files.Select(f => f.Id)).ToList()
      }).ToList();

但是,我在文件ID选择时收到错误:

  

System.NotSupportedException:LINQ to Entities无法识别   方法'System.Collections.Generic.List 1[System.Int32] ToList[Int32](System.Collections.Generic.IEnumerable 1 [System.Int32])'   方法,并且此方法无法转换为商店表达式。   在   System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter   parent,MethodCallExpression call)at ...

有什么可能出错的想法吗?

注意:我禁用了延迟加载。

1 个答案:

答案 0 :(得分:1)

var allFileIDs = context.Banners.SelectMany(b => 
                           b.Packs.SelectMany(p => p.Files.Select(f => f.ID)))
                        .ToList();

生成的SQL将如下所示:

SELECT [t2].[ID]
FROM [Banners] AS [t0], [Packs] AS [t1], [Files] AS [t2]
WHERE ([t1].[BannerID] = [t0].[ID]) AND ([t2].[PackID] = [t1].[ID])

没有延迟加载,单个查询。


误解了有关获取所有文件ID的问题。如果您需要将每个横幅投影到BannerModel:

context.Banners.Select(b => new BannerModel {
          Images = b.Packs.SelectMany(p => p.Files.Select(f => f.ID))
        }).ToList();

您看到异常,因为表达式中有ToList(),无法转换为SQL。将BannerModel.Images更改为IEnumerable<int>类型而不是List<int>,并从select语句中删除ToList()调用。


如果您不想更改BannerModel.Images的类型,还可以选择其他选项:

context.Banners.Select(b => b.Packs.SelectMany(p => p.Files.Select(f => f.ID)))
               .ToList() // brings next projection into memory
               .Select(ids => new BannerModel { Images = ids.ToList() })
               .ToList();