This repository has been archived by the owner on Nov 20, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
SqlCeModificationCommandBatch.cs
171 lines (142 loc) · 6.16 KB
/
SqlCeModificationCommandBatch.cs
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
using System;
using System.Data.Common;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Update;
using Microsoft.EntityFrameworkCore.Utilities;
namespace EFCore.SqlCe.Update.Internal
{
public class SqlCeModificationCommandBatch : AffectedCountModificationCommandBatch
{
private bool _returnFirstCommandText;
public SqlCeModificationCommandBatch(
[NotNull] IRelationalCommandBuilderFactory commandBuilderFactory,
[NotNull] ISqlGenerationHelper sqlGenerationHelper,
[NotNull] ISqlCeUpdateSqlGenerator updateSqlGenerator,
[NotNull] IRelationalValueBufferFactoryFactory valueBufferFactoryFactory)
: base(
commandBuilderFactory,
sqlGenerationHelper,
updateSqlGenerator,
valueBufferFactoryFactory)
{
}
public override void Execute(IRelationalConnection connection)
{
Check.NotNull(connection, nameof(connection));
_returnFirstCommandText = true;
var relationalCommand = CreateStoreCommand();
try
{
#if DEBUG
System.Diagnostics.Debug.WriteLine(GetCommandText());
#endif
using (var reader = relationalCommand.RelationalCommand.ExecuteReader(connection, relationalCommand.ParameterValues))
{
Consume(reader, GetCommandText(), connection);
}
}
catch (DbUpdateException)
{
throw;
}
catch (Exception ex)
{
throw new DbUpdateException(
"An error occurred while updating the entries. See the inner exception for details.",
ex);
}
}
private void Consume(RelationalDataReader reader, string returningCommandText, IRelationalConnection connection)
{
var commandIndex = 0;
try
{
if (ModificationCommands[0].RequiresResultPropagation && (returningCommandText != null))
{
_returnFirstCommandText = false;
var returningCommand = CreateStoreCommand();
using (var returningReader = returningCommand.RelationalCommand.ExecuteReader(connection, returningCommand.ParameterValues))
{
commandIndex = ConsumeResultSetWithPropagation(commandIndex,
reader.DbDataReader,
returningReader.DbDataReader);
}
}
else
{
commandIndex = ConsumeResultSetWithoutPropagation(commandIndex, reader);
}
Debug.Assert(commandIndex == ModificationCommands.Count, "Expected " + ModificationCommands.Count + " results, got " + commandIndex);
}
catch (DbUpdateException)
{
throw;
}
catch (Exception ex)
{
throw new DbUpdateException(
"An error occurred while updating the entries. See the inner exception for details.",
ex,
ModificationCommands[commandIndex].Entries);
}
}
public override Task ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken = default)
{
Check.NotNull(connection, nameof(connection));
cancellationToken.ThrowIfCancellationRequested();
return Task.Run(() => Execute(connection), cancellationToken);
}
protected override string GetCommandText()
{
var commandTexts = SplitCommandText(base.GetCommandText());
return _returnFirstCommandText ? commandTexts.Item1 : commandTexts.Item2;
}
private Tuple<string, string> SplitCommandText(string commandText)
{
var stringToFind = SqlGenerationHelper.StatementTerminator + Environment.NewLine + "SELECT ";
var stringToFindIndex = commandText.IndexOf(stringToFind, StringComparison.OrdinalIgnoreCase);
if (stringToFindIndex > 0)
{
return new Tuple<string, string>(
commandText.Substring(0, stringToFindIndex + 1).Trim(),
commandText.Substring(commandText.LastIndexOf(stringToFind, StringComparison.OrdinalIgnoreCase) + 1).Trim());
}
return new Tuple<string, string>(commandText.Trim(), null);
}
protected override int ConsumeResultSetWithoutPropagation(int commandIndex, RelationalDataReader reader)
{
const int expectedRowsAffected = 1;
var rowsAffected = reader.DbDataReader.RecordsAffected;
++commandIndex;
if (rowsAffected != expectedRowsAffected)
{
ThrowAggregateUpdateConcurrencyException(commandIndex, expectedRowsAffected, rowsAffected);
}
return commandIndex;
}
private int ConsumeResultSetWithPropagation(int commandIndex, DbDataReader reader, DbDataReader returningReader)
{
var tableModification = ModificationCommands[commandIndex];
Debug.Assert(tableModification.RequiresResultPropagation);
++commandIndex;
reader.Read();
if (reader.RecordsAffected != 1)
{
ThrowAggregateUpdateConcurrencyException(commandIndex, 1, 0);
}
returningReader.Read();
var valueBufferFactory = CreateValueBufferFactory(tableModification.ColumnModifications);
tableModification.PropagateResults(valueBufferFactory.Create(returningReader));
return commandIndex;
}
protected override bool CanAddCommand(ModificationCommand modificationCommand)
=> ModificationCommands.Count == 0;
protected override bool IsCommandTextValid()
=> true;
}
}