【问题标题】:Cannot be inferred from the usage. Try specifying the type arguments explicitly无法从用法推断。尝试明确指定类型参数
【发布时间】:2018-08-27 10:15:12
【问题描述】:

我想在性能方面进行投影,但选择部分返回匿名类型,我无法进行所需的映射。

 var jobDegreesQuery = _context.JOBDEGREEs.AsQueryable().Select(d=> new {d.DEGREE_CODE,d.DEGREE_NAME });

            if (!String.IsNullOrWhiteSpace(name))
                jobDegreesQuery = jobDegreesQuery.Where(c => c.DEGREE_NAME.Contains(name));

            var jobDegreeDTOs = jobDegreesQuery
               .ToList()
               .Select(Mapper.Map<JOBDEGREE, JobDegreeDTO>); //The error

方法 'Enumerable.Select(IEnumerable, Func)' 的类型参数不能 从用法推断。尝试明确指定类型参数。

如何投影和映射到DTO 成功?

【问题讨论】:

标签: c# linq entity-framework-6 automapper anonymous-types


【解决方案1】:

据我了解,您希望将 JOBDEGREE 映射到 JobDegreeDTO。您首先将其选择为匿名类型,因此我认为 AutoMapper 无法映射,因为您正在提供匿名。输入。

如下修改你的代码会更好:

IQueryable<JOBDEGREEs> jobDegreesQuery = _context.JOBDEGREEs; // it is already queryable

if (!String.IsNullOrWhiteSpace(name))
    jobDegreesQuery = jobDegreesQuery.Where(c => c.DEGREE_NAME.Contains(name));

var jobDegreeDTOs = jobDegreesQuery
   //.Select(d=> new {d.DEGREE_CODE,d.DEGREE_NAME }) // do you need this?
   .Select(d => Mapper.Map<JOBDEGREE, JobDegreeDTO>(d)); // here you can give any expression
   .ToList()

【讨论】:

  • 我得到与匿名类型相关的相同编译错误。
  • 据我了解,您希望将 JOBDEGREE 映射到 JobDegreeDTO。您首先将其选择为匿名类型,因此我认为 AutoMapper 无法映射,因为您正在提供匿名。类型。什么看起来像你的 dto?您要选择哪些字段?我修改了答案,你可以再试一次吗?
  • 你的意思是如果我的DTO 只包含(DEGREE_CODE,DEGREE_NAME) 那么最后一次更改做了所需的投影。
  • 是的,在上面的代码中,您可以手动选择它作为 dto 或通过第二个 select 语句映射它。这能解决你的问题吗?
【解决方案2】:

ToList() 的结果是什么?它是某个匿名类的对象列表,其中包含从您的JobDegrees 序列中提取的数据

每当您想在一系列对象上使用Enumerable.Select 时,您首先必须命名一个表示您的序列中一个元素的标识符。此标识符是=&gt; 之前的部分。在=&gt; 之后,您将编写代码以使用此输入标识符返回一个对象。

这是一种很难说的话:

IEnumerable<Person> myPersons = ...
var firstNames = myPersns.Select(person => person.FirstName);

这里=&gt; 之前的person 代表您的Persons 集合中的一项。因此person 似乎是这个标识符的正确名称。

如果您愿意,可以使用任何标识符来标识person,尽管并非所有标识符都会提高可读性:

var firstNames = myPersns.Select(x => x.FirstName);

使用 LINQ 和实体框架时,最好用复数名词来识别集合,用单数名词来识别集合的元素。

=&gt; 之后编写一些代码,使用此输入person 来准确返回一个对象。在此示例中,FirstNameperson

回到你的问题

ToList 的结果是一个带有DegreeCodeDegreeName 的对象序列。

如果要将序列中的每个对象都转换为另一个对象(这称为投影),则必须在 '=>' 之前标识序列中的一个对象。

例如

...ToList()
.Select(extractedDegreeData => ...)

这里,每个extractedDegreeData 对应于列表中的一个元素。

现在你想用这样的extractedDegreeData 做什么?你要返回Mapper.Map&lt;JOBDEGREE, JobDegreeDTO&gt;(extractedDegreeData)的返回值。

因此你的代码应该是这样的:

...ToList()
.Select(extractedDegreeData => Mapper.Map<JOBDEGREE, JobDegreeDTO>(extractedDegreeData));

建议:

在构建 LINQ 查询时,不要使用像 ToList 这样的函数,或任何其他不返回 IEnumerable&lt;TResult&gt; 的函数,这会浪费处理能力。如果在你的Select 之后你会放Take(2) 怎么办?如果您只想要前两个元素,那么创建 1000 个元素的完整列表真是太浪费了!

因此,ToListFirstOrDefaultMaxCount 等函数应该始终是 linq 查询中的最后一个。

最后:dbContext.JobDegrees 是一个DbSet&lt;JobDegree&gt;,它实现了IQueryable&lt;JobDegree&gt;,因此不需要使用AsQueryable

【讨论】:

  • 非常感谢您的解释,但我收到以下错误:Argument 1: cannot convert from '&lt;anonymous type: int DEGREE_CODE, string DEGREE_NAME&gt;' to 'DomainClasses.JOBDEGREE'
  • 我不知道你的mapper.map函数。检查它期望的输入并提供正确的输入
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多