我有一个将EF Core与MVC结合使用的C#项目。
我有一个代表“虚拟”实体的控制器。通过从两个不同的表中进行选择来创建该实体,然后按月和年对每个表进行汇总,然后将两个结果连接起来。
我的问题是:是否可以(如果是,这是一个好的解决方案)用EF Core进行累加?还是我应该使用C#遍历元素并按照我想要的方式聚合它们?
编辑:目前,我可以这样做:
public IEnumerable<MyTable> Get...(int month, int year)
return _context.MyTable
//.Include(b => b.)
.Where(t => t.Month == month && t.Year == year)
.GroupBy(a => a.BrokerId)
.Select(param1 => new {
BrokerId = param1.Key,
TotalCommissionAmountBruto = param1.Sum(s => s.CommissionAmountBruto),
TotalCommissionAmountNeto = param1.Sum(s=>s.CommissionAmountNeto)
});
这将引发错误,因为查询结果未格式化为MyTable
对象。我尝试为结果创建另一个viewModel,但是没有成功(关于隐式转换的相同错误)
viewModel:
public class MyViewModel : DtoBase
{
public int brokerId { get; set; }
public int TotalCommissionAmountBruto { get; set; }
public int TotalCommissionAmountNeto { get; set; }
}
答案 0 :(得分:1)
有很多方法可以达到此要求。如果表之间存在父子关系,则可以使用Include
和ThenInclude
。
您也可以使用FromSql
方法运行存储过程,然后选择所需的数据。
您还可以通过扩展方式Select
使用投影查询。
对于上述所有内容,您都可以参考Microsoft提供的官方文档。
答案 1 :(得分:1)
根据现在显示的代码进行编辑:
您显示的选择返回匿名类型:
.Select(param1 => new {
BrokerId = param1.Key,
TotalCommissionAmountBruto = param1.Sum(s => s.CommissionAmountBruto),
TotalCommissionAmountNeto = param1.Sum(s=>s.CommissionAmountNeto)
});
返回您的视图模型,您应该被设置为
.Select(param1 => new MyViewModel {
BrokerId = param1.Key,
TotalCommissionAmountBruto = param1.Sum(s => s.CommissionAmountBruto),
TotalCommissionAmountNeto = param1.Sum(s=>s.CommissionAmountNeto)
});
然后从以下位置更改操作的返回类型:
public IEnumerable<MyTable> Get...(int month, int year)
到
public IEnumerable<MyViewModel> Get...(int month, int year)
然后,在您的视图中,您还必须更改模型以使用新的视图模型。
奖金-
您应该考虑返回视图模型,而不是直接将数据库模型返回到视图。视图模型有很多好处:
防止大规模分配漏洞(能够发布超出您预期的用户发布能力的漏洞)。参见
可以为每个视图量身定制它们,以允许实现视图逻辑之类的东西,这些逻辑不在数据库模型中或仅特定于该视图。
它们促进了松散耦合,从而允许视图根据数据库模型的不同需求进行更改。
提问者添加内容以显示代码之前的原始答案
您可以在EF Core中使用分组和汇总功能。看看these docs中的LINQ GroupBy示例,这是一个基本示例。它比示例显示的要复杂得多。
var query = context.Orders
.GroupBy(o => new { o.CustomerId, o.EmployeeId })
.Select(g => new
{
g.Key.CustomerId,
g.Key.EmployeeId,
Sum = g.Sum(o => o.Amount),
Min = g.Min(o => o.Amount),
Max = g.Max(o => o.Amount),
Avg = g.Average(o => Amount)
});
以上是分组,然后使用一些聚合函数的基本思想。
如果您已为其编写了SQL并喜欢使用它,则还可以使用EF Core call raw SQL,这乍一看似乎太局限了,因为您必须将结果映射到实体(而您不希望这样做) ')。在2.1中,他们向名为own defined model的query types(您的虚拟实体,视图模型)添加了映射,并定义了查询。
在2.1中,您可以创建一个视图模型(您称为虚拟实体),将其添加到EF上下文中,然后可以使用数据库视图,另一个EF查询(defining query)和/对其进行查询。或匿名类型(有限制)。
例如:
给出视图模型:
public class MySpecialModel
{
public string Name { get; private set; }
public int Count { get; private set; }
}
您将其添加到您的上下文中:
public DbQuery<MySpecialModel> MySpecialModel {get;set;}
然后您将其称为:
var results = context.MySpecialModel.FromSql("select name,count from a join b on b.id=a.id)
如果由于某种原因这行不通或限制太多,我建议使用像dapper这样的微型ORM,它可以获取原始SQL并将其映射到模型。
您更细微的问题对您有好处吗?
简短的回答-可能但总是检查您的ORMS结果SQL并根据需要进行相应调整。
更长的答案-在不知道查询或您现有的EF Core逻辑的复杂性以及它生成的结果SQL以及您的上下文的情况下,它必须具有多少性能,多少用户,多少次被调用等。 ..,我们无法回答。