C# EF Core 3.1中间投影与迭代结果以设置附加属性
假设我有一个实体模型C# EF Core 3.1中间投影与迭代结果以设置附加属性,c#,sql-server,linq,ef-core-3.1,C#,Sql Server,Linq,Ef Core 3.1,假设我有一个实体模型 public class MyEntity { public DateTime TransactionDate {get; set;} public decimal TotalSales {get; set;} public long TotalPurchases {get; set;} } 我很容易地从SQLServerDB中填充一个该实体的列表,用于一系列事务日期 var results = await _dbContext.StoresDailyTran
public class MyEntity
{
public DateTime TransactionDate {get; set;}
public decimal TotalSales {get; set;}
public long TotalPurchases {get; set;}
}
我很容易地从SQLServerDB中填充一个该实体的列表,用于一系列事务日期
var results = await _dbContext.StoresDailyTransactions
.Where(t => t.TransactionDate > = rangeStartDate && t.TransactionDate <= rangeEndDate)
.GroupBy(o => o.TransactionDate)
.Select(g => new MyEntity
{
TransactionDate = g.Key,
TotalSales = g.Sum(c => c.Sales),
TotalPurchases = g.Sum(c => c.Purchases),
})
.DefaultIfEmpty()
.ToListAsync();
这很简单,因为我在查询中已经选择了值,只需计算平均值并将其分配给新的AverageSale属性
AverageSale = TotalSales / TotalPurchases
我考虑过两种不同的方法
1) 只需迭代之前生成的现有结果列表,并在返回结果之前设置新属性
foreach(MyEntity currentEntity in results)
{
currentEntity.AverageSales = currentEntity.TotalSales / currentEntity.TotalPurchases;
}
2) 在linq语句中,通过选择中间的anon投影,然后使用新的AverageSale对MyEntity进行最终投影,完成所有操作
var results = await _dbContext.StoresDailyTransactions
.Where(t => t.TransactionDate > = rangeStartDate && t.TransactionDate <= rangeEndDate)
.GroupBy(o => o.TransactionDate)
.Select(g => new
{
TransactionDate = g.Key,
TotalSales = g.Sum(c => c.Sales),
TotalPurchases = g.Sum(c => c.Purchases),
})
.Select(a => new
{
TransactionDate = a.TransactionDate,
TotalSales = a.TotalSales,
TotalPurchases = a.TotalPurchases,
AverageSale = a.TotalSales / a.TotalPurchases,
})
.DefaultIfEmpty()
.ToListAsync();
var results=await\u dbContext.StoresDailyTransactions
其中(t=>t.TransactionDate>=rangeStartDate和&t.TransactionDate o.TransactionDate)
.选择(g=>new
{
TransactionDate=g.键,
TotalSales=g.Sum(c=>c.Sales),
TotalPurchases=g.Sum(c=>c.Purchases),
})
.选择(a=>新建
{
TransactionDate=a.TransactionDate,
TotalSales=a.TotalSales,
TotalPurchases=a.TotalPurchases,
AverageSale=a.TotalSales/a.TotalPurchases,
})
.DefaultIfEmpty()
.ToListAsync();
第一个选项很容易阅读和理解正在发生的事情,但它有一种气味,它似乎很容易被粗心的开发人员打破,因为它与其他任何东西都是分开的。。。e、 g.在合并冲突中丢失,意外删除或注释掉
第二个选项似乎不太容易出错,因为它要么正常,要么不正常。虽然它看起来不太可读,并且需要一秒钟的时间来理解为什么它会被两个select语句背靠背地投影
有没有其他的东西可以让其中一个客观上更好,比如性能等,或者甚至是我没有考虑过的更好的方法
public class MyEntity
{
public DateTime TransactionDate { get; set; }
public decimal TotalSales { get; set; }
public long TotalPurchases { get; set; }
public decimal AverageSale => this.TotalSales / this.TotalPurchases;
}
然后,您的查询保持不变:
var results = await _dbContext.StoresDailyTransactions
.Where(t => t.TransactionDate >= rangeStartDate
&& t.TransactionDate <= rangeEndDate)
.GroupBy(o => o.TransactionDate)
.Select(g => new MyEntity
{
TransactionDate = g.Key,
TotalSales = g.Sum(c => c.Sales),
TotalPurchases = g.Sum(c => c.Purchases),
})
.DefaultIfEmpty()
.ToListAsync();
var results=await\u dbContext.StoresDailyTransactions
.其中(t=>t.TransactionDate>=rangeStartDate
&&t.交易日期o.交易日期)
.选择(g=>new MyEntity
{
TransactionDate=g.键,
TotalSales=g.Sum(c=>c.Sales),
TotalPurchases=g.Sum(c=>c.Purchases),
})
.DefaultIfEmpty()
.ToListAsync();
然后,您的查询保持不变:
var results = await _dbContext.StoresDailyTransactions
.Where(t => t.TransactionDate >= rangeStartDate
&& t.TransactionDate <= rangeEndDate)
.GroupBy(o => o.TransactionDate)
.Select(g => new MyEntity
{
TransactionDate = g.Key,
TotalSales = g.Sum(c => c.Sales),
TotalPurchases = g.Sum(c => c.Purchases),
})
.DefaultIfEmpty()
.ToListAsync();
var results=await\u dbContext.StoresDailyTransactions
.其中(t=>t.TransactionDate>=rangeStartDate
&&t.交易日期o.交易日期)
.选择(g=>new MyEntity
{
TransactionDate=g.键,
TotalSales=g.Sum(c=>c.Sales),
TotalPurchases=g.Sum(c=>c.Purchases),
})
.DefaultIfEmpty()
.ToListAsync();
我没有想到这一点,这是一个有趣的解决方案,只是表中实际上有一个AverageSale列。该列表示单个门店每天交易的平均销售额,为便于报告,该列需要为一组门店(智囊区)每天的平均销售额。对不起,我不认为这个细节是相关的,所以把它简化了。另外,我的公司有一个严格的标准,数据模型不能包含逻辑,这也有点排除了这种可能性。你是说你正在将查询结果投影到拥有自己表的真实实体模型吗?这听起来像是代码味道,MyEntity
应该是DTO/viewmodel它是数据库中的一个视图。视图中已存在名为AverageSale的列。该观点的结果被报道为该观点本身的一个DTO。我正在用不同的DTO生成视图的精简表示,并警告说,我的结果中的AverageSale是针对一组商店的,而不是像视图中AverageSale所表示的那个样针对单个日期的商店。我并没有想到这一点,这是一个有趣的解决方案,但实际上存在AverageSale表中的列。该列表示单个门店每天交易的平均销售额,为便于报告,该列需要为一组门店(智囊区)每天的平均销售额。对不起,我不认为这个细节是相关的,所以把它简化了。另外,我的公司有一个严格的标准,数据模型不能包含逻辑,这也有点排除了这种可能性。你是说你正在将查询结果投影到拥有自己表的真实实体模型吗?这听起来像是代码味道,MyEntity
应该是DTO/viewmodel它是数据库中的一个视图。视图中已存在名为AverageSale的列。该观点的结果被报道为该观点本身的一个DTO。我正在用不同的DTO生成视图的精简表示,并警告说,我的结果中的AverageSale是针对一组商店的,而不是像视图中AverageSale所表示的那个样针对单个日期的商店。我并没有想到这一点,这是一个有趣的解决方案,但实际上存在AverageSale表中的列。该列表示单个门店每天交易的平均销售额,为便于报告,该列需要为一组门店(智囊区)每天的平均销售额。对不起,我不认为这个细节是相关的,所以把它简化了。还有一个