C# LINQ返回MVC5 Razor视图上的所有记录和groupby
我的查询返回与特定职位匹配的人员列表。我希望它返回所有职位的列表,即使没有匹配该职位的人。我加入people的原因是因为我需要“Assigned”的计数,这是一个动态添加的计数字段,与职位匹配。但是,如果没有与该职位匹配的人员,我希望它仍然返回计费的职位,但希望“Assigned”设置为0C# LINQ返回MVC5 Razor视图上的所有记录和groupby,c#,asp.net-mvc,linq,razor,C#,Asp.net Mvc,Linq,Razor,我的查询返回与特定职位匹配的人员列表。我希望它返回所有职位的列表,即使没有匹配该职位的人。我加入people的原因是因为我需要“Assigned”的计数,这是一个动态添加的计数字段,与职位匹配。但是,如果没有与该职位匹配的人员,我希望它仍然返回计费的职位,但希望“Assigned”设置为0 dynamic query = (from a in db.Positions join b in db.People
dynamic query = (from a in db.Positions
join b in db.People
on new {
a.GradeId,
a.SeriesId,
a.CompanyId,
a.PaybandId }
equals new {
b.GradeId,
b.SeriesId,
b.CompanyId,
b.PaybandId } into ab
from k in ab.DefaultIfEmpty()
join c in db.Grades on k.GradeId equals c.Id
join d in db.Series on k.SeriesId equals d.Id
join e in db.Companies on k.CompanyId equals e.Id
join p in db.Paybands on k.PaybandId equals p.Id
group a by new { CompanyName = e.Name,
GradeName = c.Name,
SeriesName = d.Name,
PaybandName = p.Name,
a.Authorized } into f
select new { Company = f.Key.CompanyName,
Grade = f.Key.GradeName,
Series = f.Key.SeriesName,
Payband = f.Key.PaybandName,
Authorized = f.Key.Authorized,
Assigned = f.Count() }).AsEnumerable().Select(r => r.ToExpando());
我面临的另一个问题是,在razor页面上,该公司正在重复。我需要的公司标题,以显示每个公司只有一次,但希望所有职位都列在下面
以下是视图屏幕截图和razor脚本:
“我希望它能返回所有职位的列表,即使没有
与职位匹配的人。”
正如您所说,您只需执行下一步(编辑此部分):
之前:
from a in db.Positions
join b in db.People
之后:
from a in db.Positions
left join b in db.People
正如您所看到的,我应用了左联接
,因为SQL左联接
返回左表中的所有行,即使右表中没有匹配项。这意味着,如果ON子句与右表中的0(零)条记录匹配;联接仍将在结果中返回一行,但右表中的每一列都返回NULL
这意味着左连接返回左表中的所有值,加上右表中的匹配值,如果没有匹配的连接谓词,则返回NULL
我希望这对你有帮助,
干杯您需要稍微更改查询中的逻辑,以便更早地计数,然后事情就会变得简单一些。请参见下面代码段中的注释:
...
from a in db.Positions
join b in db.People
on new {
a.GradeId,
a.SeriesId,
a.CompanyId,
a.PaybandId }
equals new {
b.GradeId,
b.SeriesId,
b.CompanyId,
b.PaybandId } into ab
from k in ab.DefaultIfEmpty()
// you want to count the number of people per position here
group k by new { a.GradeId, a.SeriesId, a.CompanyId, a.PaybandId, a.Authorized } into g
select new { g.Key.GradeId, g.Key.SeriesId, g.Key.CompanyId, g.Key.PaybandId, g.Authorized, Count = g.Count(p => p != null) } into counts
// at this point you have position info AND people count per position
// next, you can do the remaining joins...
join c in db.Grades on counts.GradeId equals c.Id
join d in db.Series on counts.SeriesId equals d.Id
join e in db.Companies on counts.CompanyId equals e.Id
join p in db.Paybands on counts.PaybandId equals p.Id
// ... and select full data set, including person count, required for the view
select new {
CompanyName = e.Name,
GradeName = c.Name,
SeriesName = d.Name,
PaybandName = p.Name,
counts.Authorized,
Assigned = counts.Count
} into full
// one more step here that will help to tackle your second problem (grouping by company name in the view)
// you want your data coming into the view be grouped by company name
group full by full.CompanyName into groupByCompany
select new CompanyInfo { CompanyName = groupByCompany.Key, CompanyItems = groupByCompany.Select(i => new CompanyItem { GradeName = i.GradeName, SeriesName = i.SeriesName, PaybandName = i.PaybandName, Authorized = i.Authorized, Assigned = i.Assigned }).ToList() }
...
然后在视图中,您需要创建2个@foreach
循环,而不是一个。第一个(外部)将在上面的集合上循环并呈现一次带有公司名称的行,而另一个(内部)将在集合中每个项目的CompanyItems
属性上循环,并在公司名称行下呈现每个项目的行
此外,生成的HTML不是100%有效,因为存在多个thead
标记。以下是经过编辑的版本:
...
@model IEnumerable<CompanyInfo>
<table class="table table-responsive table-hover">
<thead>
<tr>
<th class="col-sm-1"></th>
<th class="col-sm-2">Grade</th>
<th class="col-sm-2">Series</th>
<th class="col-sm-2">Payband</th>
<th class="col-sm-2">Authorized</th>
<th class="col-sm-2">Assigned</th>
</tr>
</thead>
@foreach (CompanyInfo item in Model)
{
<tbody>
<tr class="company-name">
<th class="panel-bg" colspan="6">@item.CompanyName</th>
</tr>
@foreach (CompanyItem companyItem in item.CompanyItems)
{
<tr>
<td class="col-sm-1"></td>
<td class="col-sm-2">@companyItem.Grade</td>
<td class="col-sm-2">@companyItem.Series</td>
<td class="col-sm-2">@companyItem.Payband</td>
<td class="col-sm-2">@companyItem.Authorized</td>
<td class="col-sm-2">@companyItem.Assigned</td>
</tr>
}
</tbody>
}
</table>
...
。。。
@模型IEnumerable
等级
系列
工资带
经授权的
分配
@foreach(模型中的公司信息项)
{
@item.CompanyName
@foreach(项目中的CompanyItem CompanyItem.CompanyItems)
{
@公司项目等级
@公司项目系列
@公司项目工资带
@授权公司项目
@分配的公司项目
}
}
...
要使用强类型视图模型,请添加以下两个类:
class CompanyInfo
{
public string CompanyName { get; set; }
public List<CompanyItem> CompanyItems { get; set; }
}
class CompanyItem
{
public string GradeName { get; set; }
public string SeriesName { get; set; }
public string PaybandName { get; set; }
public bool Authorized { get; set; }
public int Assigned { get; set; }
}
class公司信息
{
公共字符串CompanyName{get;set;}
公共列表公司项目{get;set;}
}
类公司项目
{
公共字符串GradeName{get;set;}
公共字符串序列名{get;set;}
公共字符串PaybandName{get;set;}
公共bool授权{get;set;}
公共int赋值{get;set;}
}
然后根据上面的更新更新代码。你能添加你的职位类吗?@MichaelBurns-根据你的请求添加的“left join”不是有效的LINQ语法,不幸的是,否则这会简单得多:)惊人、彻底的答案。在您的实现中,我遇到了一些错误。1.名称“a”在当前上下文中不存在,而名称“2”匿名类型#1'不包含“计数”的定义。选择新建{CompanyName=e.Name,GradeName=c.Name,SeriesName=d.Name,PaybandName=p.Name,a.Authorized,//对不起,你是对的。修复了它们,请查看更新的代码。基本上,
Assigned=counts.Count()
应该被分配=计数。计数
;至于a.Authorized
,它应该被包括在第一组中,并从那里重新使用。另外,请注意class=“company name”的用法
attr在视图中。由于我们去掉了多个thead
s,因此需要使用CSS设置公司名称行的样式。这是由于动态模型和匿名类型的组合被用作模型。在运行时,匿名模型被视为一个对象,而对象没有我们试图访问的属性。因此,这里是best使用强类型视图模型。我现在将更新代码。不客气!请参阅更新的代码。您需要添加两个类,更新查询中的最终select
,并更新视图。请告诉我是否还有其他ERORR。我必须在此处和此处进行一些小更改,并且缺少一个.Key。但是,sol这是坚如磐石,我感谢你一直以来对我的帮助和帮助。我对你的做法更加理解,从长远来看,这将帮助我。再次感谢你,兄弟!这是应得的赏金!(但要到17小时后才能颁发)
...
@model IEnumerable<CompanyInfo>
<table class="table table-responsive table-hover">
<thead>
<tr>
<th class="col-sm-1"></th>
<th class="col-sm-2">Grade</th>
<th class="col-sm-2">Series</th>
<th class="col-sm-2">Payband</th>
<th class="col-sm-2">Authorized</th>
<th class="col-sm-2">Assigned</th>
</tr>
</thead>
@foreach (CompanyInfo item in Model)
{
<tbody>
<tr class="company-name">
<th class="panel-bg" colspan="6">@item.CompanyName</th>
</tr>
@foreach (CompanyItem companyItem in item.CompanyItems)
{
<tr>
<td class="col-sm-1"></td>
<td class="col-sm-2">@companyItem.Grade</td>
<td class="col-sm-2">@companyItem.Series</td>
<td class="col-sm-2">@companyItem.Payband</td>
<td class="col-sm-2">@companyItem.Authorized</td>
<td class="col-sm-2">@companyItem.Assigned</td>
</tr>
}
</tbody>
}
</table>
...
class CompanyInfo
{
public string CompanyName { get; set; }
public List<CompanyItem> CompanyItems { get; set; }
}
class CompanyItem
{
public string GradeName { get; set; }
public string SeriesName { get; set; }
public string PaybandName { get; set; }
public bool Authorized { get; set; }
public int Assigned { get; set; }
}