C# 将简单的左外联接和group by SQL语句转换为Linq

C# 将简单的左外联接和group by SQL语句转换为Linq,c#,sql-server,linq,join,linq-to-entities,C#,Sql Server,Linq,Join,Linq To Entities,2表:用户和报警 表:用户 用户ID(int), 全名(varchar) 表:警报 分配给(int), 已解决(bool) 查询: 结果: 就我的一生而言,我不知道如何将其转换为Linq查询。我的分组功能有问题。 我看了无数的例子,没有一个有我的左外连接和分组的组合,或者它们太复杂了,我不知道如何使它与我的工作。这里的任何帮助都将不胜感激 更新: 我可能不清楚我在找什么。我正在寻找按AssignedTo列分组的报警,该列是一个用户ID。。。除此之外,我想用users表中的全名替换该userid。

2表:用户和报警

表:用户 用户ID(int), 全名(varchar)

表:警报 分配给(int), 已解决(bool)

查询:

结果:

就我的一生而言,我不知道如何将其转换为Linq查询。我的分组功能有问题。 我看了无数的例子,没有一个有我的左外连接和分组的组合,或者它们太复杂了,我不知道如何使它与我的工作。这里的任何帮助都将不胜感激

更新: 我可能不清楚我在找什么。我正在寻找按AssignedTo列分组的报警,该列是一个用户ID。。。除此之外,我想用users表中的全名替换该userid。有人发布并删除了一些相近的内容,但它给了我用户表中的所有用户,这不是我要找的

更新2:请参见下面的我的答案

试试这个:

from u in context.User
join a in context.Alarm on u.UserID equals a.AssignedTo into g1
from g2 in g1.DefaultIfEmpty()
group g2 by u.Fullname into grouped
select new { Fullname = grouped.Key, Assigned = grouped.Count(t=>t.Resolved != null), Resolved = grouped.Sum
                                    (t => int.Parse(t.Resolved)), Unresolved = (grouped.Count(t=>t.Resolved != null) - grouped.Sum
                                    (t => int.Parse(t.Resolved)))}

我猜在Linq中不一定要使用“分组”,因为“LEFT JOIN”+“GROUP BY”的组合将它们改为“internal JOIN”


假设您有以下模型:

这是报警的模型:

public class Alarm
{
    public int id { get; set; }

    public int AssignedTo { get; set; }

    [ForeignKey("AssignedTo")] 
    public virtual User User { get; set; }

    public bool Resolved { get; set; }
}
这是用户的模型:

public class User
{
    public int UserID { get; set; }

    public string FullName { get; set; }

    public virtual ICollection<Alarm> Alarms { get; set; }

    public User()
    {
        Alarms = new HashSet<Alarm>();
    }
}
然后,您可以执行以下操作:

var query = context.Users.Select(
    user =>
        new UserStatistics
        {
            FullName = user.FullName,
            Assigned = user.Alarms.Count,
            Resolved = user.Alarms.Count(alarm => alarm.Resolved),
            Unresolved = user.Alarms.Count(alarm => !alarm.Resolved)
        });


var result = query.ToList();
顺便说一下,您还可以修改查询并删除
Unresolved=user.Alarms.Count(alarm=>!alarm.Resolved)
,然后将
Unresolved
属性设置为计算属性,如下所示:

public class UserStatistics
{
    public string FullName { get; set; }
    public int Assigned { get; set; }    
    public int Resolved { get; set; }    
    public int Unresolved
    {
        get { return Assigned - Resolved; }
    }
}

这将使生成的SQL查询更简单。

我终于找到了答案

这:

复制以下内容:

结果按AssignedTo(int)分组,但未选择AssignedTo。而是从联接的用户表中选择FullName

非常感谢每一位试图帮助我们的人!我从你的回答中学到了很多


为了获得额外的分数,我将如何用类似SQL的语法编写lamdbda答案?

报警表是否有主键?您知道WHERE子句将左连接变为内部连接是的,它是“id”但在sql查询中不需要,因为我们将连接alarm表中的AssignedTo字段和User表中的UserId字段。你得到的是错误的结果还是错误信息?哇!我甚至都没意识到那个尤尔根!但是,这确实给了我需要的结果。那么如何在linq查询中做到这一点呢?:)这与我试图做的类似,但我从我的错误中得到的错误与我在“group g2 by u.Fullname to grouped”行中得到的错误相同。“无法将lambda表达式转换为类型”“System.Collections.Generic.IEqualityComparer”“,因为它不是委托类型”,并且此“'MyProject.Models.User'不包含'Fullname'的定义,并且找不到接受类型为'MyProject.Models.User'的第一个参数的扩展方法'Fullname'(您是否缺少using指令或程序集引用?)“从查询中提取任何C#调用(如Int32.Parse)并将其作为常量值传递。如果不能,则无法将LINQ查询转换为SQL。因此,您需要重新考虑它(或者在内存中执行此操作,直到您真正了解自己在做什么).虽然这非常令人印象深刻,但这里有太多我不明白的地方:)我的课程绝对不是这样设置的。也许它们应该是,但我需要了解一些事情,比如虚拟Icollections和User()函数的调用位置。你的努力得A!!!:)您使用的数据访问技术是什么?(例如实体框架、LINQ到SQL…)。你的模特长什么样?你是用代码写的吗?或者是从数据库中自动生成的?Massd-我使用的是实体框架。出于所有目的,我的模型如上所述,但每个表中都有更多的属性。我已经弄明白了,并以lambda格式发布了我的答案。我将如何使用类似LINQSQL的语法编写此代码?谢谢除非确实需要,否则不要编写显式连接(通常不需要)。让EF来做它的工作:)@abatishchev请解释。@Wizadre:我会有一个导航属性1:many ICollection用于用户,User用于报警。
public class User
{
    public int UserID { get; set; }

    public string FullName { get; set; }

    public virtual ICollection<Alarm> Alarms { get; set; }

    public User()
    {
        Alarms = new HashSet<Alarm>();
    }
}
public class UserStatistics
{
    public string FullName { get; set; }
    public int Assigned { get; set; }    
    public int Resolved { get; set; }    
    public int Unresolved { get; set; }    
}
var query = context.Users.Select(
    user =>
        new UserStatistics
        {
            FullName = user.FullName,
            Assigned = user.Alarms.Count,
            Resolved = user.Alarms.Count(alarm => alarm.Resolved),
            Unresolved = user.Alarms.Count(alarm => !alarm.Resolved)
        });


var result = query.ToList();
public class UserStatistics
{
    public string FullName { get; set; }
    public int Assigned { get; set; }    
    public int Resolved { get; set; }    
    public int Unresolved
    {
        get { return Assigned - Resolved; }
    }
}
var results = alarms.GroupBy(x => x.AssignedTo)
.Join(users, alm => alm.Key , usr => usr.UserID, (alm, usr) => new {
    Fullname = usr.FullName,AssignedNum = alm.Count(),
    Resolved = alm.Where(t=>t.resolved == true).Select(y => y.resolved).Count(), 
    Unresolved = alm.Where(t=>t.resolved == false).Select(y => y.resolved).Count() });
SELECT u.Fullname, COUNT(resolved) as Assigned, SUM(CONVERT(int,Resolved)) as Resolved, 
       COUNT(resolved) -  SUM(CONVERT(int,Resolved)) as Unresolved
FROM Alarm i LEFT OUTER JOIN Users u on i.AssignedTo = u.UserID
GROUP BY u.Fullname