|
26 | 26 | // New attributes that are designed to work with Microsoft.Data.SqlClient and are publicly documented should be included in future. |
27 | 27 | namespace Microsoft.Data.SqlClient |
28 | 28 | { |
29 | | - /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/SqlCommand/*'/> |
30 | | - [DefaultEvent("RecordsAffected")] |
31 | | - [ToolboxItem(true)] |
32 | | - [DesignerCategory("")] |
33 | 29 | // TODO: Add designer attribute when Microsoft.VSDesigner.Data.VS.SqlCommandDesigner uses Microsoft.Data.SqlClient |
34 | 30 | public sealed partial class SqlCommand : DbCommand, ICloneable |
35 | 31 | { |
36 | | - private static int _objectTypeCount; // EventSource Counter |
37 | 32 | private const int MaxRPCNameLength = 1046; |
38 | | - internal readonly int ObjectID = Interlocked.Increment(ref _objectTypeCount); |
39 | 33 |
|
40 | 34 | internal sealed class ExecuteReaderAsyncCallContext : AAsyncCallContext<SqlCommand, SqlDataReader, CancellationTokenRegistration> |
41 | 35 | { |
@@ -113,8 +107,6 @@ protected override void AfterCleared(SqlCommand owner) |
113 | 107 | } |
114 | 108 | } |
115 | 109 |
|
116 | | - private string _commandText; |
117 | | - private CommandType _commandType; |
118 | 110 | private int? _commandTimeout; |
119 | 111 | private UpdateRowSource _updatedRowSource = UpdateRowSource.Both; |
120 | 112 | private bool _designTimeInvisible; |
@@ -165,38 +157,10 @@ protected override void AfterCleared(SqlCommand owner) |
165 | 157 |
|
166 | 158 | internal static readonly Action<object> s_cancelIgnoreFailure = CancelIgnoreFailureCallback; |
167 | 159 |
|
168 | | - // Prepare |
169 | | - // Against 7.0 Serve a prepare/unprepare requires an extra roundtrip to the server. |
170 | | - // |
171 | | - // From 8.0 and above, the preparation can be done as part of the command execution. |
172 | | - |
173 | | - private enum EXECTYPE |
174 | | - { |
175 | | - UNPREPARED, // execute unprepared commands, all server versions (results in sp_execsql call) |
176 | | - PREPAREPENDING, // prepare and execute command, 8.0 and above only (results in sp_prepexec call) |
177 | | - PREPARED, // execute prepared commands, all server versions (results in sp_exec call) |
178 | | - } |
179 | | - |
180 | | - // _hiddenPrepare |
181 | | - // On 8.0 and above the Prepared state cannot be left. Once a command is prepared it will always be prepared. |
182 | | - // A change in parameters, commandtext etc (IsDirty) automatically causes a hidden prepare |
183 | | - // |
184 | | - // _inPrepare will be set immediately before the actual prepare is done. |
185 | | - // The OnReturnValue function will test this flag to determine whether the returned value is a _prepareHandle or something else. |
186 | | - // |
187 | | - // _prepareHandle - the handle of a prepared command. Apparently there can be multiple prepared commands at a time - a feature that we do not support yet. |
188 | | - |
189 | | - private static readonly object s_cachedInvalidPrepareHandle = (object)-1; |
190 | | - private bool _inPrepare = false; |
191 | | - private object _prepareHandle = s_cachedInvalidPrepareHandle; // this is an int which is used in the object typed SqlParameter.Value field, avoid repeated boxing by storing in a box |
192 | | - private bool _hiddenPrepare = false; |
193 | 160 | private int _preparedConnectionCloseCount = -1; |
194 | 161 | private int _preparedConnectionReconnectCount = -1; |
195 | 162 |
|
196 | 163 | private SqlParameterCollection _parameters; |
197 | | - private SqlConnection _activeConnection; |
198 | | - private bool _dirty = false; // true if the user changes the commandtext or number of parameters after the command is already prepared |
199 | | - private EXECTYPE _execType = EXECTYPE.UNPREPARED; // by default, assume the user is not sharing a connection so the command has not been prepared |
200 | 164 | private _SqlRPC[] _rpcArrayOf1 = null; // Used for RPC executes |
201 | 165 | private _SqlRPC _rpcForEncryption = null; // Used for sp_describe_parameter_encryption RPC executes |
202 | 166 |
|
@@ -227,13 +191,6 @@ private bool ShouldCacheEncryptionMetadata |
227 | 191 | #if DEBUG |
228 | 192 | internal static int DebugForceAsyncWriteDelay { get; set; } |
229 | 193 | #endif |
230 | | - internal bool InPrepare |
231 | | - { |
232 | | - get |
233 | | - { |
234 | | - return _inPrepare; |
235 | | - } |
236 | | - } |
237 | 194 |
|
238 | 195 | /// <summary> |
239 | 196 | /// Return if column encryption setting is enabled. |
@@ -382,8 +339,6 @@ private AsyncState CachedAsyncState |
382 | 339 |
|
383 | 340 | private StatementCompletedEventHandler _statementCompletedEventHandler; |
384 | 341 |
|
385 | | - private TdsParserStateObject _stateObj; // this is the TDS session we're using. |
386 | | - |
387 | 342 | // Volatile bool used to synchronize with cancel thread the state change of an executing |
388 | 343 | // command going from pre-processing to obtaining a stateObject. The cancel synchronization |
389 | 344 | // we require in the command is only from entering an Execute* API to obtaining a |
@@ -880,131 +835,6 @@ private void PropertyChanging() |
880 | 835 | this.IsDirty = true; |
881 | 836 | } |
882 | 837 |
|
883 | | - /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/Prepare/*'/> |
884 | | - public override void Prepare() |
885 | | - { |
886 | | - // Reset _pendingCancel upon entry into any Execute - used to synchronize state |
887 | | - // between entry into Execute* API and the thread obtaining the stateObject. |
888 | | - _pendingCancel = false; |
889 | | - |
890 | | - SqlStatistics statistics = null; |
891 | | - using (TryEventScope.Create("SqlCommand.Prepare | API | Object Id {0}", ObjectID)) |
892 | | - { |
893 | | - SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.Prepare | API | Correlation | Object Id {0}, ActivityID {1}, Client Connection Id {2}", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId); |
894 | | - try |
895 | | - { |
896 | | - statistics = SqlStatistics.StartTimer(Statistics); |
897 | | - |
898 | | - // only prepare if batch with parameters |
899 | | - if (this.IsPrepared && !this.IsDirty |
900 | | - || (this.CommandType == CommandType.StoredProcedure) |
901 | | - || ((System.Data.CommandType.Text == this.CommandType) |
902 | | - && (0 == GetParameterCount(_parameters)))) |
903 | | - { |
904 | | - if (Statistics != null) |
905 | | - { |
906 | | - Statistics.SafeIncrement(ref Statistics._prepares); |
907 | | - } |
908 | | - _hiddenPrepare = false; |
909 | | - } |
910 | | - else |
911 | | - { |
912 | | - // Validate the command outside of the try/catch to avoid putting the _stateObj on error |
913 | | - ValidateCommand(isAsync: false); |
914 | | - |
915 | | - bool processFinallyBlock = true; |
916 | | - try |
917 | | - { |
918 | | - // NOTE: The state object isn't actually needed for this, but it is still here for back-compat (since it does a bunch of checks) |
919 | | - GetStateObject(); |
920 | | - |
921 | | - // Loop through parameters ensuring that we do not have unspecified types, sizes, scales, or precisions |
922 | | - if (_parameters != null) |
923 | | - { |
924 | | - int count = _parameters.Count; |
925 | | - for (int i = 0; i < count; ++i) |
926 | | - { |
927 | | - _parameters[i].Prepare(this); |
928 | | - } |
929 | | - } |
930 | | - |
931 | | - InternalPrepare(); |
932 | | - } |
933 | | - catch (Exception e) |
934 | | - { |
935 | | - processFinallyBlock = ADP.IsCatchableExceptionType(e); |
936 | | - throw; |
937 | | - } |
938 | | - finally |
939 | | - { |
940 | | - if (processFinallyBlock) |
941 | | - { |
942 | | - _hiddenPrepare = false; // The command is now officially prepared |
943 | | - |
944 | | - ReliablePutStateObject(); |
945 | | - } |
946 | | - } |
947 | | - } |
948 | | - } |
949 | | - finally |
950 | | - { |
951 | | - SqlStatistics.StopTimer(statistics); |
952 | | - } |
953 | | - } |
954 | | - } |
955 | | - |
956 | | - private void InternalPrepare() |
957 | | - { |
958 | | - if (this.IsDirty) |
959 | | - { |
960 | | - Debug.Assert(_cachedMetaData == null || !_dirty, "dirty query should not have cached metadata!"); // can have cached metadata if dirty because of parameters |
961 | | - // |
962 | | - // someone changed the command text or the parameter schema so we must unprepare the command |
963 | | - // |
964 | | - this.Unprepare(); |
965 | | - this.IsDirty = false; |
966 | | - } |
967 | | - Debug.Assert(_execType != EXECTYPE.PREPARED, "Invalid attempt to Prepare already Prepared command!"); |
968 | | - Debug.Assert(_activeConnection != null, "must have an open connection to Prepare"); |
969 | | - Debug.Assert(_stateObj != null, "TdsParserStateObject should not be null"); |
970 | | - Debug.Assert(_stateObj.Parser != null, "TdsParser class should not be null in Command.Execute!"); |
971 | | - Debug.Assert(_stateObj.Parser == _activeConnection.Parser, "stateobject parser not same as connection parser"); |
972 | | - Debug.Assert(false == _inPrepare, "Already in Prepare cycle, this.inPrepare should be false!"); |
973 | | - |
974 | | - // remember that the user wants to do a prepare but don't actually do an rpc |
975 | | - _execType = EXECTYPE.PREPAREPENDING; |
976 | | - // Note the current close count of the connection - this will tell us if the connection has been closed between calls to Prepare() and Execute |
977 | | - _preparedConnectionCloseCount = _activeConnection.CloseCount; |
978 | | - _preparedConnectionReconnectCount = _activeConnection.ReconnectCount; |
979 | | - |
980 | | - if (Statistics != null) |
981 | | - { |
982 | | - Statistics.SafeIncrement(ref Statistics._prepares); |
983 | | - } |
984 | | - } |
985 | | - |
986 | | - // SqlInternalConnectionTds needs to be able to unprepare a statement |
987 | | - internal void Unprepare() |
988 | | - { |
989 | | - Debug.Assert(true == IsPrepared, "Invalid attempt to Unprepare a non-prepared command!"); |
990 | | - Debug.Assert(_activeConnection != null, "must have an open connection to UnPrepare"); |
991 | | - Debug.Assert(false == _inPrepare, "_inPrepare should be false!"); |
992 | | - _execType = EXECTYPE.PREPAREPENDING; |
993 | | - |
994 | | - SqlClientEventSource.Log.TryTraceEvent("SqlCommand.UnPrepare | Info | Object Id {0}, Current Prepared Handle {1}", ObjectID, _prepareHandle); |
995 | | - |
996 | | - // Don't zero out the handle because we'll pass it in to sp_prepexec on the next prepare |
997 | | - // Unless the close count isn't the same as when we last prepared |
998 | | - if ((_activeConnection.CloseCount != _preparedConnectionCloseCount) || (_activeConnection.ReconnectCount != _preparedConnectionReconnectCount)) |
999 | | - { |
1000 | | - // reset our handle |
1001 | | - _prepareHandle = s_cachedInvalidPrepareHandle; |
1002 | | - } |
1003 | | - |
1004 | | - _cachedMetaData = null; |
1005 | | - SqlClientEventSource.Log.TryTraceEvent("SqlCommand.UnPrepare | Info | Object Id {0}, Command unprepared.", ObjectID); |
1006 | | - } |
1007 | | - |
1008 | 838 | // Cancel is supposed to be multi-thread safe. |
1009 | 839 | // It doesn't make sense to verify the connection exists or that it is open during cancel |
1010 | 840 | // because immediately after checking the connection can be closed or removed via another thread. |
@@ -6761,48 +6591,6 @@ internal void OnConnectionClosed() |
6761 | 6591 | } |
6762 | 6592 | } |
6763 | 6593 |
|
6764 | | - internal TdsParserStateObject StateObject |
6765 | | - { |
6766 | | - get |
6767 | | - { |
6768 | | - return _stateObj; |
6769 | | - } |
6770 | | - } |
6771 | | - |
6772 | | - private bool IsPrepared |
6773 | | - { |
6774 | | - get { return (_execType != EXECTYPE.UNPREPARED); } |
6775 | | - } |
6776 | | - |
6777 | | - private bool IsUserPrepared |
6778 | | - { |
6779 | | - get { return IsPrepared && !_hiddenPrepare && !IsDirty; } |
6780 | | - } |
6781 | | - |
6782 | | - internal bool IsDirty |
6783 | | - { |
6784 | | - get |
6785 | | - { |
6786 | | - // only dirty if prepared |
6787 | | - var activeConnection = _activeConnection; |
6788 | | - return (IsPrepared && |
6789 | | - (_dirty || |
6790 | | - ((_parameters != null) && (_parameters.IsDirty)) || |
6791 | | - ((activeConnection != null) && ((activeConnection.CloseCount != _preparedConnectionCloseCount) || (activeConnection.ReconnectCount != _preparedConnectionReconnectCount))))); |
6792 | | - } |
6793 | | - set |
6794 | | - { |
6795 | | - // only mark the command as dirty if it is already prepared |
6796 | | - // but always clear the value if it we are clearing the dirty flag |
6797 | | - _dirty = value ? IsPrepared : false; |
6798 | | - if (_parameters != null) |
6799 | | - { |
6800 | | - _parameters.IsDirty = _dirty; |
6801 | | - } |
6802 | | - _cachedMetaData = null; |
6803 | | - } |
6804 | | - } |
6805 | | - |
6806 | 6594 | /// <summary> |
6807 | 6595 | /// Get or add to the number of records affected by SpDescribeParameterEncryption. |
6808 | 6596 | /// The below line is used only for debug asserts and not exposed publicly or impacts functionality otherwise. |
|
0 commit comments