comparison Source/Data/DataProvider/AccessDataProvider.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f990fcb411a9
1 using System;
2 using System.Data;
3 using System.Data.OleDb;
4 using System.Text.RegularExpressions;
5
6 namespace BLToolkit.Data.DataProvider
7 {
8 using Mapping;
9 using Sql.SqlProvider;
10
11 public class AccessDataProvider : OleDbDataProvider
12 {
13 private static Regex _paramsExp;
14
15 // Based on idea from http://qapi.blogspot.com/2006/12/deriveparameters-oledbprovider-ii.html
16 //
17 public override bool DeriveParameters(IDbCommand command)
18 {
19 if (command == null)
20 throw new ArgumentNullException("command");
21
22 if (command.CommandType != CommandType.StoredProcedure)
23 throw new InvalidOperationException("command.CommandType must be CommandType.StoredProcedure");
24
25 var conn = command.Connection as OleDbConnection;
26
27 if (conn == null || conn.State != ConnectionState.Open)
28 throw new InvalidOperationException("Invalid connection state.");
29
30 command.Parameters.Clear();
31
32 var dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Procedures, new object[]{null, null, command.CommandText});
33
34 if (dt.Rows.Count == 0)
35 {
36 // Jet does convert parameretless procedures to views.
37 //
38 dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Views, new object[]{null, null, command.CommandText});
39
40 if (dt.Rows.Count == 0)
41 throw new DataException(string.Format("Stored procedure '{0}' not found", command.CommandText));
42
43 // Do nothing. There is no parameters.
44 //
45 }
46 else
47 {
48 var col = dt.Columns["PROCEDURE_DEFINITION"];
49
50 if (col == null)
51 {
52 // Not really possible
53 //
54 return false;
55 }
56
57 if (_paramsExp == null)
58 _paramsExp = new Regex(@"PARAMETERS ((\[(?<name>[^\]]+)\]|(?<name>[^\s]+))\s(?<type>[^,;\s]+(\s\([^\)]+\))?)[,;]\s)*", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
59
60 var match = _paramsExp.Match((string)dt.Rows[0][col.Ordinal]);
61 var names = match.Groups["name"].Captures;
62 var types = match.Groups["type"].Captures;
63
64 if (names.Count != types.Count)
65 {
66 // Not really possible
67 //
68 return false;
69 }
70
71 var separators = new[] {' ', '(', ',', ')'};
72
73 for (var i = 0; i < names.Count; ++i)
74 {
75 var paramName = names[i].Value;
76 var rawType = types[i].Value.Split(separators, StringSplitOptions.RemoveEmptyEntries);
77 var p = new OleDbParameter(paramName, GetOleDbType(rawType[0]));
78
79 if (rawType.Length > 2)
80 {
81 p.Precision = Common.Convert.ToByte(rawType[1]);
82 p.Scale = Common.Convert.ToByte(rawType[2]);
83 }
84 else if (rawType.Length > 1)
85 {
86 p.Size = Common.Convert.ToInt32(rawType[1]);
87 }
88
89 command.Parameters.Add(p);
90 }
91 }
92
93 return true;
94 }
95
96 private static OleDbType GetOleDbType(string jetType)
97 {
98 switch (jetType.ToLower())
99 {
100 case "byte":
101 case "tinyint":
102 case "integer1":
103 return OleDbType.TinyInt;
104
105 case "short":
106 case "smallint":
107 case "integer2":
108 return OleDbType.SmallInt;
109
110 case "int":
111 case "integer":
112 case "long":
113 case "integer4":
114 case "counter":
115 case "identity":
116 case "autoincrement":
117 return OleDbType.Integer;
118
119 case "single":
120 case "real":
121 case "float4":
122 case "ieeesingle":
123 return OleDbType.Single;
124
125
126 case "double":
127 case "number":
128 case "double precision":
129 case "float":
130 case "float8":
131 case "ieeedouble":
132 return OleDbType.Double;
133
134 case "currency":
135 case "money":
136 return OleDbType.Currency;
137
138 case "dec":
139 case "decimal":
140 case "numeric":
141 return OleDbType.Decimal;
142
143 case "bit":
144 case "yesno":
145 case "logical":
146 case "logical1":
147 return OleDbType.Boolean;
148
149 case "datetime":
150 case "date":
151 case "time":
152 return OleDbType.Date;
153
154 case "alphanumeric":
155 case "char":
156 case "character":
157 case "character varying":
158 case "national char":
159 case "national char varying":
160 case "national character":
161 case "national character varying":
162 case "nchar":
163 case "string":
164 case "text":
165 case "varchar":
166 return OleDbType.VarWChar;
167
168 case "longchar":
169 case "longtext":
170 case "memo":
171 case "note":
172 case "ntext":
173 return OleDbType.LongVarWChar;
174
175 case "binary":
176 case "varbinary":
177 case "binary varying":
178 case "bit varying":
179 return OleDbType.VarBinary;
180
181 case "longbinary":
182 case "image":
183 case "general":
184 case "oleobject":
185 return OleDbType.LongVarBinary;
186
187 case "guid":
188 case "uniqueidentifier":
189 return OleDbType.Guid;
190
191 default:
192 // Each release of Jet brings many new aliases to existing types.
193 // This list may be outdated, please send a report to us.
194 //
195 throw new NotSupportedException("Unknown DB type '" + jetType + "'");
196 }
197 }
198
199 public override void AttachParameter(IDbCommand command, IDbDataParameter parameter)
200 {
201 // Do some magic to workaround 'Data type mismatch in criteria expression' error
202 // in JET for some european locales.
203 //
204 if (parameter.Value is DateTime)
205 {
206 // OleDbType.DBTimeStamp is locale aware, OleDbType.Date is locale neutral.
207 //
208 ((OleDbParameter)parameter).OleDbType = OleDbType.Date;
209 }
210 else if (parameter.Value is decimal)
211 {
212 // OleDbType.Decimal is locale aware, OleDbType.Currency is locale neutral.
213 //
214 ((OleDbParameter)parameter).OleDbType = OleDbType.Currency;
215 }
216
217 base.AttachParameter(command, parameter);
218 }
219
220 public new const string NameString = DataProvider.ProviderName.Access;
221
222 public override string Name
223 {
224 get { return NameString; }
225 }
226
227 public override int MaxBatchSize
228 {
229 get { return 0; }
230 }
231
232 public override ISqlProvider CreateSqlProvider()
233 {
234 return new AccessSqlProvider();
235 }
236
237 public override object Convert(object value, ConvertType convertType)
238 {
239 switch (convertType)
240 {
241 case ConvertType.ExceptionToErrorNumber:
242 if (value is OleDbException)
243 {
244 var ex = (OleDbException)value;
245 if (ex.Errors.Count > 0)
246 return ex.Errors[0].NativeError;
247 }
248
249 break;
250 }
251
252 return SqlProvider.Convert(value, convertType);
253 }
254
255 #region DataReaderEx
256
257 public override IDataReader GetDataReader(MappingSchema schema, IDataReader dataReader)
258 {
259 return dataReader is OleDbDataReader?
260 new DataReaderEx((OleDbDataReader)dataReader):
261 base.GetDataReader(schema, dataReader);
262 }
263
264 class DataReaderEx : DataReaderBase<OleDbDataReader>, IDataReader
265 {
266 public DataReaderEx(OleDbDataReader rd): base(rd)
267 {
268 }
269
270 public new object GetValue(int i)
271 {
272 var value = DataReader.GetValue(i);
273
274 if (value is DateTime)
275 {
276 var dt = (DateTime)value;
277
278 if (dt.Year == 1899 && dt.Month == 12 && dt.Day == 30)
279 return new DateTime(1, 1, 1, dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
280 }
281
282 return value;
283 }
284
285 public new DateTime GetDateTime(int i)
286 {
287 var dt = DataReader.GetDateTime(i);
288
289 if (dt.Year == 1899 && dt.Month == 12 && dt.Day == 30)
290 return new DateTime(1, 1, 1, dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
291
292 return dt;
293 }
294 }
295
296 #endregion
297 }
298 }