Dapper - insert danych powoduje deadlock

0

Witam.
Mam panel w Angularze + ASP .NET Core 3.0 za pomocą którego dodaje się dokumenty. Mam możliwość dodawania dwóch typów dokumentów RO (Rezerwacja odbiorcy) oraz FPF (Faktura Pro Forma). W przypadku dodawania FPF, problemu nie ma, wszystkie pozycje są poprawnie dodane, ale w przypadku RO dostaje deadlocki... Metoda dodawania dokumentów ta sama.

Czy może mi ktoś wyjaśnić jakim cudem insert danych dapperem powoduje deadlock? Czy jestem w stanie coś z tym zrobić, jakiś timer, thread.sleep? Nie rozumiem dlaczego akurat teraz mam takie problemy.

0

Pokaż kod. Może masz jakiś trigger, który to powoduje.

0
        public void SaveTraNag(TraNag trn)
        {
            try
            {
                int id = _sqlService.InsertTraNag(trn).Result;
                for (int i = 0; i < trn.Pozycje.Count; i++)
                {
                    TraElem tre = trn.Pozycje[i];
                    tre.TrE_TrNId = id;
                    _sqlService.InsertTraElem(tre); 
// W tym miejscu dostaje deadlocki, ponieważ mam tylko jedną pozycje na dokumencie, zawsze tylko pierwszą.
                }

                for (int i = 0; i < trn.VAT.Count; i++)
                {
                    TraVAT trv = trn.VAT[i];
                    trv.TrV_TrNid = id;
                    _sqlService.InsertTraVAT(trv);
                }
            }
            catch(Exception ex)
            {
                _loggerManager.Error(ex);
            }
        }
        public async Task<int> InsertTraElem(TraElem tre)
        {
            using (IDbConnection db = new SqlConnection(CompanyConnectionString()))
            {
                return await db.InsertAsync(tre);
            }
        }
3

Ok kilka wdechów i jedziemy.

Za każdym razem otwierasz asycnhronicznie połączenie do bazy (czemu ?) w InsertTraElem. Nie czakasz na wstawienie tych elementów _sqlService.InsertTraVAT(trv) nie ma awaita (napisałbym że nie ma .Result ale przez palce mi to nie przejdzie) więc problem leży tutaj.

Błagam poczytaj o kolekcjach, asynchroniczności, łapaniu wyjątków, nazwach zmiennych, łączeniu się z bazą. Tutaj ani jedna linijka nie jest zgodna ze sztuka i konwencjami w .NET

Kod jest zły, bardzo zły...

Przemyśl sobie cała strukturę bo to naprawde powinno wyglądac inaczej. Zakładam że wywołujesz to w kontrolerze - jeśli tak to nie widze powodu żeby nie ciagnąc asynychronicznych wywołan aż do kontrolera - .Result to najgrosze co można tu zrobić. Nie otwieraj poaćzenia za każdym razem w pętli for - otwieraj jedno na całą metodę.

0

Co mam wyczytać z tych kolekcji, asynchroniczności, łapania wyjątków, nazwach zmiennych, łączeniu z bazą? Czego mi brakuje? Dlaczego nazwy zmiennych dla ciebie są złe? Co jest złego w łapaniu wyjątków i co jest złego z kolekcjami? Ok, z połączeniem do bazy masz rację, ale to proszę o jakąś propozycję, jak mniej więcej to poprawić, co zmienić, gdzie ?

2

Bardzo na szybko:

public async Task SaveTransaction(TraNag trn)
{
//nie łap wyjatków tutaj skro nic sensownego z nimi nie robisz - logowanie powino byc w moddleware Asp.NET

using(var connection=...)//otwieramy połaczenie
//pomyśl o transakcji bazodanowej bo teraz to operacja na otwartym sercu
{
     int id = await _sqlService.InsertTraNag(trn,connection)
     foreach(var tre in trn.Pozycje)
     {
            tre.TrE_TrNId = id;
            await sqlService.InsertTraElem(tre, connection)
     }
//reszta podobnie
}

}

To co podałem nadal nie jest dobrym kodem - wszytskie elementy powinno się wstawiać w paczkkach po kilka (wsyztskie na raz)
Nazwy zmiennych to już inna bajka - po co takie skróty i czemu po polsku.

1

Ja jeszcze bym dodał że enigmatyczne nazywanie zmiennych nie jest "cool", serio. To praktyka stosowana 20 lat temu i dziś jeszcze przez niektórych hinduskich programistów. Zmienne powinny mieć czytelne, jasno określające ich rolę nazwy. To samo tyczy się typów. No bo czym jest TraNag dla postronnego czytelnika? Mi nic to nie mówi. Z kontekstu domyślam się że to coś związanego z transakcjami, ale kod w którym trzeba się czegoś domyślać to zły kod. Nie ma naprawdę nic złego w długiej nazwie jeśli dobrze odzwierciedla ona przeznaczenie zmiennej/typu.

trv.TrV_TrNid

To już w ogóle czarna magia. Pomijam podkreślnik w nazwie właściwości...

0

Dlaczego zakładasz, że nic sensownego z nim nie robię. Właśnie dzięki temu wyjątkowi wiem, że mam błąd w dodawaniu do bazy i deadlocki. Mój middleware rzuca błędem ale to nie jest kwestia tego wątku i ten błąd nic mi nie mówił. Klient zgłasza, że podczas testów dodaje się tylko jedna pozycja do dokumentu więc drążę temat. Nie mam zamiaru tracić czasu i poprawiać go tylko po to, aby poprawnie wrzucić na forum.

Jedni twierdzą, że wszystko co związane z SQL ma być w osobnym serwisie, ty twierdzisz, że obiekt połączenia mam tworzyć w poszczególnych serwisach i w parametrach go przekazywać. Każdy piszę inaczej, a ja trace czas i się próbuje do "każdego" dostosować. Problem jest taki, że mam deadlocki, a nie "brzydki" kod.

0

Problem jest taki, że mam deadlocki, a nie "brzydki" kod.

To nie jest brzydki kod, to jest zły kod, który powoduje deadlocki.
A co robisz z tym wyjątkiem ? W jakis sposób go obsługujesz, próbujesz załagodzić jego skutki ?

Czekaj czekaj ? To jest kod produkcyyjny ? Ktoś tego używa ?

0

Tak, to jest kod produkcyjny, ktoś tego używa. Teraz właśnie próbuję coś zrobić z tym co zwrócił mi wyjątek

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0