繁体   English   中英

如何删除 Entity Framework Core 中指定日期之前的记录,不包括最新的?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM