C# ion,但我想尝试一下,如果它确实存在这样的事情。@Koji不幸的是,没有这样的“等待时间”来配置,锁检测是自动的,并且在非谨慎的时间间隔内发生;当找到锁时,将在同一时刻引发异常。您可能可以尝试ROWLOCK优化器提示,但请注意,在某些情况下,它可能会导致

C# ion,但我想尝试一下,如果它确实存在这样的事情。@Koji不幸的是,没有这样的“等待时间”来配置,锁检测是自动的,并且在非谨慎的时间间隔内发生;当找到锁时,将在同一时刻引发异常。您可能可以尝试ROWLOCK优化器提示,但请注意,在某些情况下,它可能会导致,c#,entity-framework-core,database-deadlocks,C#,Entity Framework Core,Database Deadlocks,ion,但我想尝试一下,如果它确实存在这样的事情。@Koji不幸的是,没有这样的“等待时间”来配置,锁检测是自动的,并且在非谨慎的时间间隔内发生;当找到锁时,将在同一时刻引发异常。您可能可以尝试ROWLOCK优化器提示,但请注意,在某些情况下,它可能会导致性能下降。因此,手动锁在这里看起来是一个很好的解决方案,因为无论从哪一方使用它都无关紧要——C#代码还是数据库,在任何情况下都会使用锁。 public async Task DeleteAndUpsert(List<MyEntity>


ion,但我想尝试一下,如果它确实存在这样的事情。@Koji不幸的是,没有这样的“等待时间”来配置,锁检测是自动的,并且在非谨慎的时间间隔内发生;当找到锁时,将在同一时刻引发异常。您可能可以尝试
ROWLOCK
优化器提示,但请注意,在某些情况下,它可能会导致性能下降。因此,手动锁在这里看起来是一个很好的解决方案,因为无论从哪一方使用它都无关紧要——C#代码还是数据库,在任何情况下都会使用锁。
public async Task DeleteAndUpsert(List<MyEntity> entitiesToDelete, List<MyEntity> entitiesToUpsert)
{
    if (entitiesToDelete.Any())
        await myRepository.Delete(entitiesToDelete);

    if (entitiesToUpsert.Any())
        await myRepository.Upsert(entitiesToUpsert);
}


public override async Task Upsert(IList<MyEntity> entities)
{
    using (var dbContext = new MyDbContext(DbContextOptions, DbOptions))
    {
        using (var transaction = dbContext.Database.BeginTransaction())
        {
            await PurgeDataInChildTables(entities, dbContext);
            await dbContext.BulkInsertOrUpdateAsync(entities);
            // tables that depends on the parent table (FK_Key)
            await dbContext.BulkInsertOrUpdateAsync(entities.SelectMany<Child1>(x => x.Id).ToList());
            await dbContext.BulkInsertOrUpdateAsync(entities.SelectMany<Child2>(x => x.Id).ToList());
            await dbContext.BulkInsertOrUpdateAsync(entities.SelectMany<Child3>(x => x.Id).ToList());
            transaction.Commit();
        }
    }
}

public override async Task Delete(IList<MyEntity> entities)
{
    using (var dbContext = new MyDbContext(DbContextOptions, DbOptions))
    {
        using (var transaction = dbContext.Database.BeginTransaction())
        {
            await PurgeDataInChildTables(entities, dbContext);
            await dbContext.BulkDeleteAsync(entities);
            transaction.Commit();
        }
    }
}

private async Task PurgeDataInChildTables(IList<MyEntity> entities, MyDbContext dbContext)
{
    var ids = entities.Select(x => x.Id).ToList();

    await dbContext.Child1.Where(x => ids.Contains(x.Id)).BatchDeleteAsync();
    await dbContext.Child2.Where(x => ids.Contains(x.Id)).BatchDeleteAsync();
    await dbContext.Child3.Where(x => ids.Contains(x.Id)).BatchDeleteAsync();
}
public override async Task Upsert(IList<MyEntity> entities)
{
    using (var dbContext = new MyDbContext(DbContextOptions, DbOptions))
    {
        await PurgeDataInChildTables(entities, dbContext);
        await dbContext.BulkInsertOrUpdateAsync(entities);
        // tables that depends on the parent table (FK_Key)
        await dbContext.BulkInsertOrUpdateAsync(entities.SelectMany(x => x.Child1).ToList());
        await dbContext.BulkInsertOrUpdateAsync(entities.SelectMany(x => x.Child2).ToList());
        await dbContext.BulkInsertOrUpdateAsync(entities.SelectMany(x => x.Child3).ToList());
        await dbContext.SaveChangesAsync();
    }
}

public override async Task Delete(IList<MyEntity> entities)
{
    using (var dbContext = new MyDbContext(DbContextOptions, DbOptions))
    {
        await PurgeDataInChildTables(entities, dbContext);
        await dbContext.BulkDeleteAsync(entities);
        await dbContext.SaveChangesAsync();
    }
}