Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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# 模拟使用与等于相反的contains运算符的联接?_C#_Linq_Iqueryable - Fatal编程技术网

C# 模拟使用与等于相反的contains运算符的联接?

C# 模拟使用与等于相反的contains运算符的联接?,c#,linq,iqueryable,C#,Linq,Iqueryable,我发现了join操作符,因此。但是,我需要执行非等联接 我特别需要使用以下设置编写一个查询。给定两种类型的对象类和学生 我想这样写查询 var query = from cls in allClasses join std in allStudents on cls.Students.Contains(std.StudentId) into clsStds where clsStds.Select(aStd => aStd.Grade).Average() > 70

我发现了join操作符,因此。但是,我需要执行非等联接

我特别需要使用以下设置编写一个查询。给定两种类型的对象类和学生

我想这样写查询

var query = from cls in allClasses
    join std in allStudents on cls.Students.Contains(std.StudentId) into clsStds
    where clsStds.Select(aStd => aStd.Grade).Average() > 70
    select cls;
虽然这显然是无效的语法。提供了一个非等联接的示例,尽管我尝试在这里应用它,但似乎无法正确地复制它和/或我自己严重困惑


如何模拟上面描述的联接类型?

您使用的是实体框架还是类似的?实体之间是否有导航属性?如果是这样,也许您可以对学生进行分组,然后导航到父对象。比如:

    var query = allStudents
        .GroupBy(i=>i.Class)
        .Select(i=>new{
            Class = i,
            Average = i.Average(j=>j.Grade)
        })
        .Where(i=>i.Average > 70)
        .ToList();

我找到了一种解决这个问题的简单方法。首先,我们将student中的Guid引用解析为实际的student对象

然后我们可以查询这个匿名对象集合

var classes = 
   from clsStdObj in clsStd
   where clsStdObj.stdObjs.Select(stdObj => stdObj.Grade).Average() > 70
   select clsStdObj.cls;
然后将其分解为学生平均成绩在70分以上的所有班级


但我仍然愿意接受不那么幼稚的解决方案。

这可能是一个解决方案,这要感谢@EricLippert提供了使用Any的建议,以避免classGrades为空时可能出现的崩溃:

var query = from _class in allClasses
            let classGrades = from std in allStudents
                           where _class.Students.Contains(std.StudentId)
                           select std.Grade
            where classGrades.Any()
            where classGrades.Average() > 70
            select _class;
基本上,对于每个类,我创建一个新的子查询,在其中选择该类中的所有学生,并仅预测成绩,因此结果是IEnumerable。下一部分很简单:平均分数


出于好奇,我使用秒表将您的解决方案与我的解决方案进行了比较,即使它纯粹是指示性的,我/您的延迟时间之间的比率约为0.02。

首先,您的数据模型是错误的。学生没有一个年级。他们在一个班级里有一个等级,而你的模型没有考虑到这一点。您需要第三个表,包含student、class和grade列。我强烈建议你解决这个问题

解决上述问题很简单,但我不喜欢目前为止提出的任何解决方案。它们基本上是合理的,但可能更高效、更健壮

你所面临的基本问题是:你没有一个快速简单的方法从学生ID到学生对象。首先解决这个问题:

太好了。现在,解决方案很简单:

var query = 
  from cls in allClasses
  let grades = from id in cls.Students select idToStudent(id).Grade
  where grades.Any()
  where grades.Average() > 70
  select cls;
请注意,我们正在测试是否有任何分数,因为可能会有一个没有学生的班级。如果要求平均值为零,则平均值将崩溃,因此检查是明智的

当您修复数据模型以便正确关联学生、班级和成绩时,它将是:

var query = 
  from cls in allClasses
  let grades = 
    from grade in allGrades 
    where grade.Class == cls 
    select grade.grade
  where grades.Any()
  where grades.Average() > 70
  select cls;
在一组设计合理的表格中,学生ID在计算平均值时不会出现在其中;你可以把成绩和班级直接联系起来

现在,您在开始这个问题时注意到您需要一种C不支持的连接。不,您需要修复数据关系,然后C支持您需要的连接类型!以上内容可以更有效地写成

var query = 
  from cls in allClasses
  join g in allGrades on cls equals g.Class into grades
  where grades.Average() > 70
  select cls;
由于C不会生成空组,因此检查任何组的需要消失了


这就是你需要的加入;正确设计您的桌子,然后使用它

我不熟悉实体框架,我以前在很多地方见过它,但我不确定它是什么或用于什么。这个问题来自于试图以问题中指定的方式查询MongoDB。啊,我明白了。实体框架是用于数据层的ORM,除此之外,还为数据存储中的对象生成类。它很方便,因为它允许您以面向对象的方式使用数据层,而无需花费大量精力。您有没有办法在模型中从一个学生到另一个班级?从一个学生到另一个班级是没有办法的。只有类通过Guid id引用学生,学生甚至不知道它在一个类中。因此,您只想要所有类中成绩高于70的学生?我想要相反的,我想要所有学生平均成绩高于70的类。您将问题标记为IQueryable,但您似乎正在使用LINQ对象;你能解释一下为什么要贴标签吗?我给出的查找解决方案假定LINQ是对象,IQueryable来自于MongoDB中LinqExtension的使用。这个问题代表了一个更简单和类似的情况,我希望在MongoDB中构建一个查询,因此我有您在回答中提到的奇怪的数据模型。对不起,IMongoQueryable,我刚刚意识到它的Mongo特定用法。这是一个合理的解决方案尝试,但有几个问题。如果有一个班没有学生,那么平均崩溃;您可以在其中添加classGrades.Any。第二,当班上已经有一个成员学生的列表时,迭代所有学生并拉出班上的学生,这有点奇怪@EricLippert谢谢你让我想起了那次普通的车祸,我没想过。然而关于第二点,我知道这很奇怪,但我选择了给他一个解决方案 基于他的模型和约束条件。我读了你的答案,你是绝对正确的,因为你强调了这背后的问题。
var idToStudent = allStudents.ToLookup(s => s.id);
var query = 
  from cls in allClasses
  let grades = from id in cls.Students select idToStudent(id).Grade
  where grades.Any()
  where grades.Average() > 70
  select cls;
var query = 
  from cls in allClasses
  let grades = 
    from grade in allGrades 
    where grade.Class == cls 
    select grade.grade
  where grades.Any()
  where grades.Average() > 70
  select cls;
var query = 
  from cls in allClasses
  join g in allGrades on cls equals g.Class into grades
  where grades.Average() > 70
  select cls;