EntityFramework-将ID加载到较低级别,而不加载其他列

本文关键字:加载 其他 较低级 ID EntityFramework- | 更新日期: 2023-09-27 18:01:50

我有三个实体:横幅、包和文件。

一个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选择上遇到了一个错误:

系统。NotSupportedException:LINQ to Entities不识别方法"系统"。集合。通用的列出1[System.Int32] ToList[Int32](System.Collections.Generic.IEnumerable 1[System.Int32]('方法,而此方法无法转换为存储表达式。在系统数据对象。ELinq。ExpressionConverter。MethodCallTranslator。默认转换器。翻译(ExpressionConverterparent,MethodCallExpression调用(。。。

你知道可能出了什么问题吗?

注意:我禁用了懒惰加载。

EntityFramework-将ID加载到较低级别,而不加载其他列

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