Repository navigation
Expand file tree
/
Copy pathDatabaseClientBase.Parameters.cs
More file actions
175 lines (161 loc) · 6.07 KB
/
Copy pathDatabaseClientBase.Parameters.cs
File metadata and controls
175 lines (161 loc) · 6.07 KB
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
172
173
174
175
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER
using System.Runtime.CompilerServices;
#endif
namespace DBAClientX;
public abstract partial class DatabaseClientBase
{
/// <summary>
/// Adds parameters created from dictionaries of values, types, and directions to the supplied command.
/// </summary>
/// <param name="command">The command receiving the parameters.</param>
/// <param name="parameters">Parameter values keyed by parameter name.</param>
/// <param name="parameterTypes">Explicit database types keyed by parameter name.</param>
/// <param name="parameterDirections">Explicit directions keyed by parameter name.</param>
protected virtual void AddParameters(DbCommand command, IDictionary<string, object?>? parameters, IDictionary<string, DbType>? parameterTypes = null, IDictionary<string, ParameterDirection>? parameterDirections = null)
{
if (parameters == null)
{
return;
}
foreach (var pair in parameters)
{
object value = DbaParameterValue.Unwrap(pair.Value, out DbaParameterValue? metadata);
var parameter = command.CreateParameter();
parameter.ParameterName = pair.Key;
parameter.Value = value;
if (TryGetDictionaryValue(parameterTypes, pair.Key, out var explicitType))
{
parameter.DbType = explicitType;
}
else if (metadata?.Type is DbType metadataType)
{
parameter.DbType = metadataType;
}
else
{
parameter.DbType = InferDbType(value);
}
if (TryGetDictionaryValue(parameterDirections, pair.Key, out var direction))
{
parameter.Direction = direction;
}
DbaParameterValue.ApplySize(parameter, metadata);
command.Parameters.Add(parameter);
}
}
/// <summary>
/// Copies the values of output parameters back into the supplied dictionary.
/// </summary>
/// <param name="command">The command that was executed.</param>
/// <param name="parameters">The dictionary receiving updated parameter values.</param>
protected virtual void UpdateOutputParameters(DbCommand command, IDictionary<string, object?>? parameters)
{
if (parameters == null)
{
return;
}
foreach (DbParameter p in command.Parameters)
{
if (p.Direction != ParameterDirection.Input)
{
var targetKey = FindExistingKey(parameters, p.ParameterName) ?? p.ParameterName;
parameters[targetKey] = p.Value == DBNull.Value ? null : p.Value;
}
}
}
/// <summary>
/// Adds pre-created parameters to the supplied command.
/// </summary>
/// <param name="command">The command receiving the parameters.</param>
/// <param name="parameters">The parameters to add.</param>
protected virtual void AddParameters(DbCommand command, IEnumerable<DbParameter>? parameters)
{
if (parameters == null)
{
return;
}
foreach (var parameter in parameters)
{
command.Parameters.Add(parameter);
}
}
private static DbType InferDbType(object? value)
{
if (value == null || value == DBNull.Value) return DbType.Object;
if (value is Guid) return DbType.Guid;
if (value is byte[]) return DbType.Binary;
if (value is TimeSpan) return DbType.Time;
if (value is DateTimeOffset) return DbType.DateTimeOffset;
return Type.GetTypeCode(value.GetType()) switch
{
TypeCode.Byte => DbType.Byte,
TypeCode.SByte => DbType.SByte,
TypeCode.Int16 => DbType.Int16,
TypeCode.Int32 => DbType.Int32,
TypeCode.Int64 => DbType.Int64,
TypeCode.UInt16 => DbType.UInt16,
TypeCode.UInt32 => DbType.UInt32,
TypeCode.UInt64 => DbType.UInt64,
TypeCode.Decimal => DbType.Decimal,
TypeCode.Double => DbType.Double,
TypeCode.Single => DbType.Single,
TypeCode.Boolean => DbType.Boolean,
TypeCode.String => DbType.String,
TypeCode.Char => DbType.StringFixedLength,
TypeCode.DateTime => DbType.DateTime,
_ => DbType.Object
};
}
/// <summary>
/// Looks up a dictionary value using the supplied key, falling back to a case-insensitive comparison.
/// </summary>
/// <typeparam name="TValue">The dictionary value type.</typeparam>
/// <param name="dictionary">The dictionary to inspect.</param>
/// <param name="key">The key to find.</param>
/// <param name="value">The value when a matching key is found.</param>
/// <returns><c>true</c> when the key is present; otherwise, <c>false</c>.</returns>
protected static bool TryGetDictionaryValue<TValue>(IDictionary<string, TValue>? dictionary, string key, out TValue value)
{
value = default!;
if (dictionary == null)
{
return false;
}
if (dictionary.TryGetValue(key, out var foundValue))
{
value = foundValue;
return true;
}
foreach (var pair in dictionary)
{
if (string.Equals(pair.Key, key, StringComparison.OrdinalIgnoreCase))
{
value = pair.Value;
return true;
}
}
return false;
}
private static string? FindExistingKey(IDictionary<string, object?> dictionary, string key)
{
if (dictionary.ContainsKey(key))
{
return key;
}
foreach (var pair in dictionary)
{
if (string.Equals(pair.Key, key, StringComparison.OrdinalIgnoreCase))
{
return pair.Key;
}
}
return null;
}
}