Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从LINQ查询中获取第一个结果-为什么ElementAt<;T>;(0)当第一次<;T>;()成功了吗?_C#_Linq_Entity Framework - Fatal编程技术网

C# 从LINQ查询中获取第一个结果-为什么ElementAt<;T>;(0)当第一次<;T>;()成功了吗?

C# 从LINQ查询中获取第一个结果-为什么ElementAt<;T>;(0)当第一次<;T>;()成功了吗?,c#,linq,entity-framework,C#,Linq,Entity Framework,我有一个方法AddStudent(),它查找同名学生,如果有同名学生,则从数据库返回现有学生,否则它将创建一个新学生并将其添加到数据库中 我很好奇为什么se=students.First()成功失败。这两种方法不一样吗 该方法的完整代码如下所示 public Student AddStudent(string name) { using (SchoolEntities db = new SchoolEntities()) { // find student wit

我有一个方法AddStudent(),它查找同名学生,如果有同名学生,则从数据库返回现有学生,否则它将创建一个新学生并将其添加到数据库中

我很好奇为什么
se=students.First()se=students.ElementAt(0)时,code>成功失败。这两种方法不一样吗

该方法的完整代码如下所示

public Student AddStudent(string name)
{
    using (SchoolEntities db = new SchoolEntities())
    {
        // find student with same name via LINQ
        var students = from s in db.StudentEntitySet
                       where s.name == name
                       select s;

        StudentEntity se = default(StudentEntity);

        // if student with the same name is already present, return 
        // that student
        if (students.Count<StudentEntity>() > 0)
        {
            // if i use ElementAt, if fails with a "LINQ to Entities does not
            // recognize the method 'StudentEntity ElementAt[StudentEntity]
            // (System.Linq.IQueryable`1[StudentEntity], Int32)' method, 
            // and this method cannot be translated into a store expression.", 
            // but not when I use First. Why?

            // se = students.ElementAt<StudentEntity>(0);
            se = students.First<StudentEntity>();
        }
        else
        {
            // passing 0 for first parameter (id) since it's represented by 
            // a BigInt IDENTITY field in the database so any value
            // doesn't matter.
            se = StudentEntity.CreateStudentEntity(0, name);
            db.AddToStudentEntitySet(se);
            db.SaveChanges();
        }

        // create a Student object from the Entity object
        return new Student(se);
    }
}
public Student AddStudent(字符串名)
{
使用(SchoolEntities db=new SchoolEntities())
{
//通过LINQ查找同名学生
var students=来自db.StudentEntitySet中的s
其中s.name==name
选择s;
StudentEntity se=默认值(StudentEntity);
//如果已存在同名学生,请返回
//那个学生
如果(students.Count()>0)
{
//如果我使用ElementAt,如果失败,则使用“LINQ to Entities NOTS”
//在[StudentEntity]中识别方法“StudentEntity元素”
//(System.Linq.IQueryable`1[StudentEntity],Int32)“方法,
//并且此方法无法转换为存储表达式。“,
//但当我第一次使用时就不行了。为什么?
//se=学生。元素AT(0);
se=学生。首先();
}
其他的
{
//正在为第一个参数(id)传递0,因为它由
//数据库中的BigInt标识字段,因此任何值
//没关系。
se=StudentEntity.CreateSudentEntity(0,名称);
db.AddToStudentEntitySet(se);
db.SaveChanges();
}
//从实体对象创建学生对象
返回新生(se);
}
}

谢谢

它失败了,因为
ElementAt
方法是一种索引访问方法,实体框架不知道如何将其转换为SQL

使用
First
方法时,实体框架可以将其转换为SQL查询中的
TOP 1
子句。这很简单。为了使用
ElementAt
,它必须基于窗口函数(
ROW\u NUMBER()
)构造一个复杂得多的查询,而且它还不够复杂

它实际上是实体框架的一部分。根本不支持
ElementAt
扩展


理论上,你可以这样写:

se = students.AsEnumerable().ElementAt<StudentEntity>(0);
se=students.AsEnumerable().ElementAt(0);
这指示实体框架在调用
AsEnumerable()
之后不要尝试“翻译”任何内容,因此,它将检索所有结果(而不仅仅是第一个结果)并遍历它们,直到它到达所需的元素(在本例中恰好是第一个)


但是,与仅使用
First()
相比,这将大大降低操作的速度,因为它不只是从服务器获取一个结果,而是获取所有结果,然后进行过滤。如果出于某种奇怪的原因,我需要获取第5个或第10个元素或第一个元素以外的其他元素,我只会使用此解决方法。

我觉得奇怪的是,它无法执行
跳过n TOP 1
@Simon:我不确定您指的是哪个DBMS,但SQL Server没有
跳过
关键字。实体框架可以使用
Skip(n)
Take(n)
扩展方法进行分页查询(它生成一个
行号
查询,如我在回答中所述),但SQL翻译往往是一个接一个地实现的,我猜微软只是没有着手实现
ElementAt
,他们认为它不够重要,可能是因为它可以很容易地用
Skip(n)
然后
Take(1)
组合而成。西蒙:正如阿诺诺所说,你可以通过Skip(n).Take(1).First()来完成。我不确定为什么它不能在内部将ElementAt转换成这个,但我的猜测是,如果结果少于n个,ElementAt就有不同的语义(例如ElementAt应该抛出,但是Skip/Take会导致一个空序列——但第一个仍然会处理抛出…。@Aaronaught:是的,我的意思是ESQL中的
SKIP
子句。听起来MSSQL不支持它,但我使用过的大多数其他RDBMs都支持它(语法稍有不同)。比较
First()
Skip(0)生成的SQL。使用(1)。First()
你就会明白为什么首先使用正确的方法更好。:)另一方面,使用var student=db.StudentEntitySet.SingleOrDefault(s=>s.name==name),可以大大简化代码并提高可读性;如果(student!=null){return student;}//Create student hereNice!我会尝试一下。在VS2008中不为EF运行,抛出一个异常“LINQ to Entities不支持方法'Single'。显然适用于EF4-:(无论如何谢谢:)@Neal,使用了FirstOrDefault()而不是SingleOrDefault(),现在可以使用了。代码现在看起来好多了。