[英]How do I delete records before a specified date in Entity Framework Core excluding the latest?
如何在 Entity Framework Core 中删除除最新股票记录之外的所有在特定日期之前创建的记录。 我无法弄清楚所需的 LINQ 查询,但已经设法将 SQL 放在一起应该可以完成这项工作:
--
-- Parameters.
--
DECLARE @PurgeDate DATETIME = DATEADD(day, -7, GETDATE());
DECLARE @RegionId INT = 28;
DECLARE @StockCodes TABLE(
StockCode NVARCHAR(10)
);
-- Could be a significant number
INSERT INTO @StockCodes VALUES ('ABC123'), ('DEF123') /* etc... */;
--
-- Get stock records that are newer than the purge date or the latest record if not.
-- This ensures there is always at least one stock record for a stock code.
--
WITH LatestStockRecords
AS
(
SELECT s.*, [RowNumber] = ROW_NUMBER() OVER (PARTITION BY s.[StockCode] ORDER BY s.[CreatedAt] DESC)
FROM StockRecords AS s
INNER JOIN Locations AS l
ON s.[LocationId] = l.[Id]
WHERE l.[RegionId] = @RegionId
AND s.[StockCode] IN (SELECT * FROM @StockCodes)
)
SELECT *.[Id]
INTO #_STOCK_RECORD_IDS
FROM LatestStockRecords
WHERE [CreatedAt] >= @PurgeDate
OR [RowNumber] = 1;
--
-- Delete the stock records that do not appear in the latest stock records temporary table.
--
DELETE s
FROM StockRecords AS s
INNER JOIN Locations AS l
ON s.[LocationId] = l.[Id]
WHERE l.[RegionId] = @RegionId
AND s.[StockCode] IN (SELECT * FROM @StockCodes)
AND s.[Id] NOT IN (SELECT * FROM #_STOCK_RECORD_IDS);
可能有大量记录要删除,因此需要考虑性能。
编辑:删除 DbContext 和实体,因为我认为它们与问题无关。
这就是我最终解决问题的方法。 我不得不强制评估分组查询,因为此时 Entity Framework Core 似乎不支持必要的查询。
var regionId = 28;
var stockCodes = new string[] { "ABC123", "DEF123" /* etc... */ };
var purgeDate = DateTime.UtcNow.AddDays(-NumberOfDaysToPurge);
bool IsPurgeable(StockRecord stockRecord)
{
return stockRecord.CreatedAt >= purgeDate;
}
var latestStockRecordIds = context.StockRecords
.Where(stockRecord =>
stockRecord.Location.RegionId == regionId
&& stockCodes.Contains(stockRecord.StockCode))
.AsEnumerable() // <-- force execution
.GroupBy(stockRecord => stockRecord.StockCode)
.SelectMany(group =>
{
var orderedStockRecords = group.OrderByDescending(stockRecord => stockRecord.CreatedAt);
var stockRecords = orderedStockRecords.Count(IsPurgeable) > 0
? orderedStockRecords.Where(IsPurgeable)
: orderedStockRecords.Take(1);
return stockRecords.Select(stockRecord => stockRecord.Id);
});
var stockRecordsToRemove = await context.StockRecords
.Where(stockRecord =>
stockRecord.Location.RegionId == regionId
&& StockCodeCodes.Contains(stockRecord.StockCode)
&& stockRecord.CreatedAt <= purgeDate
&& !latestStockRecordIds.Contains(stockRecord.Id))
.ToListAsync();
context.ChangeTracker.AutoDetectChangesEnabled = false;
context.StockRecords.RemoveRange(stockRecordsToRemove);
await context.SaveChangesAsync();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.