【发布时间】:2017-04-25 21:47:46
【问题描述】:
我有这个“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; }
}
还有这个动作,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's
今天可以创建、编辑和删除Item:
api/items/create?receptionId=...api/items/edit?itemId=...api/items/delete?itemId=...
我还有一个通过 Excel 导入接收的工具:
api/items/createBulk?...
也许明天我会有更多创建Item 的方法,所以问题是我如何确保ItemsCount 和Quantity 这两个新字段始终是最新的?
我应该像这样在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,但我不确定它们是否适用于这样的场景。
【问题讨论】:
-
您可能想要查看 EF 正在生成的查询,并查看它为这些查询执行的查询计划是什么。您也许可以继续使用当前的方法,但您只需要添加适当的一两个索引。
-
我很难想到这不会是高效的。你看过 SQL 探查器吗?您是否碰巧发出多个查询?这怎么可能编译?列表不能与 ActionResult 争吵......
-
当前方法已经被很好的索引(列有索引
ReceptionId,表Items)
标签: c# sql-server performance entity-framework