简体   繁体   English

'int'不包含'ToList'的定义

[英]'int' does not contain a definition for 'ToList'

So I'm trying to run a Linq query that's analogous to the SQL query: 因此,我尝试运行类似于SQL查询的Linq查询:

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

To get a count of the number of rows (tasks) within the given ww range that are marked as done under a particular manager and grouped by ww. 获取给定ww范围内被标记为在特定管理器下完成并按ww分组的行(任务)数的计数。 I've tried to create a LINQ query that would return something similar (wwStartSelected && wwEndSelected are global vars): 我试图创建一个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;
    }
}

This query would then feed into a chart: 然后,此查询将馈入图表:

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

However I'm running into an issue with my Linq line and it says: 但是我的Linq生产线遇到问题,它说:

'int' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) 'int'不包含'ToList'的定义,并且找不到扩展方法'ToList'接受类型为'int'的第一个参数(是否缺少using指令或程序集引用?)

Is there way to get fix this easily or do I have to convert to string, then convert back to int for the chart series (the latter of which seems a bit silly [but if so, best way to do so])? 是否有办法轻松地解决此问题,还是我必须转换为字符串,然后再转换回图表系列的int(后者似乎有点愚蠢[但如果是,那是最好的方法])?

.Count().ToList()

You're asking it to count the items in the list (which results in a number) and then convert that single number into a list, which makes no sense. 您要让它计算列表中的项目(产生一个数字),然后将该单个数字转换为列表,这没有任何意义。

Either return a list and count it later (omit the .Count() ) or, change the method to return an int not a List<int> and omit the .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;
    }
}

As an aside, to save you writing hundreds of these methods, you can pass the Where clause in as a parameter... Where一句,为了节省编写数百种此类方法的费用,您可以将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;
    }
}

Then call it like this... 然后这样称呼...

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

Edit Re: Comments 编辑回复:评论

To return a count of each group, List<int> is a bad idea as you aren't ordering the groups so the counts will be in an undefined order. 要返回每个组的计数, List<int>是个坏主意,因为您没有对组进行排序,因此计数将处于不确定的顺序。 The ideal solution is to have a class that has an appropriate Key and Count property, but to simplify the example, I'll use a Tuple. 理想的解决方案是拥有一个具有适当的KeyCount属性的类,但是为了简化示例,我将使用元组。

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

Note that after you've done the group, the next Select is against the group, which has a Key property for the thing you've grouped on and a lot of aggregate methods for counting, summing, etc.. 请注意,在完成分组之后,下一个Select与该分组相对。该分组具有用于分组的对象的Key属性以及许多用于计数,求和等的汇总方法。

If you really just want a list of ints, change the last Select to be... 如果您确实只需要一个整数列表,请将最后一个“选择”更改为...

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

If you weren't passing it out of the method, I'd just use an anonymous class... 如果您没有将其从方法中传递出去,我将只使用一个匿名类...

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

But that's no use in a method signature. 但这在方法签名中没有用。 If you created a CountResult class with Ww and Count properties... 如果您创建了具有WwCount属性的CountResult类...

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

Edit Re: Comments #2 编辑回复:评论#2

Linq-To-Entities builds an expression tree which is executed against SQL server, whereas Linq-To-Objects runs in-memory on the client and has more features (as it doesn't need to work out equivalent SQL). Linq-To-Entities构建一个表达式树,该树可针对SQL Server执行,而Linq-To-Objects在客户端的内存中运行并具有更多功能(因为它不需要计算出等效的SQL)。 In this case, when it gets results from SQL it creates a special proxy class that looks/behaves the same as your entities but handle additional things like tracking which properties have changed. 在这种情况下,当它从SQL获取结果时,它会创建一个特殊的代理类,该类看起来/行为与您的实体相同,但是会处理其他事情,例如跟踪哪些属性已更改。 Because of this, you can only use classes which can be constructed (with a parameterless constructor) and then have their properties set (and tracked). 因此,您只能使用可以构造的类(使用无参数构造函数), 然后设置(并跟踪)它们的属性。

(Although you didn't specify Linq-To-Entities, it's obvious from your question so I should've caught this). (尽管您未指定Linq-To-Entities,但从您的问题中可以明显看出,所以我应该抓住了这一点)。

LINQ doesn't deal in lists, but IQueryable s, which support lazy evaluation. LINQ不处理列表,但支持延迟搜索的IQueryable

Eg If you do... 例如,如果您这样做...

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

The query is only executed on the last line and at most 100 records will be returned by the database. 该查询仅在最后一行执行,并且数据库最多返回100条记录。 a and b are both IQueryable<SomeSet> and "just" contain the expression tree (basically a hierarchy representing the constrains/operations applied so far). ab都是IQueryable<SomeSet> ,“ just”包含表达式树(基本上是表示到目前为止已应用的约束/操作的层次结构)。

So, to be able to use parameterised constructors / other Linq-To-Object features, we can force the evaluation ... 因此,为了能够使用参数化的构造函数/其他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(); 

Which should allow you to use constructors, should you wish. 如果愿意,应该允许您使用构造函数。

That said, getting a zero count is difficult - the same as it would be getting it from a database (if you group by a field, it doesn't show any 0 counts). 也就是说,很难获得零计数-就像从数据库中获得零计数一样(如果按字段分组,则不会显示任何0计数)。 There are a number of ways to approach this and which one you use depends on how much data you're playing with. 有多种方法可以解决此问题,您使用哪种方法取决于您正在处理的数据量。 All of them require some way of defining all possible values. 所有这些都需要某种定义所有可能值的方式。 I'll use a List<string> as it works well with LINQ 我将使用List<string>因为它可以很好地与LINQ一起使用

You could, for example get a list of all values and run a different count for each. 例如,您可以获取所有值的列表,并对每个值运行不同的计数。 This is easy but requires multiple queries. 这很容易,但是需要多个查询。 If there are lots of groups, it might be expensive... 如果有很多团体,那可能会很昂贵。

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

(This will only return counts, but in the same order as your groups list. As before, you can Select anything you like, including a CountResult...) (这将只返回计数,但顺序与组列表相同。像以前一样,您可以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();
    });

Alternatively, you can run the query you were doing previously and add the missing groups with a count of 0 . 或者,您可以运行以前执行的查询,并添加计数为0的缺失组。 This has the benefit of running a single SQL query and letting the database do all the heavy lifting (Ok, handling a few counts isn't too expensive but it's worth bearing in mind for other problems - you don't want to get the whole DB table in memory and do the processing there!). 这样的好处是运行单个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})
                );

In short, take the previous results set, and concatenate (join) it with the result of; 简而言之,取先前的结果集,并将其与(结果)连接(连接); (take a list of all groups, remove those already in set 1, for the remainder create a new object with the appropriate ww and a count of 0 ) (获取所有组的列表,删除组1中已经存在的组,其余的创建一个具有适当ww且计数为0的新对象)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM