diff --git a/src/food-market.infrastructure/Integrations/MoySklad/MoySkladImportService.cs b/src/food-market.infrastructure/Integrations/MoySklad/MoySkladImportService.cs index 368607a..e12e79f 100644 --- a/src/food-market.infrastructure/Integrations/MoySklad/MoySkladImportService.cs +++ b/src/food-market.infrastructure/Integrations/MoySklad/MoySkladImportService.cs @@ -538,13 +538,19 @@ await foreach (var p in _client.StreamProductsAsync(token, ct, includeArchived: } catch (Exception ex) { - _log.LogWarning(ex, "Failed to import MoySklad product {Name}", p.Name); - errors.Add($"{p.Name}: {ex.Message}"); + // ВАЖНО: очищаем ChangeTracker, иначе неудачный батч-SaveChanges оставляет + // «отравленные» сущности и КАЖДЫЙ следующий SaveChanges падает каскадом + // (теряется весь прогон). Теперь сбой одного товара не роняет остальные. + _db.ChangeTracker.Clear(); + var inner = ex.InnerException?.Message ?? ex.Message; + _log.LogWarning(ex, "Failed to import MoySklad product {Name}: {Inner}", p.Name, inner); + errors.Add($"{p.Name}: {inner}"); if (progress is not null) progress.Errors = errors; } } - await _db.SaveChangesAsync(ct); + try { await _db.SaveChangesAsync(ct); } + catch (Exception ex) { _db.ChangeTracker.Clear(); _log.LogWarning(ex, "Final products SaveChanges failed: {Inner}", ex.InnerException?.Message ?? ex.Message); } // Финальная проверка дубликатов штрихкодов (на всякий, если // уникальный индекс был нарушен исторически).