Skip to content

Commit e93d72d

Browse files
authored
Merge pull request #154 from sgwyn/fix-RecordsAffected
fixed RecordsAffected functionality and added Integration Tests
2 parents 338c4ee + 267ce41 commit e93d72d

File tree

7 files changed

+469
-91
lines changed

7 files changed

+469
-91
lines changed

src/AdoNetCore.AseClient/AseDataReader.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public sealed class AseDataReader : DbDataReader
1919
private readonly CommandBehavior _behavior;
2020
private readonly IInfoMessageEventNotifier _eventNotifier;
2121
private bool _hasFirst;
22+
private int _totalResults;
2223

2324
#if ENABLE_SYSTEM_DATA_COMMON_EXTENSIONS
2425
private readonly AseCommand _command;
@@ -44,6 +45,8 @@ internal AseDataReader(CommandBehavior behavior, IInfoMessageEventNotifier event
4445
internal void AddResult(TableResult result)
4546
{
4647
_results.Add(result);
48+
_totalResults++;
49+
result.RecordsAffected = _finalRecordsAffected;
4750

4851
// If this is the first data result back, then we should automatically point at it.
4952
if (!_hasFirst)
@@ -632,7 +635,19 @@ public override bool Read()
632635

633636
public override int Depth => 0;
634637
public override bool IsClosed => _currentTable == null;
635-
public override int RecordsAffected => _currentTable?.Rows.Count ?? 0;
638+
private int _finalRecordsAffected = -1;
639+
public override int RecordsAffected
640+
{
641+
get
642+
{
643+
return _currentTable != null && _currentResult < _totalResults ? _currentTable.RecordsAffected : _finalRecordsAffected;
644+
}
645+
}
646+
647+
public void SetRecordsAffected(int value)
648+
{
649+
_finalRecordsAffected = value;
650+
}
636651

637652
public IList GetList()
638653
{

src/AdoNetCore.AseClient/Internal/Handler/DoneTokenHandler.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,24 @@ public void Handle(IToken token)
4646
break;
4747
case DoneProcToken t:
4848
Logger.Instance?.WriteLine($"{t.Type}: {t.Status}");
49-
if (t.Status.HasFlag(DoneProcCommonToken.DoneProcStatus.TDS_DONE_INXACT))
49+
if (t.Status.HasFlag(DoneToken.DoneStatus.TDS_DONE_INXACT))
5050
{
5151
Logger.Instance?.WriteLine($" {t.TransactionState}");
5252
TransactionState = t.TransactionState;
5353
}
54-
if (t.Status.HasFlag(DoneProcCommonToken.DoneProcStatus.TDS_DONE_COUNT))
54+
if (t.Status.HasFlag(DoneToken.DoneStatus.TDS_DONE_COUNT))
5555
{
5656
RowsAffected += t.Count;
5757
}
5858
break;
5959
case DoneInProcToken t:
6060
Logger.Instance?.WriteLine($"{t.Type}: {t.Status}");
61-
if (t.Status.HasFlag(DoneProcCommonToken.DoneProcStatus.TDS_DONE_INXACT))
61+
if (t.Status.HasFlag(DoneToken.DoneStatus.TDS_DONE_INXACT))
6262
{
6363
Logger.Instance?.WriteLine($" {t.TransactionState}");
6464
TransactionState = t.TransactionState;
6565
}
66-
if (t.Status.HasFlag(DoneProcCommonToken.DoneProcStatus.TDS_DONE_COUNT))
66+
if (t.Status.HasFlag(DoneToken.DoneStatus.TDS_DONE_COUNT))
6767
{
6868
RowsAffected += t.Count;
6969
}

src/AdoNetCore.AseClient/Internal/Handler/StreamingDataReaderTokenHandler.cs

Lines changed: 80 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Data.Common;
34
using System.Text;
@@ -29,6 +30,8 @@ internal class StreamingDataReaderTokenHandler : ITokenHandler
2930
private TableResult _current;
3031
private bool _hasFirstResultSet;
3132
private bool _hasSentCurrent;
33+
private bool _hasFormatted;
34+
private int _runningTotalRecordsAffected;
3235

3336
public StreamingDataReaderTokenHandler(TaskCompletionSource<DbDataReader> readerSource, AseDataReader dataReader, IInfoMessageEventNotifier eventNotifier)
3437
{
@@ -48,80 +51,107 @@ public void Handle(IToken token)
4851
switch (token)
4952
{
5053
case IFormatToken format:
54+
5155
ReturnCurrent();
5256
_current = new TableResult
5357
{
54-
Formats = format.Formats
58+
Formats = format.Formats,
59+
RecordsAffected = -1
5560
};
5661
_hasSentCurrent = false;
62+
_hasFormatted = true;
5763
break;
5864
case RowToken row:
5965
_current?.Rows.Add(new RowResult
6066
{
6167
Items = row.Values
6268
});
6369
break;
64-
case DoneToken _:
70+
case DoneToken t:
71+
HandleDoneToken(t);
72+
break;
6573
case DoneInProcToken _:
6674
case DoneProcToken _:
6775
ReturnCurrent();
6876
break;
6977
case EedToken t:
78+
HandleEedToken(t);
79+
break;
80+
}
81+
}
7082

71-
var isSevere = t.Severity > 10;
72-
73-
if (isSevere)
74-
{
75-
_foundSevereError = true;
76-
}
83+
private void HandleDoneToken(DoneToken token)
84+
{
85+
if (_hasFormatted)
86+
{
87+
ReturnCurrent();
88+
_hasFormatted = false;
89+
}
90+
else if ((token.Status & DoneToken.DoneStatus.TDS_DONE_COUNT) == DoneToken.DoneStatus.TDS_DONE_COUNT)
91+
{
92+
_runningTotalRecordsAffected += token.Count;
93+
_dataReader.SetRecordsAffected(_runningTotalRecordsAffected);
94+
}
95+
if ((token.Status & DoneToken.DoneStatus.TDS_DONE_MORE) == DoneToken.DoneStatus.TDS_DONE_FINAL)
96+
{
97+
ReturnCurrent();
98+
}
99+
}
77100

78-
var error = new AseError
79-
{
80-
IsError = isSevere,
81-
IsFromServer = true,
82-
Message = t.Message,
83-
MessageNumber = t.MessageNumber,
84-
ProcName = t.ProcedureName,
85-
State = t.State,
86-
TranState = (int)t.TransactionStatus,
87-
Status = (int)t.Status,
88-
Severity = t.Severity,
89-
ServerName = t.ServerName,
90-
SqlState = Encoding.ASCII.GetString(t.SqlState),
91-
IsFromClient = false,
92-
IsInformation = !isSevere,
93-
IsWarning = false,
94-
LineNum = t.LineNumber
95-
};
101+
private void HandleEedToken(EedToken token)
102+
{
103+
var isSevere = token.Severity > 10;
96104

97-
_allErrors.Add(error);
105+
if (isSevere)
106+
{
107+
_foundSevereError = true;
108+
}
98109

99-
// if we have not encountered any data yet, then send messages straight out.
100-
if (_current == null)
101-
{
102-
_eventNotifier?.NotifyInfoMessage(new AseErrorCollection(error), error.Message);
103-
}
104-
// else if we have encountered any data, then add the messages to the data reader so that they are returned with data/message order preserved.
105-
else
106-
{
107-
_current.Messages.Add(new MessageResult {Errors = new AseErrorCollection(error), Message = error.Message});
108-
}
110+
var error = new AseError
111+
{
112+
IsError = isSevere,
113+
IsFromServer = true,
114+
Message = token.Message,
115+
MessageNumber = token.MessageNumber,
116+
ProcName = token.ProcedureName,
117+
State = token.State,
118+
TranState = (int)token.TransactionStatus,
119+
Status = (int)token.Status,
120+
Severity = token.Severity,
121+
ServerName = token.ServerName,
122+
SqlState = Encoding.ASCII.GetString(token.SqlState),
123+
IsFromClient = false,
124+
IsInformation = !isSevere,
125+
IsWarning = false,
126+
LineNum = token.LineNumber
127+
};
128+
129+
_allErrors.Add(error);
130+
131+
// if we have not encountered any data yet, then send messages straight out.
132+
if (_current == null)
133+
{
134+
_eventNotifier?.NotifyInfoMessage(new AseErrorCollection(error), error.Message);
135+
}
136+
// else if we have encountered any data, then add the messages to the data reader so that they are returned with data/message order preserved.
137+
else
138+
{
139+
_current.Messages.Add(new MessageResult { Errors = new AseErrorCollection(error), Message = error.Message });
140+
}
109141

110-
var msgType = isSevere
111-
? "ERROR"
112-
: "INFO ";
142+
var msgType = isSevere
143+
? "ERROR"
144+
: "INFO ";
113145

114-
var formatted = $"{msgType} [{t.Severity}] [L:{t.LineNumber}]: {t.Message}";
146+
var formatted = $"{msgType} [{token.Severity}] [L:{token.LineNumber}]: {token.Message}";
115147

116-
if (formatted.EndsWith("\n"))
117-
{
118-
Logger.Instance?.Write(formatted);
119-
}
120-
else
121-
{
122-
Logger.Instance?.WriteLine(formatted);
123-
}
124-
break;
148+
if (formatted.EndsWith("\n"))
149+
{
150+
Logger.Instance?.Write(formatted);
151+
}
152+
else
153+
{
154+
Logger.Instance?.WriteLine(formatted);
125155
}
126156
}
127157

src/AdoNetCore.AseClient/Internal/TableResult.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@ internal sealed class TableResult
88
public List<RowResult> Rows { get; } = new List<RowResult>();
99

1010
public List<MessageResult> Messages { get; } = new List<MessageResult>();
11+
12+
public int RecordsAffected { get; set; } = 0;
1113
}
1214
}
Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.IO;
33
using AdoNetCore.AseClient.Enum;
44
using AdoNetCore.AseClient.Interface;
@@ -8,37 +8,7 @@ namespace AdoNetCore.AseClient.Token
88
{
99
internal abstract class DoneProcCommonToken
1010
{
11-
[Flags]
12-
public enum DoneProcStatus : ushort
13-
{
14-
/// <summary>
15-
/// This is the final result for the last command. It indicates that the command has completed successfully.
16-
/// </summary>
17-
// ReSharper disable once InconsistentNaming
18-
TDS_DONE_FINAL = 0x0000,
19-
/// <summary>
20-
/// This Status indicates that there are more results to follow for the current command.
21-
/// </summary>
22-
// ReSharper disable once InconsistentNaming
23-
TDS_DONE_MORE = 0x0001,
24-
/// <summary>
25-
/// This indicates that an error occurred on the current command.
26-
/// </summary>
27-
// ReSharper disable once InconsistentNaming
28-
TDS_DONE_ERROR = 0x0002,
29-
/// <summary>
30-
/// There is a transaction in progress for the current request.
31-
/// </summary>
32-
// ReSharper disable once InconsistentNaming
33-
TDS_DONE_INXACT = 0x0004,
34-
/// <summary>
35-
/// This Status indicates that the count argument is valid. This bit is used to distinguish between an empty count field and a count field with a value of 0.
36-
/// </summary>
37-
// ReSharper disable once InconsistentNaming
38-
TDS_DONE_COUNT = 0x0010,
39-
}
40-
41-
public DoneProcStatus Status { get; set; }
11+
public DoneToken.DoneStatus Status { get; set; }
4212
public TranState TransactionState { get; set; }
4313
public int Count { get; set; }
4414

@@ -49,10 +19,10 @@ public void Write(Stream stream, DbEnvironment env)
4919

5020
public void Read(Stream stream, DbEnvironment env, IFormatToken previous)
5121
{
52-
Status = (DoneProcStatus)stream.ReadUShort();
22+
Status = (DoneToken.DoneStatus)stream.ReadUShort();
5323
TransactionState = (TranState)stream.ReadUShort();
5424
Count = stream.ReadInt();
5525
Logger.Instance?.WriteLine($"<- {Status}, {TransactionState}, {Count}");
5626
}
5727
}
58-
}
28+
}

0 commit comments

Comments
 (0)