代码之家  ›  专栏  ›  技术社区  ›  anonymous

从LINQ查询获取第一个结果-为什么当第一个成功时elementat(0)失败?

  •  3
  • anonymous  · 技术社区  · 14 年前

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

    我很好奇为什么 se = students.First<StudentEntity>(); 成功时 se = students.ElementAt<StudentEntity>(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<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);
        }
    }
    

    谢谢!

    1 回复  |  直到 14 年前
        1
  •  8
  •   Aaronaught    14 年前

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

    当你使用 First 方法,实体框架可以将其转换为 TOP 1 SQL查询中的子句。这很简单。为了使用 要素 ,它必须基于窗口函数构造一个更复杂的查询。( ROW_NUMBER() )而且,好吧,这还不够复杂。

    它实际上是一个 documented limitation 实体框架。这个 要素 不支持扩展。


    理论上,你可以这样写:

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

    这将指示实体框架不要在 AsEnumerable() 调用,因此它将检索 全部的 对结果(不只是第一个)进行迭代,直到它到达所需的元素(在本例中是 发生 第一个)。

    但是,这会减慢操作速度 很多 与仅仅使用 First() ,因为它不只是从服务器获取1个结果,而是随后获取所有结果和过滤器。如果出于某种奇怪的原因,我需要得到第五个或第十个元素或某个元素,我将只使用这个变通方法。 其他 比第一个要多。