C# 实体框架-从子记录计算总和字段

C# 实体框架-从子记录计算总和字段,c#,asp.net,asp.net-mvc,entity-framework,entity-framework-core,C#,Asp.net,Asp.net Mvc,Entity Framework,Entity Framework Core,我使用的是实体框架核心和ASP.NET核心,代码优先 在我的应用程序中,我有发票,具有典型的InvoiceHeader->InvoiceLine关系。InvoiceLine实体有一个LineAmount字段,当显示为列表时,我希望将其相加并显示在InvoiceHeader上(这样我可以在查看发票列表时看到发票总额) 我猜我需要在InvoiceHeader实体中添加一个TotalAmount属性,带有注释[NotMapped]。但是如何最有效地填充它呢 目前我的InvoiceHeaderContr

我使用的是实体框架核心和ASP.NET核心,代码优先

在我的应用程序中,我有发票,具有典型的
InvoiceHeader
->
InvoiceLine
关系。
InvoiceLine
实体有一个
LineAmount
字段,当显示为列表时,我希望将其相加并显示在
InvoiceHeader
上(这样我可以在查看发票列表时看到发票总额)

我猜我需要在
InvoiceHeader
实体中添加一个
TotalAmount
属性,带有注释
[NotMapped]
。但是如何最有效地填充它呢

目前我的
InvoiceHeaderController.Index()
是:

    // GET: InvoiceHeaders
    public async Task<IActionResult> Index()
    {
        ApplicationUser appUser = ConstantData.GetApplicationUser(_context, _userManager.GetUserId(User));
        var applicationDbContext = _context.InvoiceHeader.Include(i => i.Customer).Include(i => i.CustomerBranch)
            .Where(i => i.CustomerID == appUser.CustomerID);
        return View(await applicationDbContext.ToListAsync());
    }
//获取:InvoiceHeaders
公共异步任务索引()
{
ApplicationUser appUser=ConstantData.GetApplicationUser(_context,_userManager.GetUserId(User));
var applicationDbContext=\u context.InvoiceHeader.Include(i=>i.Customer).Include(i=>i.CustomerBranch)
.Where(i=>i.CustomerID==appUser.CustomerID);
返回视图(等待applicationDbContext.toListSync());
}
有谁能告诉我计算(和)这个
TotalAmount
属性最有效的方法是什么


谢谢。

选择sum作为单独字段,您需要创建新的模型类,如下所示

public class InvoiceHeaderModel{
   public InvoiceHeader invoiceHeader{get;set;}
   public decimal TotalAmount {get;set;}
}
并在行动上做出改变

// GET: InvoiceHeaders
public async Task<IActionResult> Index()
{
    ApplicationUser appUser = ConstantData.GetApplicationUser(_context, _userManager.GetUserId(User));
    var applicationDbContext =await _context.InvoiceHeader.Where(i =>i.CustomerID == appUser.CustomerID).ToListAsync();
    var data = applicationDbContext.Aggregate( new List<InvoiceHeaderModel>(),(invoiceHeaderModellist, it)=>{ invoiceHeaderModellist.Add(new InvoiceHeaderModel(){ InvoiceHeader =it,TotalAmount  = it.InvoiceLine.Sum(t=>t.LineAmount)}); return invoiceHeaderModellist;});
    return View(data);
}
//获取:InvoiceHeaders
公共异步任务索引()
{
ApplicationUser appUser=ConstantData.GetApplicationUser(_context,_userManager.GetUserId(User));
var applicationDbContext=await _context.InvoiceHeader.Where(i=>i.CustomerID==appUser.CustomerID.toListSync();
var data=applicationDbContext.Aggregate(new List(),(invoiceHeaderModellist,it)=>{invoiceHeaderModellist.Add(new InvoiceHeaderModel(){InvoiceHeader=it,TotalAmount=it.InvoiceLine.Sum(t=>t.LineAmount)});返回invoiceHeaderModellist;});
返回视图(数据);
}

在这个操作中,我认为您不需要包括“include(i=>i.Customer)。include(i=>i.CustomerBranch)”,如果需要,您可以在where closure之前添加。

选择sum作为单独的字段,您需要创建新的模型类,如下所示

public class InvoiceHeaderModel{
   public InvoiceHeader invoiceHeader{get;set;}
   public decimal TotalAmount {get;set;}
}
并在行动上做出改变

// GET: InvoiceHeaders
public async Task<IActionResult> Index()
{
    ApplicationUser appUser = ConstantData.GetApplicationUser(_context, _userManager.GetUserId(User));
    var applicationDbContext =await _context.InvoiceHeader.Where(i =>i.CustomerID == appUser.CustomerID).ToListAsync();
    var data = applicationDbContext.Aggregate( new List<InvoiceHeaderModel>(),(invoiceHeaderModellist, it)=>{ invoiceHeaderModellist.Add(new InvoiceHeaderModel(){ InvoiceHeader =it,TotalAmount  = it.InvoiceLine.Sum(t=>t.LineAmount)}); return invoiceHeaderModellist;});
    return View(data);
}
//获取:InvoiceHeaders
公共异步任务索引()
{
ApplicationUser appUser=ConstantData.GetApplicationUser(_context,_userManager.GetUserId(User));
var applicationDbContext=await _context.InvoiceHeader.Where(i=>i.CustomerID==appUser.CustomerID.toListSync();
var data=applicationDbContext.Aggregate(new List(),(invoiceHeaderModellist,it)=>{invoiceHeaderModellist.Add(new InvoiceHeaderModel(){InvoiceHeader=it,TotalAmount=it.InvoiceLine.Sum(t=>t.LineAmount)});返回invoiceHeaderModellist;});
返回视图(数据);
}

在这个操作中,我认为您不需要包括“include(i=>i.Customer).include(i=>i.CustomerBranch)”,如果需要,您可以在where closure之前添加。

我设法解决了这个问题。萨尼什的建议很接近,但不是我想要的

我最终使用的代码是:

// GET: InvoiceHeaders

public async Task<IActionResult> Index()
{
    ApplicationUser appUser = ConstantData.GetApplicationUser(_context, _userManager.GetUserId(User));
            var applicationDbContext = _context.InvoiceHeader.Include(i => i.Customer).Include(i => i.CustomerBranch)
                .Where(i => i.CustomerID == appUser.CustomerID)
                .Select(i => new InvoiceListViewModel
                {
                    invoiceHeader = i,
                    TotalAmount = i.InvoiceLines.Sum(t => t.LineAmount)
                });
    return View(await applicationDbContext.ToListAsync());
}
//获取:InvoiceHeaders
公共异步任务索引()
{
ApplicationUser appUser=ConstantData.GetApplicationUser(_context,_userManager.GetUserId(User));
var applicationDbContext=\u context.InvoiceHeader.Include(i=>i.Customer).Include(i=>i.CustomerBranch)
.Where(i=>i.CustomerID==appUser.CustomerID)
.选择(i=>new InvoiceListViewModel
{
invoiceHeader=i,
TotalAmount=i.InvoiceLines.Sum(t=>t.LineAmount)
});
返回视图(等待applicationDbContext.toListSync());
}

谢谢你的帮助,萨尼什。

我设法解决了。萨尼什的建议很接近,但不是我想要的

我最终使用的代码是:

// GET: InvoiceHeaders

public async Task<IActionResult> Index()
{
    ApplicationUser appUser = ConstantData.GetApplicationUser(_context, _userManager.GetUserId(User));
            var applicationDbContext = _context.InvoiceHeader.Include(i => i.Customer).Include(i => i.CustomerBranch)
                .Where(i => i.CustomerID == appUser.CustomerID)
                .Select(i => new InvoiceListViewModel
                {
                    invoiceHeader = i,
                    TotalAmount = i.InvoiceLines.Sum(t => t.LineAmount)
                });
    return View(await applicationDbContext.ToListAsync());
}
//获取:InvoiceHeaders
公共异步任务索引()
{
ApplicationUser appUser=ConstantData.GetApplicationUser(_context,_userManager.GetUserId(User));
var applicationDbContext=\u context.InvoiceHeader.Include(i=>i.Customer).Include(i=>i.CustomerBranch)
.Where(i=>i.CustomerID==appUser.CustomerID)
.选择(i=>new InvoiceListViewModel
{
invoiceHeader=i,
TotalAmount=i.InvoiceLines.Sum(t=>t.LineAmount)
});
返回视图(等待applicationDbContext.toListSync());
}

感谢您的帮助,Saneesh。

您的数据模型不应包含该属性。对其使用视图模型。您只需使用linq
.Sum()
即可获得总额。您在InvoiceLine中有行金额字段,并且InvoiceHeader中已经有一个CustomerID字段。您必须在Invoiceheader控制器中按客户填写行金额的总和,对吗?@StephenMuecke:实际上,这取决于具体情况。有时,预先计算总金额并将其存储在“标题”中是很有用的—当您不需要详细信息时,检索速度更快。有时,这可用于验证数据完整性(某种审计)。当然,这也有它自己的缺点。@Saneeshkunjunni:CustomerID在这里并不重要。这只是这张发票的客户ID。一个客户可以有多张发票,在这种情况下,一个客户的每张发票都有不同的发票total@StephenMuecke:谢谢。我试试看。你的数据模型不应该包含那个属性。对其使用视图模型。您只需使用linq
.Sum()
即可获得总额。您在InvoiceLine中有行金额字段,并且InvoiceHeader中已经有一个CustomerID字段。您必须在Invoiceheader控制器中按客户填写行金额的总和,对吗?@StephenMuecke:实际上,这取决于具体情况。有时,预先计算总金额并将其存储在“标题”中是很有用的—当您不需要详细信息时,检索速度更快。有时这可能