从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个元素或除第一个之外的某些元素。