我正在使用LINQ to Entities。
我有一张叫做学生的桌子;它有ID和Name作为列。 ID是主键。
我希望能够选择学生的姓名,并获得具有相同姓名的学生数量。
例如,我将此作为我的表数据。
ID Name
1 Bob
2 Will
3 Bob
执行查询后,我将返回一个看起来像这样的学生对象列表。
Name Quantity
Bob 2
Will 1
我猜它有点类似于stackoverflow的Tags页面的工作方式;它有名称和数量。
无论如何,我创建了一个名为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; }
}
}
}
我想出了这个,但我收到了一个错误..
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;
}
我得到的错误说的是无法从匿名类型转换为学生列表。它是否与它有关而没有识别我在分部类中添加的数量字段?
谢谢!
答案 0 :(得分:4)
将Student
类型更改为如下所示:
public partial class Student
{
public Int32 Quantity { get; set; }
public String Name { get; set; }
}
你的查询看起来像这样:
var students = from s in db.Students
group s by s.Name into g
select new Student {
Name = g.Key,
Quantity = g.Count() };
您的方法返回IQueryable<Student>
,但您当前正在返回IQueryable<T>
预计的匿名类型。
您需要重构Student
类型以获得类型为Name
的{{1}}属性,然后从表达式中投射String
类型的新实例,以便返回表达式的类型将与方法的返回类型匹配。
答案 1 :(得分:2)
问题是你没有回来的学生 - 你试图从你的功能中返回一个匿名类型。这是不允许的。
创建一个类来表示您的结果,并在查询中使用new MyClass { ... }
而不是new { ... }
,并将方法更改为返回IQueryable<MyClass>
而不是IQueryable<Student>
。
例如,您可以创建一个名为StudentNameAndResults
的类。
class StudentNameAndResults
{
public string Name { get; set; }
public int Quantity { get; set; }
}
或者,您可以将结果作为字典或IGrouping的IEnumarable返回。例如:
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);
}
此外,您创建的属性使用的是前C#3.0天的详细语法。现在,如果您不需要任何特殊逻辑,则可以使用auto-implemented properties:
public int Quantity { get; set; }
答案 2 :(得分:2)
select new
关键字导致数据的形式发生变化,这意味着LINQ查询不会返回IQueryable&lt; Student&gt;,而是返回包含“Name”和“Quantity”属性的匿名类型。如果您更改它以返回具体类型而不是匿名类型,您将能够以所需的形式检索数据。
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;
}
答案 3 :(得分:2)
您的函数返回学生
public IQueryable<Student> FindStudentsDistinctWithQuantity(){ ... }
但是你的Linq查询返回一个包含Name和Int(count)
的新类型 >>> select new {Name = g.Key, Quantity = g.Count()});
y-try选择新学生{Name = g.Key,Quantity = g.Count()}
答案 4 :(得分:2)
该方法的返回值将“students
”集合与IQueryable<Student>
绑定,但是...... Linq表达式正在创建IQueryable<some anonymous type>
,并且两者之间没有转换。
通过修改您选择的部分,您可以进一步了解宝贝:
select new Student() {....}
希望这会有所帮助,
泰勒
答案 5 :(得分:1)
var students= (from s in db.Students
group s by s.Name into g
select new {Name = g.Key, Quantity = g.Count()});
这是一种匿名类型,而不是IQueryable<Student>
。您需要返回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()};
学生定义初始化中使用的属性。
答案 6 :(得分:1)
您正在linq查询中进行投影。如果你将光标悬停在var students
内部,你会看到它是一个匿名类型的集合。
如果您想要返回IQueryabley<Student>
,则需要执行以下操作:
var students= from s in db.Students
group s by s.Name into g
select s.Key;
外部方法无法了解您在上一个示例中创建的匿名类型,因此您将无法返回类型化集合。
使用我建议的方法,您仍然可以稍后对方法的返回值进行投影,因为IQueryable在第一次枚举之前是可组合的:
var students = FindStudentsDistinctWithQuantity();
var namesAndQunatity = from s in students select new {s.Name, s.Quantity};