Mercurial > pub > bltoolkit
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 } |
