Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF Core 3.1中间投影与迭代结果以设置附加属性_C#_Sql Server_Linq_Ef Core 3.1 - Fatal编程技术网

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表中的列。该列表示单个门店每天交易的平均销售额,为便于报告,该列需要为一组门店(智囊区)每天的平均销售额。对不起,我不认为这个细节是相关的,所以把它简化了。还有一个