简体   繁体   English

为什么这个linq表达式不起作用?

[英]Why is this linq expression not working?

I'm using LINQ to Entities. 我正在使用LINQ to Entities。

I have a table called Student; 我有一张叫做学生的桌子; it has ID and Name as it's columns. 它有ID和Name作为列。 ID is a primary key. ID是主键。

I'd like to be able select the name of the Student and get the amount of Students with the same Name. 我希望能够选择学生的姓名,并获得具有相同姓名的学生数量。

So for example I'd have this as my table data. 例如,我将此作为我的表格数据。

ID  Name  
1   Bob
2   Will
3   Bob

After performing the query I'd return a List of Student objects looking like this. 执行查询后,我将返回一个看起来像这样的Student对象列表。

Name    Quantity
Bob     2
Will    1

I guess it is kind of similar to how the Tags page of stackoverflow works; 我想这有点类似于stackoverflow的Tags页面的工作原理; It has the name and the quantity. 它有名称和数量。

Anyways, I created a partial class called Student.cs in which I added a Quantity property like this. 无论如何,我创建了一个名为Student.cs的分部类,其中我添加了一个Quantity属性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MySite.Models
{
    public partial class Student
    {
        private int _quantity;

        public int Quantity
        {
            get { return _quantity; }
            set { _quantity = value; }
        }
    }
}

I came up with this but I'm getting an error.. 我想出了这个,但我收到了一个错误..

    public IQueryable<Student> FindStudentsDistinctWithQuantity()
    {
        /*SELECT Name, COUNT(Name) AS Quantity
        FROM Student
        GROUP BY Name*/

        var students= (from s in db.Students
                    group s by s.Name into g
                    select new {Name = g.Key, Quantity = g.Count()});            

        return students;
    }

The error i'm getting says something like Can't convert from type Anonymous to the Student list. 我得到的错误说不能从匿名类型转换为学生列表。 Does it have something to do with it not recognizing the quantity field I added in the partial class? 它是否与它有关而没有识别我在分部类中添加的数量字段?

Thanks! 谢谢!

Change your Student type to look like this: 将您的Student类型更改为如下所示:

public partial class Student
{
    public Int32 Quantity { get; set; }
    public String Name { get; set; }
}

And your query to look like this: 你的查询看起来像这样:

var students = from s in db.Students
               group s by s.Name into g
               select new Student { 
                   Name = g.Key, 
                   Quantity = g.Count() };

Your method returns an IQueryable<Student> but you are currently returning an IQueryable<T> of a projected anonymous type. 您的方法返回IQueryable<Student>但您当前正在返回一个预计匿名类型的IQueryable<T>

You need to refactor your Student type to have a Name property of type String and then project new instances of your Student type from the expression so that the return type of your expression will match the return type of your method. 您需要重构您的Student类型以具有String类型的Name属性,然后从表达式中设置您的Student类型的新实例,以便表达式的返回类型与您的方法的返回类型匹配。

The problem is that you are not returning students - you are trying to return an anonymous type from your function. 问题是你没有回来的学生 - 你试图从你的函数返回一个匿名类型。 This is not allowed. 这是不允许的。

Create a class to represent your result and use new MyClass { ... } instead of new { ... } in your query, and change the method to return IQueryable<MyClass> instead of IQueryable<Student> . 创建一个类来表示结果,并在查询中使用new MyClass { ... }而不是new { ... } ,并将方法更改为返回IQueryable<MyClass>而不是IQueryable<Student>

You could for example make a class called StudentNameAndResults . 例如,您可以创建一个名为StudentNameAndResults的类。

class StudentNameAndResults
{
    public string Name { get; set; }
    public int Quantity { get; set; }
}

Alternatively, you could just return the result as a Dictionary or an IEnumarable of IGrouping. 或者,您可以将结果作为字典或IGrouping的IEnumarable返回。 For example: 例如:

public IDictionary<string, int> FindStudentsDistinctWithQuantity()
{
    Database db = new Database();
    var students= (from s in db.Students
                group s by s.Name into g
                select new {Name = g.Key, Quantity = g.Count()});

    return students.ToDictionary(s => s.Name, s => s.Quantity);
}

Also, the property you created is using the verbose syntax from pre-C# 3.0 days. 此外,您创建的属性使用前C#3.0天的详细语法。 Now you can use auto-implemented properties if you don't need any special logic: 现在,如果您不需要任何特殊逻辑,则可以使用自动实现的属性

public int Quantity { get; set; }

The select new keywords are causing the form of the data to change, which means the LINQ query will not return an IQueryable<Student>, but rather an anonymous type containing the "Name" and "Quantity" properties. select new关键字会导致数据的形式发生变化,这意味着LINQ查询不会返回IQueryable <Student>,而是返回包含“Name”和“Quantity”属性的匿名类型。 If you change it to return a concrete type rather than an anonymous one you will be able to retrieve the data in the form you want. 如果您更改它以返回具体类型而不是匿名类型,您将能够以所需的形式检索数据。

public class StudentGrouping {
    public string Name { get; set; }
    public int Quantity { get; set; }
}

public IQueryable<StudentGrouping> FindStudentsDistinctWithQuantity()
{
    /*SELECT Name, COUNT(Name) AS Quantity
    FROM Student
    GROUP BY Name*/

    var students= (from s in db.Students
                group s by s.Name into g
                select new StudentGrouping {
                   Name = g.Key, 
                   Quantity = g.Count()
                }).AsQueryable();            

    return students;
}

Your function returns Student 您的函数返回Student

public IQueryable<Student> FindStudentsDistinctWithQuantity(){ ... }

But your Linq query returns a new type that contains a Name and an Int (count) 但是你的Linq查询返回一个包含Name和Int(count)的新类型

               >>> select new {Name = g.Key, Quantity = g.Count()});            

y-try select new Student{Name = g.Key, Quantity = g.Count()} y-try选择新学生{Name = g.Key,Quantity = g.Count()}

The method's return value ties the " students " collection to IQueryable<Student> but... the Linq expression is creating an IQueryable<some anonymous type> , and there is no conversion between the two. 方法的返回值将“ students ”集合IQueryable<Student>IQueryable<Student>但是...... Linq表达式创建了一个IQueryable<some anonymous type> ,并且两者之间没有转换。

You may get a baby step further by modifying your select part to be: 通过修改您选择的部分,您可以进一步了解宝贝:

select new Student() {....}

Hopefully this helps, 希望这有帮助,

Tyler 泰勒

 var students= (from s in db.Students
                    group s by s.Name into g
                    select new {Name = g.Key, Quantity = g.Count()}); 

This is an anonymous type, not IQueryable<Student> . 这是一个匿名类型,而不是IQueryable<Student> Either you need to return System.Object , or you need to return IQueryable<Student> as follows... 您需要返回System.Object ,或者需要返回IQueryable<Student> ,如下所示...

return from s in db.Students
       group s by s.Name into g
      select new Student{Name = g.Key, Quantity = g.Count()};

Where Student defines the properties used in the initializtion. 学生定义初始化中使用的属性。

You are doing a projection in your linq query. 您正在linq查询中进行投影。 If you'd hover the cursor over var students inside vs you'll see its a collection of an anonymous type. 如果你将光标悬停在内部的var students上,你会看到它是一个匿名类型的集合。

If you want to return an IQueryabley<Student> you need to do: 如果您想要返回IQueryabley<Student>您需要执行以下操作:

 var students= from s in db.Students
                    group s by s.Name into g
                    select s.Key; 

There is no way outside methods can know about the anonymous type you have created in your previous example, so you won't be able to return a typed collection. 外部方法无法了解您在上一个示例中创建的匿名类型,因此您将无法返回类型化集合。

With the method I suggested you will still be able to do a projection on the return value of your method later on, since IQueryable is composable until the first enumeration: 使用我建议的方法,您仍然可以稍后对方法的返回值进行投影,因为IQueryable可以在第一次枚举之前进行组合:

var students = FindStudentsDistinctWithQuantity();
var namesAndQunatity = from s in students select new {s.Name, s.Quantity};

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

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