提问人:Liturghian Pope 提问时间:10/8/2023 最后编辑:marc_sLiturghian Pope 更新时间:10/10/2023 访问量:64
将内存中列表与数据库列表进行比较的有效方法
Efficient way to compare in-memory list with database list
问:
使用 .NET 6 和 Entity Framework,我正在尝试一种有效的方法来查找和标记数据库中记录之间的差异,基于复合键。考虑使用由 ID 和 Year 组成的复合主键的此类。
class Building
{
public int ID { get; set; }
public int Year { get; set; }
public string Name { get; set; }
public double Size { get; set; }
public decimal LastSalePrice { get; set; }
}
我在内存中检索了所有年份为 == 2022 的建筑物,现在我需要将列表中的所有建筑物与具有 2021 年份的建筑物进行比较并标记差异。
在我看来,有两种方式:
- 需要另一个类来保存标志(这可能不是最好的方法,因为构建列表和更改标志都需要发送到前端,这需要一个额外的类来将所有信息放在一起)
- 通过添加 'NameChanged'、'SizeChanged'、'LastSalePriceChanged' 布尔值来标记差异来修改构建类
我的目标是避免检索 2021 年的建筑物列表,然后在内存中执行逐项比较。相反,我正在寻找一种在数据库级别运行的解决方案,以干净地标记差异。例如,如果建筑物在 2022 年存在,但在 2021 年不存在,则所有标志都应设置为“true”。
我对性能和资源使用方面的最有效方法感兴趣,并避免不必要的数据检索。
谢谢!
PS:我尝试检索年份为“2021”的建筑物列表并比较每个建筑物 ID,但它非常冗长,并且是一个“面向业务逻辑”的解决方案。这不是我想要的“干净的、面向数据层的”解决方案。
答:
如果每个年份的 ID 相同,并且复合唯一键是 ID 和年份的组合,则可以使用自联接:
var differingBuildings = await context.Buildings
.Join(context.Buildings.DefaultIfEmpty(), b1 => b1.Id, b2 => b2.Id,
(b1, b2) => new { BuildingYear1 = b1, BuildingYear2 = b2 })
.Where(x => x.BuildingYear1.Year = year1
&& x.BuildingYear2.Year = year2
&& (x.BuildingYear1.Name != x.BuildingYear2.Name
|| x.BuildingYear1.Size != x.BuildingYear2.Size
|| x.BuildingYear1.LastSalePrice != x.BuildingYear2.LastSalePrice))
.Select(x => new
{
x.BuildingYear2.Id,
x.BuildingYear2.Year,
NameChanged = x.BuildingYear1 == null || x.BuildingYear1.Name != x.BuildingYear2.Name,
SizeChanged = x.BuildingYear1 == null || x.BuildingYear1.Size != x.BuildingYear2.Size,
LastSalePriceChanged = x.BuildingYear1 == null || x.BuildingYear1.LastSalePrice != x.BuildingYear2.LastSalePrice
}).ToListAsync();
这将返回名称、大小或销售价格不同的任何建筑物两年,以及最近(假设第 2 年>第 1 年)年份和值更改的标志。这可能不是一个特别高性能的查询,因此根据数据量,简单地将两年的所有建筑物(或基于 ID 的建筑物集)加载到内存中并在那里进行比较可能会更有效。
如果 Year2 表示您在内存中更新的数据,那么我只需将 Year 1 加载到内存中并进行比较。试图将所有建筑物的数据反馈给 SQL 以实现某种形式的连接(如上所述)是没有意义的。获取上一年的数据并在内存中进行比较。如果您有更新的 ID 子集,则可以使用该集按 ID 获取等效的建筑物。
评论
year2
year1
b1 => new { b1.Id, b1.Year }, b2 => new { b2.Id, Year = b2.Year-1 }
Where
year1
|| x == null
评论