Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C#] Dapper, Task en SqlTransaction-combinatie gaat fout

Pagina: 1
Acties:

  • Xanland
  • Registratie: Oktober 2007
  • Laatst online: 00:04
Geachte heren van GoT,

Samen met mijn stagebegeleider (van het bedrijf) loop ik al een aantal tegen een probleem aan met betrekking tot de combinatie Dapper, Task's en SqlTransaction's.

Het probleem is als volgt (bij de UnitTests): Als eerst worden er via drie methodes ondere andere eerst twee insert-query's uitgevoerd. Vervolgens worden op die twee ingevoegde items een update uitgevoerd. Dit gebeurt allemaal met behulp van de SqlTransaction en Dapper.
Daarna moeten deze rijen verder worden verwerkt wat asynchroon gebeurt met behulp van een Task. In deze task wordt ook weer via een SqlTransaction (met als IsolationLevel ReadCommited) een update met een query uitgevoerd.

Het gebeuren van het uitvoeren van de query gebeurt met de volgende "boilerplate":
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
try {
    SqlConnection conn = new SqlConnection(...);
    conn.Open ();
    
    string transName = "x";
    SqlTransaction sqlTrans = conn.BeginTransaction(transName);
    string sqlQry = "insert/update/select";
    try
    {
        conn.Query <type> (sqlQry, <object met waarden voor query>, sqlTrans);
        sqlTrans.Commit ();
    }
    catch (Exception ex)
    {
        sqlTrans.Rollback (transName);
    }
    finally
    {
        sqlTrans.Dispose();
    }
}
catch (Exception exc)
{
    throw;
}


Het probleem ligt er nu bij dat er iets fout gaat bij de taak. Alle query's van de eerste drie methodes worden correct uitgevoerd en kloppen ook als ik een select uitvoer op de betreffende tabellen.

Hierna wordt de Task afgevuurd. Dit bestaat uit twee methodes:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
public Task<Result_Rb> startTask (int b, string d)
{
    return Task.Factory.StartNew<Result_Rb>(OtherMethodOfSameClass, new 
    {
        a = b,
       c = d
    });
}

private Result_rb OtherMethodOfSameClass (dynamic bla) {
    // met o.a. inhoud van bovengenoemde boilerplate
    // let wel mbt SqlTransaction -> SqlTransaction sqlTrans = conn.BeginTransaction(System.Data.IsolationLevel.ReadCommitted, transName);
}


Ondanks het feit dat die andere drie methodes eerst worden uitgevoerd en dan deze task, wordt er niks gedaan met de al ingeschoten rijen. Dit zou wel moeten aangezien ze wel aan de where, waar de task op basis van update, voldoen.

De casussen waar het wel lukt zijn als volgt:
1. Eerst die drie methodes uitvoeren. Na even wachten die taak uitvoeren. (dus zeg maar als twee aparte unittests)
2. Alles in 1 unittest, maar met een breakpoint op de return. Wel even een aantal seconden wachten voordat je verder gaat bij de breakpoint.

Zijn er toevallig hier knappe koppen die hier iets op weten? Want het zou gewoon in één unit test moeten kunnen naar onze mening.

RobIII: Ik probeer als ik wil stoppen met mijn auto ook altijd de sigarettenaansteker, de airco, 3 radioknoppen en de binnenverlichting en dan de rem :P


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Xanland schreef op woensdag 15 januari 2014 @ 09:01:
Het probleem ligt er nu bij dat er iets fout gaat bij de taak. Alle query's van de eerste drie methodes worden correct uitgevoerd en kloppen ook als ik een select uitvoer op de betreffende tabellen.
Wat is "Iets"? Komt er een exception, wordt de query niet goed uitgevoerd?

Kijk bijvoorbeeld eens of de query wel daadwerkelijk uitgevoerd worden in je SQL server.

[ Voor 10% gewijzigd door Woy op 15-01-2014 09:11 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Xanland
  • Registratie: Oktober 2007
  • Laatst online: 00:04
Woops, sorry.

Dat iets is in dit geval onduidelijk, als ik gewoon run test doe (dus zoals 2, maar dan ZONDER breakpoints) dan lijkt alles goed te gaan. Zelfs met een try-catch waarbij ik een AggregateException 'flatten" dan komt er he-le-maal niks.

RobIII: Ik probeer als ik wil stoppen met mijn auto ook altijd de sigarettenaansteker, de airco, 3 radioknoppen en de binnenverlichting en dan de rem :P


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik zou zeggen, voeg eens wat meer logging toe. Met breakpoints debuggen is niet altijd de beste manier, zeker niet met multithreading.

Tevens zou ik gewoon eens de SQL Server monitor aanzetten, om te kijken wat er aan die kant daadwerkelijk gebeurt.

Laat ook eens je Unit test zien de daadwerkelijk fout gaat?

[ Voor 11% gewijzigd door Woy op 15-01-2014 09:40 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Haan
  • Registratie: Februari 2004
  • Laatst online: 22-11 15:31

Haan

dotnetter

Unit testen met een live database verbinding is sowieso niet echt een best practice, daarvoor gebruik je in de regel iets van statische data (een in-memory List bijvoorbeeld). Feitelijk ben je nu het framework dat je gebruikt aan het testen, dat mag je overlaten aan de mensen die dat framework ontwikkelen ;)

Kater? Eerst water, de rest komt later


  • Xanland
  • Registratie: Oktober 2007
  • Laatst online: 00:04
Klopt, maar in dit geval is het nogal lastig naar mijn inziens want de query's zelf - gewone SQL, verwerkt door Dapper - moeten getest worden.
Het framework wat wij gebruiken, een servicebus, is geschreven door ons. Hierbij zijn stored procedures omgezet naar in-line (om het zo maar te noemen) SQL om uit te voeren op de db via Dapper.
Woy schreef op woensdag 15 januari 2014 @ 09:40:
Ik zou zeggen, voeg eens wat meer logging toe. Met breakpoints debuggen is niet altijd de beste manier, zeker niet met multithreading.

Tevens zou ik gewoon eens de SQL Server monitor aanzetten, om te kijken wat er aan die kant daadwerkelijk gebeurt.

Laat ook eens je Unit test zien de daadwerkelijk fout gaat?
Over breakpoints ben ik het helemaal met je eens, het geeft zelfs in dit geval ook hele andere resultaten dan wanneer je run test doet dan debug test. Heb zelf al ook al gekeken of de query's daadwerkelijk in de goede volgorde worden uitgevoerd, wat ook het geval was. Dit aangezien ik zeker wilde uitsluiten dat het geen race-conditie was. De query's worden in ieder geval op de goede volgorde uitgevoerd.

UnitTest:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[TestMethod]
public void Dequeue ()
{
    // definiëren van taskGuid, routingHd en msgRepo
    for (int i = 0; i < 5; i++)
    {
        long messageId = msgRepo.CreateMessage(_guid, "http://unittest.action.rx", DateTime.Now, "127.0.0.1");
        msgRepo.EnqueueEntry(messageId, routingHd.GetByteArray(), 0, false, "LAPTOP", 9836, 1, 2, 3, 3, false);
                
        int partCount = 1;
        int size = 1;
        msgRepo.CompleteMessage(messageId, partCount, size);
    }

    Task<DequeueResult_Rb> dqResult = msgRepo.StartDequeueEntries(5, "LAPTOP", 9836, 1, taskGuid.ToString());
    try
    {
        dqResult.Wait(); // toegevoegd of dit wat uitmaakte
        DequeueResult_Rb res = dqResult.Result;
        Assert.IsNotNull(res);
    }
    catch (AggregateException agg)
    {
        agg.Flatten();
    }
}


Zet hier wel de kantlijnnotitie bij dat er ook nog is getest of het SqlTransaction-gebeuren wat uitmaakte. Die drie methodes waren eerst zonder SqlTransaction.

RobIII: Ik probeer als ik wil stoppen met mijn auto ook altijd de sigarettenaansteker, de airco, 3 radioknoppen en de binnenverlichting en dan de rem :P

Pagina: 1