c# - 提高性能但需要维护的计算字段 (EF)

标签 c# sql-server performance entity-framework

我有这个“1 到 N”模型:

class Reception
{
    public int ReceptionId { get; set; }
    public string Code { get; set; }
    public virtual List<Item> Items { get; set; }
}

class Item
{
    public int ItemId { get; set; }
    public string Code { get; set; }
    public int Quantity { get; set; }
    public int ReceptionId { get; set; }
    public virtual Reception Reception { get; set; }
}

而这个 Action ,api/receptions/list

public JsonResult List() 
{
     return dbContext.Receptions
        .Select(e => new 
         {
             code = e.Code,
             itemsCount = e.Items.Count,
             quantity = e.Items.Sum(i => i.Quantity)

         }).ToList();
}

它返回一个接收列表,以及它们的项目数:

[
    {code:"1231",itemsCount:10,quantity:30},
    {code:"1232",itemsCount:5,quantity:70},
    {code:"1234",itemsCount:30,quantity:600},
    ...
]

这工作正常,但我有太多的 ReceptionItem,因此查询花费的时间太长...

所以我想通过向 Reception 添加一些持久字段来加快速度:

class Reception
{
    public int ReceptionId { get; set; }
    public string Code { get; set; }
    public virtual List<Item> Items { get; set; }
    public int ItemsCount { get; set; } // Persisted
    public int Quantity { get; set; } // Persisted
}

有了这个改变,查询最终变成了这样:

public JsonResult List() 
{
     return dbContext.Receptions
        .Select(e => new 
         {
             code = e.Code,
             itemsCount = e.ItemsCount,
             quantity = e.Quantity

         }).ToList();
}

我的问题是:
维护这两个字段的最佳方法是什么?
我会提高性能,但现在我需要更加小心地创建 Item

如今,可以创建、编辑和删除 Item:

  • api/items/create?receptionId=...
  • api/items/edit?itemId=...
  • api/items/delete?itemId=...

我还有一个通过 Excel 导入接收的工具:

  • api/items/createBulk?...

也许明天我会有更多创建Item 的方法,所以问题是我如何确保这两个新字段ItemsCount数量 总是最新的?

我应该像这样在 Reception 中创建一个方法吗?

class Reception
{
    ...

    public void UpdateMaintainedFields() 
    {
        this.Quantity = this.Items.Sum(e => e.Quantity);
        this.ItemsCount = this.Items.Count();
    }
}    

然后记得从所有以前的 URL 调用它? (items/create, items/edit, ...)

或者也许我应该在数据库中有一个存储过程?

常见的做法是什么?我知道有 calculated columns 但它们指的是同一类的字段。还有 indexed views,但我不确定它们是否适用于这样的场景。

最佳答案

从你的代码来看,在我看来你没有业务逻辑层,所有的东西都在 Controller 中实现,这给你带来了问题,当你有不同的方式时(看起来,你意味着不同的 Controller )你必须重新实现这个逻辑而且很容易忘记,如果你不忘记,你可能会忘记以后维护。

所以我建议为业务逻辑(如添加新项目)创建一个层,并在您要创建项目的 Controller 中使用它。

我还建议按照您的要求编写函数 UpdateMaintainedFields,但在添加项目后在业务逻辑层调用它,而不是在 Controller 中调用它!

如果你能接受不能编写单元测试,你也可以在数据库上编写逻辑(触发器)。

关于c# - 提高性能但需要维护的计算字段 (EF),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43621537/

相关文章:

c# - 什么都不抛出时的异常效率

javascript - 避免从其他网站加载我的 js/css 文件

c# - Linq to Mongodb动态更新功能

c# - 对于 Silverlight 4 Visual Studio 解决方案,版本控制需要什么?

c# - 如何使用ssis搜索文件系统中的文件夹并将其移动到目标文件系统?

c# - 从 .NET SqlCommand 调用时 SQL Server 批量插入失败

c# - Windows Azure 每天创建表

c# - 通过反射调用带有参数的泛型方法时,无法将 System.Int32 类型的对象转换为 System.Object[]

sql - 如何在多个数据库表上创建单个触发器

Java并行序列化和压缩