获得第一个结果从LINQ查询 - 为什么ElementAt的< T>在第一&LT(0)失败; T>()成功? [英] Getting the first result from a LINQ query - why does ElementAt<T>(0) fails when First<T>() succeeds?

查看:102
本文介绍了获得第一个结果从LINQ查询 - 为什么ElementAt的< T>在第一&LT(0)失败; T>()成功?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个方法的传递addStudent()这看起来与同名的学生,如果有同名的学生返回从数据库中现有的学生,否则,它会创建一个新的学生,并将其添加到数据库中。



我很好奇,为什么 SE = students.First< StudentEntity>(); 成功当 SE = students.ElementAt< StudentEntity>(0); 当我尝试从LINQ查询的第一个结果失败。是不是这两种方法相同?



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

 公益助学传递addStudent(字符串名称)
{
使用(SchoolEntities DB =新SchoolEntities())
{
//学生找到同名通过LINQ
VAR学生=从s在db.StudentEntitySet
,其中s.name ==名
选择s;

StudentEntity SE =默认(StudentEntity);

//如果学生使用相同的名称已经存在,返回
//该学生
如果(students.Count< StudentEntity>()0)
{
//如果我使用ElementAt的,如果失败,出现LINQ到实体并不
//识别方法StudentEntity的ElementAt [StudentEntity]
//(System.Linq.IQueryable `1 [StudentEntity],Int32)将方法,
//这个方法不能被翻译成店的表情。,
//而不是当我使用第一。为什么?

//本身= students.ElementAt&所述; StudentEntity>(0);
SE = students.First< StudentEntity>();
}
,否则
{
//传递0,因为它是由
//在数据库中,所以任何价值$一个BIGINT IDENTITY字段表示的第一个参数(ID) b $ b //无所谓。
本身= StudentEntity.CreateStudentEntity(0,名);
db.AddToStudentEntitySet(SE);
db.SaveChanges();
}

//创建实体对象
A Student对象返回新的学生(SE);
}
}



谢谢!


< DIV CLASS =h2_lin>解决方案

这将失败,因为的ElementAt 法是一种索引访问方法和实体框架不知道如何以将其转换成SQL。



当您使用首先方法,实体框架可以转化为一个<$此C $ C> TOP 1 子句中的SQL查询。这是非常非常简单。为了使用的ElementAt ,那就要构建基于窗口函数( ROW_NUMBER()一个更复杂的查询),那么,它只是不太够复杂的做到这一点。



这实际上是一个的文件限制。在的ElementAt 延长根本不支持。






您可以在理论上,而是写:

  SE = students.AsEnumerable()的ElementAt< StudentEntity>(0); 

这指示实体框架不会尝试翻译后的任何事物的 AsEnumerable()调用,因此相反,它将检索的所有的结果(不只是第一批),直到它到达你想要的元素遍历它们(这在这种情况下,仅仅发生的是第一个)。



不过,这会拖慢操作的很多相比,只使用第一(),因为不是从服务器获取刚刚1的结果,它获取所有他们和过滤器之后。如果出于某种奇怪的原因,我需要得到第5或10元或某些元素的其他的比第一次。


我只会使用此解决方案

I have a method AddStudent() which looks for a student with the same name and returns an existing student from the database if there is a student with the same name, otherwise it creates a new student and adds it to the database.

I'm curious why se = students.First<StudentEntity>(); succeeds when se = students.ElementAt<StudentEntity>(0); fails when I try to get the first result from the LINQ query. Aren't the two methods the same?

The full code for the method is shown below.

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);
    }
}

Thanks!

解决方案

It fails because the ElementAt method is an indexed-access method and the Entity Framework doesn't know how to turn that into SQL.

When you use the First method, Entity Framework can translate this into a TOP 1 clause in a SQL query. It's very very simple. In order to use ElementAt, it would have to construct a much more complex query based on windowing functions (ROW_NUMBER()) and, well, it just isn't quite sophisticated enough to do that.

It's actually a documented limitation of the Entity Framework. The ElementAt extension simply isn't supported.


You could, in theory, write this instead:

se = students.AsEnumerable().ElementAt<StudentEntity>(0);

This instructs the Entity Framework not to try to "translate" anything after the AsEnumerable() call, so instead, it will retrieve all of the results (not just the first) and iterate through them until it gets to the element you want (which in this case just happens to be the first).

However, this will slow down the operation a lot compared to just using First(), because instead of just fetching 1 result from the server, it fetches all of them and filters afterward. I would only use this workaround if for some strange reason I needed to get the 5th or 10th element or some element other than the first one.

这篇关于获得第一个结果从LINQ查询 - 为什么ElementAt的&LT; T&gt;在第一&LT(0)失败; T&GT;()成功?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆