PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/Signum.Engine/Connection/FieldReader.cs

https://github.com/mutharasank/framework
C# | 611 lines | 542 code | 69 blank | 0 comment | 56 complexity | 30e180d1406a65ae047ee5b8d818b5c1 MD5 | raw file
Possible License(s): GPL-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Data.SqlClient;
  6. using Signum.Utilities.Reflection;
  7. using System.Linq.Expressions;
  8. using System.Reflection;
  9. using Signum.Utilities;
  10. using Signum.Engine.Maps;
  11. using Signum.Entities;
  12. using System.Data.SqlTypes;
  13. using System.Data.Common;
  14. using Microsoft.SqlServer.Types;
  15. using Microsoft.SqlServer.Server;
  16. using Signum.Utilities.ExpressionTrees;
  17. namespace Signum.Engine
  18. {
  19. public class FieldReader
  20. {
  21. DbDataReader reader;
  22. TypeCode[] typeCodes;
  23. private const TypeCode tcGuid = (TypeCode)20;
  24. private const TypeCode tcTimeSpan = (TypeCode)21;
  25. private const TypeCode tcDateTimeOffset = (TypeCode)22;
  26. public int LastOrdinal;
  27. TypeCode GetTypeCode(int ordinal)
  28. {
  29. Type type = reader.GetFieldType(ordinal);
  30. TypeCode tc = Type.GetTypeCode(type);
  31. if (tc == TypeCode.Object)
  32. {
  33. if (type == typeof(Guid))
  34. tc = tcGuid;
  35. if (type == typeof(TimeSpan))
  36. tc = tcTimeSpan;
  37. if (type == typeof(DateTimeOffset))
  38. tc = tcDateTimeOffset;
  39. }
  40. return tc;
  41. }
  42. public FieldReader(DbDataReader reader)
  43. {
  44. this.reader = reader;
  45. this.typeCodes = new TypeCode[reader.FieldCount];
  46. for (int i = 0; i < typeCodes.Length; i++)
  47. typeCodes[i] = GetTypeCode(i);
  48. }
  49. public bool IsNull(int ordinal)
  50. {
  51. LastOrdinal = ordinal;
  52. return reader.IsDBNull(ordinal);
  53. }
  54. public string GetString(int ordinal)
  55. {
  56. LastOrdinal = ordinal;
  57. if (reader.IsDBNull(ordinal))
  58. {
  59. return null;
  60. }
  61. switch (typeCodes[ordinal])
  62. {
  63. case TypeCode.Byte:
  64. return reader.GetByte(ordinal).ToString();
  65. case TypeCode.Int16:
  66. return reader.GetInt16(ordinal).ToString();
  67. case TypeCode.Int32:
  68. return reader.GetInt32(ordinal).ToString();
  69. case TypeCode.Int64:
  70. return reader.GetInt64(ordinal).ToString();
  71. case TypeCode.Double:
  72. return reader.GetDouble(ordinal).ToString();
  73. case TypeCode.Single:
  74. return reader.GetFloat(ordinal).ToString();
  75. case TypeCode.Decimal:
  76. return reader.GetDecimal(ordinal).ToString();
  77. case TypeCode.DateTime:
  78. return reader.GetDateTime(ordinal).ToString();
  79. case tcGuid:
  80. return reader.GetGuid(ordinal).ToString();
  81. case TypeCode.String:
  82. return reader.GetString(ordinal);
  83. default:
  84. return reader.GetValue(ordinal).ToString();
  85. }
  86. }
  87. public byte[] GetByteArray(int ordinal)
  88. {
  89. LastOrdinal = ordinal;
  90. if (reader.IsDBNull(ordinal))
  91. {
  92. return null;
  93. }
  94. return (byte[])reader.GetValue(ordinal);
  95. }
  96. public bool GetBoolean(int ordinal)
  97. {
  98. LastOrdinal = ordinal;
  99. switch (typeCodes[ordinal])
  100. {
  101. case TypeCode.Boolean:
  102. return reader.GetBoolean(ordinal);
  103. case TypeCode.Byte:
  104. return reader.GetByte(ordinal) != 0;
  105. case TypeCode.Int16:
  106. return reader.GetInt16(ordinal) != 0;
  107. case TypeCode.Int32:
  108. return reader.GetInt32(ordinal) != 0;
  109. case TypeCode.Int64:
  110. return reader.GetInt64(ordinal) != 0;
  111. case TypeCode.String:
  112. return bool.Parse(reader.GetString(ordinal));
  113. default:
  114. return ReflectionTools.ChangeType<bool>(reader.GetValue(ordinal));
  115. }
  116. }
  117. public bool? GetNullableBoolean(int ordinal)
  118. {
  119. LastOrdinal = ordinal;
  120. if (reader.IsDBNull(ordinal))
  121. {
  122. return null;
  123. }
  124. return GetBoolean(ordinal);
  125. }
  126. public Byte GetByte(int ordinal)
  127. {
  128. LastOrdinal = ordinal;
  129. switch (typeCodes[ordinal])
  130. {
  131. case TypeCode.Byte:
  132. return reader.GetByte(ordinal);
  133. case TypeCode.Int16:
  134. return (Byte)reader.GetInt16(ordinal);
  135. case TypeCode.Int32:
  136. return (Byte)reader.GetInt32(ordinal);
  137. case TypeCode.Int64:
  138. return (Byte)reader.GetInt64(ordinal);
  139. case TypeCode.Double:
  140. return (Byte)reader.GetDouble(ordinal);
  141. case TypeCode.Single:
  142. return (Byte)reader.GetFloat(ordinal);
  143. case TypeCode.Decimal:
  144. return (Byte)reader.GetDecimal(ordinal);
  145. default:
  146. return ReflectionTools.ChangeType<Byte>(reader.GetValue(ordinal));
  147. }
  148. }
  149. public Byte? GetNullableByte(int ordinal)
  150. {
  151. LastOrdinal = ordinal;
  152. if (reader.IsDBNull(ordinal))
  153. {
  154. return null;
  155. }
  156. return GetByte(ordinal);
  157. }
  158. public Char GetChar(int ordinal)
  159. {
  160. LastOrdinal = ordinal;
  161. switch (typeCodes[ordinal])
  162. {
  163. case TypeCode.Byte:
  164. return (Char)reader.GetByte(ordinal);
  165. case TypeCode.Int16:
  166. return (Char)reader.GetInt16(ordinal);
  167. case TypeCode.Int32:
  168. return (Char)reader.GetInt32(ordinal);
  169. case TypeCode.Int64:
  170. return (Char)reader.GetInt64(ordinal);
  171. case TypeCode.Double:
  172. return (Char)reader.GetDouble(ordinal);
  173. case TypeCode.Single:
  174. return (Char)reader.GetFloat(ordinal);
  175. case TypeCode.Decimal:
  176. return (Char)reader.GetDecimal(ordinal);
  177. default:
  178. return ReflectionTools.ChangeType<Char>(reader.GetValue(ordinal));
  179. }
  180. }
  181. public Char? GetNullableChar(int ordinal)
  182. {
  183. LastOrdinal = ordinal;
  184. if (reader.IsDBNull(ordinal))
  185. {
  186. return null;
  187. }
  188. return GetChar(ordinal);
  189. }
  190. public Single GetFloat(int ordinal)
  191. {
  192. LastOrdinal = ordinal;
  193. switch (typeCodes[ordinal])
  194. {
  195. case TypeCode.Byte:
  196. return (Single)reader.GetByte(ordinal);
  197. case TypeCode.Int16:
  198. return (Single)reader.GetInt16(ordinal);
  199. case TypeCode.Int32:
  200. return (Single)reader.GetInt32(ordinal);
  201. case TypeCode.Int64:
  202. return (Single)reader.GetInt64(ordinal);
  203. case TypeCode.Double:
  204. return (Single)reader.GetDouble(ordinal);
  205. case TypeCode.Single:
  206. return reader.GetFloat(ordinal);
  207. case TypeCode.Decimal:
  208. return (Single)reader.GetDecimal(ordinal);
  209. default:
  210. return ReflectionTools.ChangeType<Single>(reader.GetValue(ordinal));
  211. }
  212. }
  213. public Single? GetNullableFloat(int ordinal)
  214. {
  215. LastOrdinal = ordinal;
  216. if (reader.IsDBNull(ordinal))
  217. {
  218. return null;
  219. }
  220. return GetFloat(ordinal);
  221. }
  222. public Double GetDouble(int ordinal)
  223. {
  224. LastOrdinal = ordinal;
  225. switch (typeCodes[ordinal])
  226. {
  227. case TypeCode.Byte:
  228. return (Double)reader.GetByte(ordinal);
  229. case TypeCode.Int16:
  230. return (Double)reader.GetInt16(ordinal);
  231. case TypeCode.Int32:
  232. return (Double)reader.GetInt32(ordinal);
  233. case TypeCode.Int64:
  234. return (Double)reader.GetInt64(ordinal);
  235. case TypeCode.Double:
  236. return reader.GetDouble(ordinal);
  237. case TypeCode.Single:
  238. return (Double)reader.GetFloat(ordinal);
  239. case TypeCode.Decimal:
  240. return (Double)reader.GetDecimal(ordinal);
  241. default:
  242. return ReflectionTools.ChangeType<Double>(reader.GetValue(ordinal));
  243. }
  244. }
  245. public Double? GetNullableDouble(int ordinal)
  246. {
  247. LastOrdinal = ordinal;
  248. if (reader.IsDBNull(ordinal))
  249. {
  250. return null;
  251. }
  252. return GetDouble(ordinal);
  253. }
  254. public Decimal GetDecimal(int ordinal)
  255. {
  256. LastOrdinal = ordinal;
  257. switch (typeCodes[ordinal])
  258. {
  259. case TypeCode.Byte:
  260. return (Decimal)reader.GetByte(ordinal);
  261. case TypeCode.Int16:
  262. return (Decimal)reader.GetInt16(ordinal);
  263. case TypeCode.Int32:
  264. return (Decimal)reader.GetInt32(ordinal);
  265. case TypeCode.Int64:
  266. return (Decimal)reader.GetInt64(ordinal);
  267. case TypeCode.Double:
  268. return (Decimal)reader.GetDouble(ordinal);
  269. case TypeCode.Single:
  270. return (Decimal)reader.GetFloat(ordinal);
  271. case TypeCode.Decimal:
  272. return reader.GetDecimal(ordinal);
  273. default:
  274. return ReflectionTools.ChangeType<Decimal>(reader.GetValue(ordinal));
  275. }
  276. }
  277. public Decimal? GetNullableDecimal(int ordinal)
  278. {
  279. LastOrdinal = ordinal;
  280. if (reader.IsDBNull(ordinal))
  281. {
  282. return null;
  283. }
  284. return GetDecimal(ordinal);
  285. }
  286. public Int16 GetInt16(int ordinal)
  287. {
  288. LastOrdinal = ordinal;
  289. switch (typeCodes[ordinal])
  290. {
  291. case TypeCode.Byte:
  292. return (Int16)reader.GetByte(ordinal);
  293. case TypeCode.Int16:
  294. return reader.GetInt16(ordinal);
  295. case TypeCode.Int32:
  296. return (Int16)reader.GetInt32(ordinal);
  297. case TypeCode.Int64:
  298. return (Int16)reader.GetInt64(ordinal);
  299. case TypeCode.Double:
  300. return (Int16)reader.GetDouble(ordinal);
  301. case TypeCode.Single:
  302. return (Int16)reader.GetFloat(ordinal);
  303. case TypeCode.Decimal:
  304. return (Int16)reader.GetDecimal(ordinal);
  305. default:
  306. return ReflectionTools.ChangeType<Int16>(reader.GetValue(ordinal));
  307. }
  308. }
  309. public Int16? GetNullableInt16(int ordinal)
  310. {
  311. LastOrdinal = ordinal;
  312. if (reader.IsDBNull(ordinal))
  313. {
  314. return null;
  315. }
  316. return GetInt16(ordinal);
  317. }
  318. public Int32 GetInt32(int ordinal)
  319. {
  320. LastOrdinal = ordinal;
  321. switch (typeCodes[ordinal])
  322. {
  323. case TypeCode.Byte:
  324. return (Int32)reader.GetByte(ordinal);
  325. case TypeCode.Int16:
  326. return (Int32)reader.GetInt16(ordinal);
  327. case TypeCode.Int32:
  328. return reader.GetInt32(ordinal);
  329. case TypeCode.Int64:
  330. return (Int32)reader.GetInt64(ordinal);
  331. case TypeCode.Double:
  332. return (Int32)reader.GetDouble(ordinal);
  333. case TypeCode.Single:
  334. return (Int32)reader.GetFloat(ordinal);
  335. case TypeCode.Decimal:
  336. return (Int32)reader.GetDecimal(ordinal);
  337. default:
  338. return ReflectionTools.ChangeType<Int32>(reader.GetValue(ordinal));
  339. }
  340. }
  341. public Int32? GetNullableInt32(int ordinal)
  342. {
  343. LastOrdinal = ordinal;
  344. if (reader.IsDBNull(ordinal))
  345. {
  346. return null;
  347. }
  348. return GetInt32(ordinal);
  349. }
  350. public Int64 GetInt64(int ordinal)
  351. {
  352. LastOrdinal = ordinal;
  353. switch (typeCodes[ordinal])
  354. {
  355. case TypeCode.Byte:
  356. return (Int64)reader.GetByte(ordinal);
  357. case TypeCode.Int16:
  358. return (Int64)reader.GetInt16(ordinal);
  359. case TypeCode.Int32:
  360. return (Int64)reader.GetInt32(ordinal);
  361. case TypeCode.Int64:
  362. return (Int64)reader.GetInt64(ordinal);
  363. case TypeCode.Double:
  364. return (Int64)reader.GetDouble(ordinal);
  365. case TypeCode.Single:
  366. return (Int64)reader.GetFloat(ordinal);
  367. case TypeCode.Decimal:
  368. return (Int64)reader.GetDecimal(ordinal);
  369. default:
  370. return ReflectionTools.ChangeType<Int64>(reader.GetValue(ordinal));
  371. }
  372. }
  373. public Int64? GetNullableInt64(int ordinal)
  374. {
  375. LastOrdinal = ordinal;
  376. if (reader.IsDBNull(ordinal))
  377. {
  378. return null;
  379. }
  380. return GetInt64(ordinal);
  381. }
  382. public DateTime GetDateTime(int ordinal)
  383. {
  384. LastOrdinal = ordinal;
  385. DateTime dt;
  386. switch (typeCodes[ordinal])
  387. {
  388. case TypeCode.DateTime:
  389. dt = reader.GetDateTime(ordinal);
  390. break;
  391. default:
  392. dt = ReflectionTools.ChangeType<DateTime>(reader.GetValue(ordinal));
  393. break;
  394. }
  395. if (Schema.Current.TimeZoneMode == TimeZoneMode.Utc)
  396. return new DateTime(dt.Ticks, DateTimeKind.Utc);
  397. return dt;
  398. }
  399. public DateTime? GetNullableDateTime(int ordinal)
  400. {
  401. LastOrdinal = ordinal;
  402. if (reader.IsDBNull(ordinal))
  403. {
  404. return null;
  405. }
  406. return GetDateTime(ordinal);
  407. }
  408. public DateTimeOffset GetDateTimeOffset(int ordinal)
  409. {
  410. LastOrdinal = ordinal;
  411. switch (typeCodes[ordinal])
  412. {
  413. case tcDateTimeOffset:
  414. return ((SqlDataReader)reader).GetDateTimeOffset(ordinal);
  415. default:
  416. return ReflectionTools.ChangeType<DateTimeOffset>(reader.GetValue(ordinal));
  417. }
  418. }
  419. public DateTimeOffset? GetNullableDateTimeOffset(int ordinal)
  420. {
  421. LastOrdinal = ordinal;
  422. if (reader.IsDBNull(ordinal))
  423. {
  424. return null;
  425. }
  426. return GetDateTimeOffset(ordinal);
  427. }
  428. public TimeSpan GetTimeSpan(int ordinal)
  429. {
  430. LastOrdinal = ordinal;
  431. switch (typeCodes[ordinal])
  432. {
  433. case tcTimeSpan:
  434. return ((SqlDataReader)reader).GetTimeSpan(ordinal);
  435. default:
  436. return ReflectionTools.ChangeType<TimeSpan>(reader.GetValue(ordinal));
  437. }
  438. }
  439. public TimeSpan? GetNullableTimeSpan(int ordinal)
  440. {
  441. LastOrdinal = ordinal;
  442. if (reader.IsDBNull(ordinal))
  443. {
  444. return null;
  445. }
  446. return GetTimeSpan(ordinal);
  447. }
  448. public Guid GetGuid(int ordinal)
  449. {
  450. LastOrdinal = ordinal;
  451. switch (typeCodes[ordinal])
  452. {
  453. case tcGuid:
  454. return reader.GetGuid(ordinal);
  455. default:
  456. return ReflectionTools.ChangeType<Guid>(reader.GetValue(ordinal));
  457. }
  458. }
  459. public Guid? GetNullableGuid(int ordinal)
  460. {
  461. LastOrdinal = ordinal;
  462. if (reader.IsDBNull(ordinal))
  463. {
  464. return null;
  465. }
  466. return GetGuid(ordinal);
  467. }
  468. static MethodInfo miGetUdt = ReflectionTools.GetMethodInfo((FieldReader r) => r.GetUdt<IBinarySerialize>(0)).GetGenericMethodDefinition();
  469. public T GetUdt<T>(int ordinal) where T : IBinarySerialize
  470. {
  471. LastOrdinal = ordinal;
  472. if (reader.IsDBNull(ordinal))
  473. {
  474. return (T)(object)null;
  475. }
  476. return (T)reader.GetValue(ordinal);
  477. }
  478. static Dictionary<Type, MethodInfo> methods =
  479. typeof(FieldReader).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
  480. .Where(m => m.Name != "GetExpression" && m.Name != "IsNull")
  481. .ToDictionary(a => a.ReturnType);
  482. public static Expression GetExpression(Expression reader, int ordinal, Type type)
  483. {
  484. MethodInfo mi = methods.TryGetC(type);
  485. if (mi != null)
  486. return Expression.Call(reader, mi, Expression.Constant(ordinal));
  487. if (typeof(IBinarySerialize).IsAssignableFrom(type.UnNullify()))
  488. {
  489. if (type.IsNullable())
  490. return Expression.Call(reader, miGetUdt.MakeGenericMethod(type.UnNullify()), Expression.Constant(ordinal)).Nullify();
  491. else
  492. return Expression.Call(reader, miGetUdt.MakeGenericMethod(type.UnNullify()), Expression.Constant(ordinal));
  493. }
  494. throw new InvalidOperationException("Type {0} not supported".Formato(type));
  495. }
  496. static MethodInfo miIsNull = ReflectionTools.GetMethodInfo((FieldReader r) => r.IsNull(0));
  497. public static Expression GetIsNull(Expression reader, int ordinal)
  498. {
  499. return Expression.Call(reader, miIsNull, Expression.Constant(ordinal));
  500. }
  501. internal FieldReaderException CreateFieldReaderException(Exception ex)
  502. {
  503. return new FieldReaderException(ex)
  504. {
  505. Ordinal = LastOrdinal,
  506. ColumnName = reader.GetName(LastOrdinal),
  507. ColumnType = reader.GetFieldType(LastOrdinal),
  508. };
  509. }
  510. }
  511. [Serializable]
  512. public class FieldReaderException : SqlTypeException
  513. {
  514. public FieldReaderException(Exception inner) : base(null, inner) { }
  515. protected FieldReaderException(
  516. System.Runtime.Serialization.SerializationInfo info,
  517. System.Runtime.Serialization.StreamingContext context)
  518. : base(info, context) { }
  519. public override string Message
  520. {
  521. get
  522. {
  523. string text = "{0}\r\nOrdinal: {1}\r\nColumnName: {2}\r\nRow: {3}".Formato(
  524. InnerException.Message, Ordinal, ColumnName, Row);
  525. if (Projector != null)
  526. {
  527. text += "\r\nCalling: row.Reader.Get{0}({1})".Formato(ColumnType.Name, Ordinal);
  528. text += "\r\nProjector:\r\n{0}".Formato(Projector.NiceToString().Indent(4));
  529. }
  530. if(Command != null)
  531. text += "\r\nCommand:\r\n{0}".Formato(Command.PlainSql().Indent(4));
  532. return text;
  533. }
  534. }
  535. public int Ordinal { get; internal set; }
  536. public string ColumnName { get; internal set; }
  537. public Type ColumnType { get; internal set; }
  538. public int Row { get; internal set; }
  539. public SqlPreCommand Command { get; internal set; }
  540. public LambdaExpression Projector { get; internal set; }
  541. }
  542. }