别裁伪体亲风雅,转益多师是汝师。这篇文章主要讲述使用Automapper优化相关子查询相关的知识,希望能为你提供帮助。
更新:Automapper在简单的情况下自动应用它,因为它already adds a ToList()
。我看到的这个问题导致我打开这个问题变成了一个更复杂的问题(SoftwareIds member是N+1
的罪魁祸首。见this。)。
在EF Core 2.1中,我们获得了在LINQ子查询上添加ToList()
以缓冲结果并避免N + 1数据库查询的支持。 (Docs)这对于针对DbContext的简单LINQ查询非常有用。
但是,如果我有一个Automapper配置文件导致N + 1个查询:
public MyMappingProfile() =>
CreateMap<
MyEntity, MyDto>
().ForMember(e =>
e.MyCollectionProp, o =>
o.MapFrom(l =>
l.MyCollectionPropMany.Select(la =>
la.MyCollectionEntity)))
添加
ToList()
会抛出异常:public MyMappingProfile() =>
CreateMap<
MyEntity, MyDto>
().ForMember(e =>
e.MyCollectionProp, o =>
o.MapFrom(l =>
l.MyCollectionPropMany.Select(la =>
la.MyCollectionEntity).ToList()))
System.NotSupportedException:'无法解析表达式'MyDto.MyCollectionPropMany.Select(la => la.MyCollectionEntity).ToList()':当前不支持方法'System.Linq.Enumerable.ToList'的重载。有没有办法在Automapper配置文件中启用子查询缓冲?
楷模:
public class MyEntity
{
public int Id { get;
set;
}
public ICollection<
MyCollectionPropMany>
MyCollectionPropManys { get;
set;
}
...
}public class MyCollectionPropMany
{
public int MyEntityId { get;
set;
}
public MyEntity MyEntity { get;
set;
}
public int MyCollectionPropId { get;
set;
}
public MyCollectionProp MyCollectionProp { get;
set;
}
}public class MyCollectionProp
{
public int Id { get;
set;
}
public ICollection<
MyCollectionPropMany>
MyCollectionPropManys { get;
set;
}
...
}public class MyDto
{
public int Id { get;
set;
}
public IEnumerable<
MyCollectionPropDto>
MyCollectionPropDtos { get;
set;
}
...
}public class MyCollectionPropDto
{
public string Name { get;
set;
}
...
}
Automapper v7.0.1
真实场景(我试图简化/制作SO的通用):Source在这个真实的例子中,
Languages
和Tags
成员通过多对多正在生成N + 1个查询。答案事实证明,AutoMapper有时会在映射可枚举类型时自动将
ToList
/ ToArray
添加到投影表达式,有时则不会。规则似乎如下。如果目标可枚举类型可直接从源表达式类型分配,则AutoMapper直接使用源表达式。换句话说,如果以下赋值有效(伪代码):
dst.Member = src.Expression;
在这种情况下,您可以在映射表达式中包含或不包含
ToList
(因此选择加入EF Core相关查询优化)。在所有其他情况下,AutoMapper会根据需要执行可枚举的元素映射,然后添加
ToArray
或ToList
。没有办法选择退出。【使用Automapper优化相关子查询】很简单,如果目标可枚举元素类型为Dto(需要映射),则不要在源LINQ表达式中包含
ToList
,如果它是原始类型或实体类型,请包含ToList
以避免N + 1个查询。如果目标集合类型是IEnumerable<
T>
,则所有这些都适用。如果源表达式返回IReadOnlyCollection<
T>
,AutoMapper将自动处理任何其他派生类型,如IReadOnlyList<
T>
,ICollection<
T>
,IList<
T>
,List<
T>
,T[]
,IEnumerable<
TSource>
等。推荐阅读
- 如何解决 - 无法使用Automapper将Generic.List强制转换为Linq.IQueryable()
- 返回ApplicationUser对象或ApplicationUserId字符串的列表
- Spring @RequestMapping注释到不同的位置
- 使用Azure App Service Logging时是否需要blob StorageExceptions()
- 从密钥保险库将证书上载到App Service
- 禁用Azure App Services上的某些W3C日志记录字段
- 如何获取Azure App Service的特定用户分配的托管服务标识的令牌()
- 具有真实电话号码的Firebase PhoneAuth不工作但白名单号正在运行 - Android
- Firebase的新Firestore DB对电子商务Android应用程序来说更贵吗()