我尝试使用LINQ到我的EF Code First数据库进行查询以检索全年的销售额并返回一个新的DTO对象,该对象包含月份数和当月销售总额。
我的查询工作正常,但不包含销售的月份会返回null而不是“0”,这会在我的视图中产生问题。
我已经尝试了空合并??
,但得到的编译错误对decimal
无效。我也尝试了DefaultIfEmpty
,但这似乎与.Sum-method一起使用。
有什么建议吗?
型号:
public class YearlySalesDto
{
public string Month { get; set; }
public decimal TotalSales { get; set; }
}
查询:
[AllowAnonymous]
public IEnumerable<YearlySalesDto> Index()
{
var result = from r in db.Orders
group r by r.OrderDate.Month into g
select new YearlySalesDto { Month = g.Key.ToString() ?? "", TotalSales = g.Sum(p => p.OrderItems.Select(x => x.Quantity * x.UnitPrice).Sum()) };
if (result == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return result;
}
此查询的结果,因为我在第3个月和第4个月只在数据库中有销售。
[
{
"Month": "3",
"TotalSales": 158
},
{
"Month": "4",
"TotalSales": 373
}
]
答案 0 :(得分:4)
你的选择与此问题无关,你可以摆脱它并仍然看到问题,GroupBy
不返回g.Count == 0
的值,你需要做的是添加占位符条目对于db.Orders
中没有行的月份,总计为0,并将其与结果合并。
var result = from r in db.Orders
group r by r.OrderDate.Month
into g
select new YearlySalesDto {
Month = g.Key.ToString(), // The ?? "" is unnecessary.
TotalSales = g.Sum(p => p.OrderItems.Select(x => x.Quantity * x.UnitPrice).Sum())
};
var fixedResult = result.AsEnumerable()
.Union(Enumerable.Range(1,12)
.Select(x=>new YearlySalesDto { Month = x.ToString(), TotalSales = 0 })
, new MonthComparer());
//Elsewhere
class MonthComparer : IEqualityComparer<YearlySalesDto>
{
public bool Equals(YearlySalesDto x, YearlySalesDto y)
{
return x.Month == y.Month;
}
public int GetHashCode(YearlySalesDto x)
{
return x.Month.GetHashCode();
}
}
答案 1 :(得分:3)
您收到的编译错误由@Scott在上面的评论中解释。
至于数月的零值,数据库中没有剩下的数据,请将结果与月份集合连接,如果是null
地点0
:
var result = from m in Enumerable.Range(1,12)
join g in db.Orders.GroupBy(r => r.OrderDate.Month) on m equals g.Key into joint
from g in joint.DefaultIfEmpty()
select new YearlySalesDto {
Month = m.ToString(),
TotalSales = g == null ? 0 : g.Sum(p => p.OrderItems.SelectMany(x => x.Quantity * x.UnitPrice))
};