我有这个“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},
...
]
这工作正常,但我有太多的 Reception
和 Item
,因此查询花费的时间太长...
所以我想通过向 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/