从LINQ查询中获取第一个结果 – 当First ()成功时,为什么ElementAt (0)会失败?

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

我很好奇为什么se = students.First();se = students.ElementAt(0); 当我尝试从LINQ查询中获取第一个结果时失败。 这两种方法不一样吗?

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

 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() > 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(0); se = students.First(); } 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); } } 

谢谢!

它失败是因为ElementAt方法是索引访问方法,而entity framework不知道如何将其转换为SQL。

当您使用First方法时,Entity Framework可以将其转换为SQL查询中的TOP 1子句。 这非常简单。 为了使用ElementAt ,它必须基于窗口函数( ROW_NUMBER() )构造一个更复杂的查询,而且,它只是不够复杂到那么做。

它实际上是entity framework的文档限制 。 不支持ElementAt扩展。


理论上,你可以写这个:

 se = students.AsEnumerable().ElementAt(0); 

这指示entity framework在AsEnumerable()调用之后不要尝试“翻译”任何内容,因此它将检索所有结果(不仅仅是第一个)并迭代它们直到它到达你想要的元素(在这种情况下恰好是第一个)。

但是,与仅使用First()相比,这将大大减慢操作速度,因为它不是仅从服务器获取1个结果,而是随后获取所有结果并过滤。 我只会使用这种解决方法,如果由于一些奇怪的原因我需要获得第5或第10个元素或除第一个之外的某些元素。