'int' does not contain a definition for 'ToList&

本文关键字:definition ToList for not int does contain | 更新日期: 2023-09-27 18:17:04

所以我试图运行一个类似于SQL查询的Linq查询:

SELECT COUNT(*) 
FROM table 
WHERE ww >= [wwStartSelected] 
    AND ww <= [wwEndSelected] 
    AND manager='[managerName]' 
    AND status='Done'
GROUP BY ww; 

获取给定ww范围内标记为在特定管理器下完成并按ww分组的行(任务(数。我试图创建一个LINQ查询,它将返回类似的内容(wwStartSelected和wwEndSelected是全局变量(:

protected List<int> getManagerDoneCount(string managerName)
{
    using (var context = new InfoDBContext())
    {
        List<int> managerDoneCount = context.InfoSet.Where(x => x.ww >= wwStartSelected && x.ww <= wwEndSelected && x.manager == managerName && x.status == "Done").GroupBy(x => x.ww).Count().ToList();
        return managerDoneCount;
    }
}

然后,这个查询将进入一个图表:

var testChart = new Chart(width: 600, height: 400)
    .AddTitle("Test")
    .AddSeries(
        name: "Done",
        chartType: "StackedColumn100",
        xValue: new[] { WWList },
        yValues: new[] { getManagerDoneCount("someManager") })

然而,我的Linq线路遇到了问题,上面写着:

"int"不包含"ToList"的定义,也不包含扩展方法"ToList"可以找到接受"int"类型的第一个参数(您是缺少using指令或程序集引用?(

有没有办法轻松解决这个问题,或者我必须转换为字符串,然后再转换回图表系列的int(后者似乎有点傻[但如果有,最好的方法是这样做](?

'int' does not contain a definition for 'ToList&

.Count().ToList()

你要求它计算列表中的项目(这会产生一个数字(,然后将单个数字转换为列表,这毫无意义。

返回一个列表并稍后计数(省略.Count()(,或者更改方法以返回int而不是List<int>并省略.ToList()

protected int getManagerDoneCount(string managerName)
{
    using (var context = new InfoDBContext())
    {
        int managerDoneCount = context.InfoSet
                .Where(x => x.ww >= wwStartSelected &&
                            x.ww <= wwEndSelected && 
                            x.manager == managerName &&
                            x.status == "Done")
                .GroupBy(x => x.ww)
                .Count();
        return managerDoneCount;
    }
}

顺便说一句,为了避免编写数百个这样的方法,可以将Where子句作为参数传入。。。

using System.Linq.Expressions;
protected int getManagerCount(string managerName, Expression<Info> predicate)
{
    using (var context = new InfoDBContext())
    {
        int managerDoneCount = context.InfoSet
                .Where(predicate)
                .GroupBy(x => x.ww)
                .Count();
        return managerDoneCount;
    }
}

那就这样说吧。。。

var count = getManagerCount("...", x => x.ww >= wwStartSelected &&
                                        x.ww <= wwEndSelected && 
                                        x.manager == managerName &&
                                        x.status == "Done");

编辑回复:注释

要返回每个组的计数,List<int>是个坏主意,因为您没有对组进行排序,所以计数将按未定义的顺序排列。理想的解决方案是拥有一个具有适当KeyCount属性的类,但为了简化示例,我将使用Tuple。

//I'm assuming `ww` is an `int`, change the first type parameter of the tuple as appropriate
List<Tuple<int, int>> counts = context.InfoSet
                .Where(x => x.ww >= wwStartSelected &&
                            x.ww <= wwEndSelected && 
                            x.manager == managerName &&
                            x.status == "Done")
                .GroupBy(x => x.ww)
                .Select(x => new Tuple<int, int>(x.Key, x.Count())).ToList(); 

请注意,在完成分组后,下一个Select是针对该组的,该组具有用于分组的事物的Key属性,以及用于计数、求和等的许多聚合方法。

如果您真的只想要一个int列表,请将最后一个Select更改为…

.Select(x => x.Count())

如果你不把它从方法中传递出去,我只会使用一个匿名类。。。

.Select(x => new {Ww = x.Key, Count = x.Count()})

但这在方法签名中没有用。如果创建了具有WwCount属性的CountResult类。。。

.Select(x => new CountResult{Ww = x.Key, Count = x.Count()})

编辑回复:评论#2

Linq To Entities构建了一个针对SQL server执行的表达式树,而Linq To Objects在客户端的内存中运行,并具有更多功能(因为它不需要计算出等效的SQL(。在这种情况下,当它从SQL中获得结果时,它会创建一个特殊的代理类,该类的外观/行为与实体相同,但会处理其他事情,如跟踪哪些属性发生了更改。因此,您只能使用可以构造(使用无参数构造函数(的类,然后设置(并跟踪(它们的属性。

(虽然您没有指定Linq-To实体,但从您的问题中可以明显看出,所以我应该了解到这一点(。

LINQ不处理列表,而是处理IQueryables,后者支持惰性评估。

如果你这样做…

var a = dbcontext.SomeSet.Where(x => true); //You could omit the Where entirely, just for illustration purposes
var b = a.Where(x => x.Id < 100);
var c = b.ToList();

查询只在最后一行执行,数据库最多返回100条记录。ab都是IQueryable<SomeSet>,并且"只是"包含表达式树(基本上是表示迄今为止应用的约束/操作的层次结构(。

因此,为了能够使用参数化构造函数/其他Linq to Object功能,我们可以强制进行评估。。。

List<Tuple<int, int>> counts = context.InfoSet
                .Where(x => x.ww >= wwStartSelected &&
                            x.ww <= wwEndSelected && 
                            x.manager == managerName &&
                            x.status == "Done")
                .GroupBy(x => x.ww)
                .ToList() // <<<< Force execution of SQL query
                .Select(x => new Tuple<int, int>(x.Key, x.Count())).ToList(); 

如果你愿意的话,它应该允许你使用构造函数。

也就是说,获取零计数是困难的——就像从数据库中获取一样(如果按字段分组,它不会显示任何0计数(。有很多方法可以做到这一点,你使用哪一种取决于你使用的数据量。所有这些都需要某种方式来定义所有可能的值。我将使用List<string>,因为它与LINQ 配合良好

例如,您可以获取所有值的列表,并对每个值运行不同的计数。这很简单,但需要多个查询。如果有很多团体,可能会很贵。。。

var groups = new List<string> {"ww1", "ww2", ...};
var counts = groups.Select(g => context.InfoSet.Where(x => x.ww == g && 
                                          x.manager == managerName &&
                                          x.status == "Done").Count());

(这只会返回计数,但与您的组列表的顺序相同。和以前一样,您可以随心所欲地Select,包括CountResult…(

var counts = groups.Select(g => new CountResult { 
        Ww = g,
        Count = context.InfoSet.Where(x => x.ww == g && 
                                          x.manager == managerName &&
                                          x.status == "Done").Count();
    });

或者,您可以运行以前执行的查询,并添加计数为0的丢失组。这样做的好处是运行一个SQL查询,让数据库完成所有繁重的工作(好吧,处理一些计数并不太贵,但对于其他问题,值得记住——你不想在内存中获得整个DB表并在那里进行处理!(。

var groups = new List<string> {"ww1", "ww2", ...};
var previousQuery = ... //(I'll assume a List<CountResult> but tuple would work the same)
var finalList = previousQuery.Concat(
                    groups.Where(g => ! previousQuery.Exists(p => p.Ww == g))
                          .Select(g => new CountResult {Ww=g, Count=0})
                );

简而言之,取前面的结果集,并将其与的结果连接(联接(;(获取所有组的列表,删除集合1中已经存在的组,对于其余组,创建一个具有适当ww0计数的新对象(