diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs
index 9be7b50..bf9cdd8 100644
--- a/AmalgamationTool/DynamORM.Amalgamation.cs
+++ b/AmalgamationTool/DynamORM.Amalgamation.cs
@@ -1,15883 +1,15338 @@
-62/*
- * DynamORM - Dynamic Object-Relational Mapping library.
- * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * See: http://opensource.org/licenses/bsd-license.php
- *
- * Supported preprocessor flags:
- * * DYNAMORM_OMMIT_OLDSYNTAX - Remove dynamic table functionality
- * * DYNAMORM_OMMIT_GENERICEXECUTION - Remove generic execution functionality
- * * DYNAMORM_OMMIT_TRYPARSE - Remove TryParse helpers (also applies DYNAMORM_OMMIT_GENERICEXECUTION)
-*/
-
-using DynamORM.Builders.Extensions;
-using DynamORM.Builders.Implementation;
-using DynamORM.Builders;
-using DynamORM.Helpers.Dynamics;
-using DynamORM.Helpers;
-using DynamORM.Mapper;
-using DynamORM.Validation;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Collections;
-using System.ComponentModel;
-using System.Data.Common;
-using System.Data;
-using System.Dynamic;
-using System.IO;
-using System.Linq.Expressions;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
-using System.Text.RegularExpressions;
-using System.Text;
-using System;
-
-[module: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "This is a generated file which generates all the necessary support classes.")]
-[module: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1403:FileMayOnlyContainASingleNamespace", Justification = "This is a generated file which generates all the necessary support classes.")]
-
-namespace DynamORM
-{
- /// Cache data reader in memory.
- public class DynamicCachedReader : DynamicObject, IDataReader
- {
- #region Constructor and Data
-
- private class Data
- {
- internal DataTable _schema;
- internal int _fields;
- internal int _rows;
- internal int _rowsAffected;
- internal int _position = -1;
- internal int _cachePos = -1;
-
- internal IList _names;
- internal IDictionary _ordinals;
- internal IList _types;
- internal IList _cache;
- }
-
- private List _data = new List();
- private int _currentDataPosition = 0;
-
- private DynamicCachedReader()
- {
- }
-
- /// Initializes a new instance of the class.
- /// Reader to cache.
- /// The offset row.
- /// The limit to number of tows. -1 is no limit.
- /// The progress delegate.
- public DynamicCachedReader(IDataReader reader, int offset = 0, int limit = -1,
- Func progress = null)
- {
- InitDataReader(reader, offset, limit, progress);
- }
-
- #endregion Constructor and Data
-
- #region Helpers
-
- /// Create data reader from dynamic enumerable.
- /// List of objects.
- /// Instance of containing objects data.
- public static DynamicCachedReader FromDynamicEnumerable(IEnumerable objects)
- {
- var first = (objects as IEnumerable).FirstOrDefault();
-
- if (first == null)
- return null;
-
- var firstDict = first as IDictionary;
- var r = new DynamicCachedReader();
- r.Init(firstDict.Keys.Count);
-
- r._data.Add(new Data());
-
- var data = r._data[r._currentDataPosition];
-
- for (int i = 0; i < firstDict.Keys.Count; i++)
- data._types.Add(null);
-
- foreach (dynamic elem in (objects as IEnumerable))
- {
- int c = 0;
- var dict = elem as IDictionary;
-
- foreach (var k in firstDict.Keys)
- {
- object val = dict[k];
-
- data._cache.Add(val);
-
- if (data._types[c] == null && val != null)
- data._types[c] = val.GetType();
-
- c++;
- }
-
- data._rows++;
- }
-
- for (int i = 0; i < firstDict.Keys.Count; i++)
- if (data._types[i] == null)
- data._types[i] = typeof(string);
-
- data._schema = new DataTable("DYNAMIC");
- data._schema.Columns.Add(new DataColumn("ColumnName", typeof(string)));
- data._schema.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int)));
- data._schema.Columns.Add(new DataColumn("ColumnSize", typeof(int)));
- data._schema.Columns.Add(new DataColumn("NumericPrecision", typeof(short)));
- data._schema.Columns.Add(new DataColumn("NumericScale", typeof(short)));
- data._schema.Columns.Add(new DataColumn("DataType", typeof(Type)));
- data._schema.Columns.Add(new DataColumn("ProviderType", typeof(int)));
- data._schema.Columns.Add(new DataColumn("NativeType", typeof(int)));
- data._schema.Columns.Add(new DataColumn("AllowDBNull", typeof(bool)));
- data._schema.Columns.Add(new DataColumn("IsUnique", typeof(bool)));
- data._schema.Columns.Add(new DataColumn("IsKey", typeof(bool)));
- data._schema.Columns.Add(new DataColumn("IsAutoIncrement", typeof(bool)));
-
- int ordinal = 0;
- DataRow dr = null;
-
- foreach (var column in firstDict.Keys)
- {
- dr = data._schema.NewRow();
-
- dr[0] = column;
- dr[1] = ordinal;
- dr[2] = 0;
- dr[3] = 0;
- dr[4] = 0;
- dr[5] = data._types[ordinal];
- dr[6] = data._types[ordinal].ToDbType();
- dr[7] = data._types[ordinal].ToDbType();
- dr[8] = true;
- dr[9] = false;
- dr[10] = false;
- dr[11] = false;
-
- data._schema.Rows.Add(dr);
-
- data._names.Add(dr[0].ToString());
- data._ordinals.Add(dr[0].ToString().ToUpper(), ordinal++);
- data._types.Add((Type)dr[5]);
-
- dr.AcceptChanges();
- }
-
- dr.AcceptChanges();
-
- return r;
- }
-
- /// Create data reader from enumerable.
- /// Type of enumerated objects.
- /// List of objects.
- /// Instance of containing objects data.
- public static DynamicCachedReader FromEnumerable(IEnumerable objects)
- {
- var mapper = DynamicMapperCache.GetMapper();
-
- if (mapper == null)
- throw new InvalidCastException(string.Format("Object type '{0}' can't be mapped.", typeof(T).FullName));
-
- var r = new DynamicCachedReader();
- r.Init(mapper.ColumnsMap.Count + 1);
- r.CreateSchemaTable(mapper);
- r.FillFromEnumerable(objects, mapper);
-
- r.IsClosed = false;
-
- return r;
- }
-
- /// Create data reader from enumerable.
- /// Type of enumerated objects.
- /// List of objects.
- /// Instance of containing objects data.
- public static DynamicCachedReader FromEnumerable(Type elementType, IEnumerable objects)
- {
- var mapper = DynamicMapperCache.GetMapper(elementType);
-
- if (mapper == null)
- throw new InvalidCastException(
- string.Format("Object type '{0}' can't be mapped.", elementType.FullName));
-
- var r = new DynamicCachedReader();
- r.Init(mapper.ColumnsMap.Count + 1);
- r.CreateSchemaTable(mapper);
- r.FillFromEnumerable(elementType, objects, mapper);
-
- r.IsClosed = false;
-
- return r;
- }
-
- private void InitDataReader(IDataReader reader, int offset = 0, int limit = -1,
- Func progress = null)
- {
- do
- {
- Init(reader.FieldCount);
-
- var data = _data[_currentDataPosition];
-
- data._schema = reader.GetSchemaTable();
- data._rowsAffected = reader.RecordsAffected;
-
- int i = 0;
-
- for (i = 0; i < data._fields; i++)
- {
- data._names.Add(reader.GetName(i));
- data._types.Add(reader.GetFieldType(i));
-
- if (!data._ordinals.ContainsKey(reader.GetName(i).ToUpper()))
- data._ordinals.Add(reader.GetName(i).ToUpper(), i);
- }
-
- int current = 0;
- while (reader.Read())
- {
- if (current < offset)
- {
- current++;
- continue;
- }
-
- for (i = 0; i < data._fields; i++)
- data._cache.Add(reader[i]);
-
- data._rows++;
- current++;
-
- if (limit >= 0 && data._rows >= limit)
- break;
-
- if (progress != null && !progress(this, data._rows))
- break;
- }
-
- IsClosed = false;
- data._position = -1;
- data._cachePos = -1;
-
- if (progress != null)
- progress(this, data._rows);
- } while (reader.NextResult());
-
- reader.Close();
- }
-
- private void FillFromEnumerable(IEnumerable objects, DynamicTypeMap mapper)
- {
- var data = _data[_currentDataPosition];
- foreach (var elem in objects)
- {
- foreach (var col in mapper.ColumnsMap)
- {
- object val = null;
-
- if (col.Value.Get != null)
- val = col.Value.Get(elem);
-
- data._cache.Add(val);
- }
-
- data._cache.Add(elem);
-
- data._rows++;
- }
- }
-
- private void FillFromEnumerable(Type elementType, IEnumerable objects, DynamicTypeMap mapper)
- {
- var data = _data[_currentDataPosition];
-
- foreach (var elem in objects)
- {
- foreach (var col in mapper.ColumnsMap)
- {
- object val = null;
-
- if (col.Value.Get != null)
- val = col.Value.Get(elem);
-
- data._cache.Add(val);
- }
-
- data._cache.Add(elem);
-
- data._rows++;
- }
- }
-
- private void CreateSchemaTable(DynamicTypeMap mapper)
- {
- var data = _data[_currentDataPosition];
- data._schema = new DataTable("DYNAMIC");
- data._schema.Columns.Add(new DataColumn("ColumnName", typeof(string)));
- data._schema.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int)));
- data._schema.Columns.Add(new DataColumn("ColumnSize", typeof(int)));
- data._schema.Columns.Add(new DataColumn("NumericPrecision", typeof(short)));
- data._schema.Columns.Add(new DataColumn("NumericScale", typeof(short)));
- data._schema.Columns.Add(new DataColumn("DataType", typeof(Type)));
- data._schema.Columns.Add(new DataColumn("ProviderType", typeof(int)));
- data._schema.Columns.Add(new DataColumn("NativeType", typeof(int)));
- data._schema.Columns.Add(new DataColumn("AllowDBNull", typeof(bool)));
- data._schema.Columns.Add(new DataColumn("IsUnique", typeof(bool)));
- data._schema.Columns.Add(new DataColumn("IsKey", typeof(bool)));
- data._schema.Columns.Add(new DataColumn("IsAutoIncrement", typeof(bool)));
-
- int ordinal = 0;
- DataRow dr = null;
-
- foreach (var column in mapper.ColumnsMap)
- {
- dr = data._schema.NewRow();
-
- dr[0] = column.Value.Column.NullOr(x => x.Name ?? column.Value.Name, column.Value.Name);
- dr[1] = ordinal;
- dr[2] = column.Value.Column.NullOr(x => x.Size ?? int.MaxValue, int.MaxValue);
- dr[3] = column.Value.Column.NullOr(x => x.Precision ?? 0, 0);
- dr[4] = column.Value.Column.NullOr(x => x.Scale ?? 0, 0);
- dr[5] = column.Value.Column.NullOr(x => x.Type.HasValue ? x.Type.Value.ToType() : column.Value.Type,
- column.Value.Type);
- dr[6] = column.Value.Column.NullOr(x => x.Type ?? column.Value.Type.ToDbType(),
- column.Value.Type.ToDbType());
- dr[7] = column.Value.Column.NullOr(x => x.Type ?? column.Value.Type.ToDbType(),
- column.Value.Type.ToDbType());
- dr[8] = column.Value.Column.NullOr(x => x.IsKey, false)
- ? true
- : column.Value.Column.NullOr(x => x.AllowNull, true);
- dr[9] = column.Value.Column.NullOr(x => x.IsUnique, false);
- dr[10] = column.Value.Column.NullOr(x => x.IsKey, false);
- dr[11] = false;
-
- data._schema.Rows.Add(dr);
-
- data._names.Add(dr[0].ToString());
- data._ordinals.Add(dr[0].ToString().ToUpper(), ordinal++);
- data._types.Add((Type)dr[5]);
-
- dr.AcceptChanges();
- }
-
- dr = data._schema.NewRow();
-
- dr[0] = "#O";
- dr[1] = ordinal;
- dr[2] = int.MaxValue;
- dr[3] = 0;
- dr[4] = 0;
- dr[5] = mapper.Type;
- dr[6] = DbType.Object;
- dr[7] = DbType.Object;
- dr[8] = true;
- dr[9] = false;
- dr[10] = false;
- dr[11] = false;
-
- data._schema.Rows.Add(dr);
-
- data._names.Add("#O");
- data._ordinals.Add("#O".ToUpper(), ordinal++);
- data._types.Add(mapper.Type);
-
- dr.AcceptChanges();
- }
-
- private void Init(int fieldCount)
- {
- _data.Add(new Data()
- {
- _rows = 0,
- _fields = fieldCount,
- _names = new List(fieldCount),
- _ordinals = new Dictionary(fieldCount),
- _types = new List(fieldCount),
- _cache = new List(fieldCount * 100),
- });
-
- _currentDataPosition = _data.Count - 1;
- }
-
- /// Sets the current position in reader.
- /// The position.
- public void SetPosition(int pos)
- {
- if (pos >= -1 && pos < _data[_currentDataPosition]._rows)
- {
- _data[_currentDataPosition]._position = pos;
- _data[_currentDataPosition]._cachePos =
- _data[_currentDataPosition]._position * _data[_currentDataPosition]._fields;
- }
- else
- throw new IndexOutOfRangeException();
- }
-
- #endregion Helpers
-
- #region IDataReader Members
-
- /// Closes the System.Data.IDataReader Object.
- public void Close()
- {
- IsClosed = true;
- _currentDataPosition = -1;
- }
-
- /// Gets a value indicating the depth of nesting for the current row.
- /// This implementation use this field to indicate row count.
- public int Depth
- {
- get { return _data[_currentDataPosition]._rows; }
- }
-
- /// Returns a System.Data.DataTable that describes the column metadata of the
- /// System.Data.IDataReader. A System.Data.DataTable that describes
- /// the column metadata.
- /// The System.Data.IDataReader is closed.
- public DataTable GetSchemaTable()
- {
- return _data[_currentDataPosition]._schema;
- }
-
- /// Gets a value indicating whether the data reader is closed.
- public bool IsClosed { get; private set; }
-
- /// Advances the data reader to the next result, when reading the results of batch SQL statements.
- /// Returns true if there are more rows; otherwise, false.
- public bool NextResult()
- {
- _currentDataPosition++;
-
- return _data.Count < _currentDataPosition;
- }
-
- /// Advances the System.Data.IDataReader to the next record.
- /// Returns true if there are more rows; otherwise, false.
- public bool Read()
- {
- var data = _data[_currentDataPosition];
-
- data._cachePos = (++data._position) * data._fields;
-
- return data._position < data._rows;
- }
-
- /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement.
- /// The number of rows changed, inserted, or deleted; 0 if no rows were affected or the statement
- /// failed; and -1 for SELECT statements.
- public int RecordsAffected
- {
- get { return _data[_currentDataPosition]._rowsAffected; }
- }
-
- #endregion IDataReader Members
-
- #region IDisposable Members
-
- /// Performs application-defined tasks associated with
- /// freeing, releasing, or resetting unmanaged resources.
- public void Dispose()
- {
- foreach (var data in _data)
- {
- data._names.Clear();
- data._types.Clear();
- data._cache.Clear();
- data._schema.Dispose();
- }
-
- _data.Clear();
- }
-
- #endregion IDisposable Members
-
- #region IDataRecord Members
-
- /// Gets the number of columns in the current row.
- /// When not positioned in a valid record set, 0; otherwise, the number of columns in the current record. The default is -1.
- public int FieldCount
- {
- get { return _data[_currentDataPosition]._fields; }
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public bool GetBoolean(int i)
- {
- var data = _data[_currentDataPosition];
- return (bool)data._cache[data._cachePos + i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public byte GetByte(int i)
- {
- var data = _data[_currentDataPosition];
- return (byte)data._cache[data._cachePos + i];
- }
-
- /// Reads a stream of bytes from the specified column offset into the buffer
- /// as an array, starting at the given buffer offset.
- /// The index of the field to find.
- /// The index within the field from which to start the read operation.
- /// The buffer into which to read the stream of bytes.
- /// The index for buffer to start the read operation.
- /// The number of bytes to read.
- /// The actual number of bytes read.
- public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
- {
- var data = _data[_currentDataPosition];
-
- using (MemoryStream ms = new MemoryStream((byte[])data._cache[data._cachePos + i]))
- return ms.Read(buffer, bufferoffset, length);
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public char GetChar(int i)
- {
- var data = _data[_currentDataPosition];
- return (char)data._cache[data._cachePos + i];
- }
-
- /// Reads a stream of characters from the specified column offset into the buffer
- /// as an array, starting at the given buffer offset.
- /// The zero-based column ordinal.
- /// The index within the row from which to start the read operation.
- /// The buffer into which to read the stream of bytes.
- /// The index for buffer to start the read operation.
- /// The number of bytes to read.
- /// The actual number of characters read.
- public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
- {
- var data = _data[_currentDataPosition];
-
- using (MemoryStream ms = new MemoryStream((byte[])data._cache[data._cachePos + i]))
- {
- byte[] buff = new byte[buffer.Length];
- long ret = ms.Read(buff, bufferoffset, length);
-
- for (int n = bufferoffset; n < ret; n++)
- buffer[n] = (char)buff[n];
-
- return ret;
- }
- }
-
- /// Returns an System.Data.IDataReader for the specified column ordinal.
- /// The index of the field to find.
- /// An System.Data.IDataReader.
- public IDataReader GetData(int i)
- {
- return null;
- }
-
- /// Gets the data type information for the specified field.
- /// The index of the field to find.
- /// The data type information for the specified field.
- public string GetDataTypeName(int i)
- {
- return _data[_currentDataPosition]._types[i].Name;
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public DateTime GetDateTime(int i)
- {
- var data = _data[_currentDataPosition];
- return (DateTime)data._cache[data._cachePos + i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public decimal GetDecimal(int i)
- {
- var data = _data[_currentDataPosition];
- return (decimal)data._cache[data._cachePos + i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public double GetDouble(int i)
- {
- var data = _data[_currentDataPosition];
- return (double)data._cache[data._cachePos + i];
- }
-
- /// Gets the System.Type information corresponding to the type of System.Object
- /// that would be returned from System.Data.IDataRecord.GetValue(System.Int32).
- /// The index of the field to find.
- /// The System.Type information corresponding to the type of System.Object that
- /// would be returned from System.Data.IDataRecord.GetValue(System.Int32).
- public Type GetFieldType(int i)
- {
- return _data[_currentDataPosition]._types[i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public float GetFloat(int i)
- {
- var data = _data[_currentDataPosition];
- return (float)data._cache[data._cachePos + i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public Guid GetGuid(int i)
- {
- var data = _data[_currentDataPosition];
- return (Guid)data._cache[data._cachePos + i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public short GetInt16(int i)
- {
- var data = _data[_currentDataPosition];
- return (short)data._cache[data._cachePos + i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public int GetInt32(int i)
- {
- var data = _data[_currentDataPosition];
- return (int)data._cache[data._cachePos + i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public long GetInt64(int i)
- {
- var data = _data[_currentDataPosition];
- return (long)data._cache[data._cachePos + i];
- }
-
- /// Gets the name for the field to find.
- /// The index of the field to find.
- /// The name of the field or the empty string (""), if there is no value to return.
- public string GetName(int i)
- {
- return _data[_currentDataPosition]._names[i];
- }
-
- /// Return the index of the named field.
- /// The name of the field to find.
- /// The index of the named field.
- public int GetOrdinal(string name)
- {
- var data = _data[_currentDataPosition];
-
- if (data._ordinals.ContainsKey(name.ToUpper()))
- return data._ordinals[name.ToUpper()];
-
- return -1;
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public string GetString(int i)
- {
- var data = _data[_currentDataPosition];
-
- return (string)data._cache[data._cachePos + i];
- }
-
- /// Return the value of the specified field.
- /// The index of the field to find.
- /// Field value upon return.
- public object GetValue(int i)
- {
- var data = _data[_currentDataPosition];
-
- return data._cache[data._cachePos + i];
- }
-
- /// Gets all the attribute fields in the collection for the current record.
- /// An array of System.Object to copy the attribute fields into.
- /// The number of instances of System.Object in the array.
- public int GetValues(object[] values)
- {
- var data = _data[_currentDataPosition];
-
- for (int i = 0; i < data._fields; i++)
- values[i] = data._cache[data._cachePos + i];
-
- return data._fields;
- }
-
- /// Return whether the specified field is set to null.
- /// The index of the field to find.
- /// Returns true if the specified field is set to null; otherwise, false.
- public bool IsDBNull(int i)
- {
- var data = _data[_currentDataPosition];
- return data._cache[data._cachePos + i] == null || data._cache[data._cachePos + i] == DBNull.Value;
- }
-
- /// Gets or sets specified value in current record.
- /// Name of column.
- /// Value of specified column.
- public object this[string name]
- {
- get
- {
- var data = _data[_currentDataPosition];
-
- if (data._ordinals.ContainsKey(name.ToUpper()))
- return data._cache[data._cachePos + data._ordinals[name.ToUpper()]];
-
- throw new IndexOutOfRangeException(String.Format("Field '{0}' not found.", name));
- }
- }
-
- /// Gets or sets specified value in current record.
- /// The index of the field to find.
- /// Value of specified column.
- public object this[int i]
- {
- get
- {
- var data = _data[_currentDataPosition];
- return data._cache[data._cachePos + i];
- }
- }
-
- #endregion IDataRecord Members
- }
-
- /// Small utility class to manage single columns.
- public class DynamicColumn
- {
- #region Enums
-
- /// Order By Order.
- public enum SortOrder
- {
- /// Ascending order.
- Asc,
-
- /// Descending order.
- Desc
- }
-
- /// Dynamic query operators.
- public enum CompareOperator
- {
- /// Equals operator (default).
- Eq,
-
- /// Not equal operator.
- Not,
-
- /// Like operator.
- Like,
-
- /// Not like operator.
- NotLike,
-
- /// In operator.
- In,
-
- /// Less than operator.
- Lt,
-
- /// Less or equal operator.
- Lte,
-
- /// Greater than operator.
- Gt,
-
- /// Greater or equal operator.
- Gte,
-
- /// Between two values.
- Between,
- }
-
- #endregion Enums
-
- #region Constructors
-
- /// Initializes a new instance of the class.
- public DynamicColumn()
- {
- ParameterDirection = ParameterDirection.Input;
- }
-
- /// Initializes a new instance of the class.
- /// Constructor provided for easier object creation in queries.
- /// Name of column to set.
- public DynamicColumn(string columnName)
- : this()
- {
- ColumnName = columnName;
- }
-
- /// Initializes a new instance of the class.
- /// Constructor provided for easier object creation in queries.
- /// Name of column to set.
- /// Compare column to value(s) operator.
- /// Parameter value(s).
- public DynamicColumn(string columnName, CompareOperator oper, object value)
- : this(columnName)
- {
- Operator = oper;
- Value = value;
- }
-
- #endregion Constructors
-
- #region Properties
-
- /// Gets or sets column name.
- public string ColumnName { get; set; }
-
- /// Gets or sets column alias.
- /// Select specific.
- public string Alias { get; set; }
-
- /// Gets or sets aggregate function used on column.
- /// Select specific.
- public string Aggregate { get; set; }
-
- /// Gets or sets order direction.
- public SortOrder Order { get; set; }
-
- /// Gets or sets parameter direction when used in procedure invocation.
- public ParameterDirection ParameterDirection { get; set; }
-
- /// Gets or sets value for parameters.
- public object Value { get; set; }
-
- /// Gets or sets condition operator.
- public CompareOperator Operator { get; set; }
-
- /// Gets or sets a value indicating whether this condition will be treated as or condition.
- public bool Or { get; set; }
-
- /// Gets or sets a value indicating whether start new block in where statement.
- public bool BeginBlock { get; set; }
-
- /// Gets or sets a value indicating whether end existing block in where statement.
- public bool EndBlock { get; set; }
-
- /// Gets or sets a value indicating whether set parameters for null values.
- public bool? VirtualColumn { get; set; }
-
- /// Gets or sets schema representation of a column.
- /// Workaround to providers issues which sometimes pass wrong
- /// data o schema. For example decimal has precision of 255 in SQL
- /// server.
- public DynamicSchemaColumn? Schema { get; set; }
-
- #endregion Properties
-
- #region Query creation helpers
-
- #region Operators
-
- private DynamicColumn SetOperatorAndValue(CompareOperator c, object v)
- {
- Operator = c;
- Value = v;
-
- return this;
- }
-
- /// Helper method setting
- /// to and
- /// to provided value .
- /// Value of parameter to set.
- /// Returns self.
- public DynamicColumn Eq(object value)
- {
- return SetOperatorAndValue(CompareOperator.Eq, value);
- }
-
- /// Helper method setting
- /// to and
- /// to provided value .
- /// Value of parameter to set.
- /// Returns self.
- public DynamicColumn Not(object value)
- {
- return SetOperatorAndValue(CompareOperator.Not, value);
- }
-
- /// Helper method setting
- /// to and
- /// to provided value .
- /// Value of parameter to set.
- /// Returns self.
- public DynamicColumn Like(object value)
- {
- return SetOperatorAndValue(CompareOperator.Like, value);
- }
-
- /// Helper method setting
- /// to and
- /// to provided value .
- /// Value of parameter to set.
- /// Returns self.
- public DynamicColumn NotLike(object value)
- {
- return SetOperatorAndValue(CompareOperator.NotLike, value);
- }
-
- /// Helper method setting
- /// to and
- /// to provided value .
- /// Value of parameter to set.
- /// Returns self.
- public DynamicColumn Greater(object value)
- {
- return SetOperatorAndValue(CompareOperator.Gt, value);
- }
-
- /// Helper method setting
- /// to and
- /// to provided value .
- /// Value of parameter to set.
- /// Returns self.
- public DynamicColumn Less(object value)
- {
- return SetOperatorAndValue(CompareOperator.Lt, value);
- }
-
- /// Helper method setting
- /// to and
- /// to provided value .
- /// Value of parameter to set.
- /// Returns self.
- public DynamicColumn GreaterOrEqual(object value)
- {
- return SetOperatorAndValue(CompareOperator.Gte, value);
- }
-
- /// Helper method setting
- /// to and
- /// to provided value .
- /// Value of parameter to set.
- /// Returns self.
- public DynamicColumn LessOrEqual(object value)
- {
- return SetOperatorAndValue(CompareOperator.Lte, value);
- }
-
- /// Helper method setting
- /// to and
- /// to provided values.
- /// Value of from parameter to set.
- /// Value of to parameter to set.
- /// Returns self.
- public DynamicColumn Between(object from, object to)
- {
- return SetOperatorAndValue(CompareOperator.Between, new[] { from, to });
- }
-
- /// Helper method setting
- /// to and
- /// to provided values.
- /// Values of parameters to set.
- /// Returns self.
- public DynamicColumn In(IEnumerable values)
- {
- return SetOperatorAndValue(CompareOperator.In, values);
- }
-
- /// Helper method setting
- /// to and
- /// to provided values.
- /// Values of parameters to set.
- /// Returns self.
- public DynamicColumn In(params object[] values)
- {
- if (values.Length == 1 && (values[0].GetType().IsCollection() || values[0] is IEnumerable))
- return SetOperatorAndValue(CompareOperator.In, values[0]);
-
- return SetOperatorAndValue(CompareOperator.In, values);
- }
-
- #endregion Operators
-
- #region Order
-
- /// Helper method setting
- /// to ..
- /// Returns self.
- public DynamicColumn Asc()
- {
- Order = SortOrder.Asc;
- return this;
- }
-
- /// Helper method setting
- /// to ..
- /// Returns self.
- public DynamicColumn Desc()
- {
- Order = SortOrder.Desc;
- return this;
- }
-
- #endregion Order
-
- #region Other
-
- /// Helper method setting
- ///
- /// to provided name .
- /// Name to set.
- /// Returns self.
- public DynamicColumn SetName(string name)
- {
- ColumnName = name;
- return this;
- }
-
- /// Helper method setting
- ///
- /// to provided alias .
- /// Alias to set.
- /// Returns self.
- public DynamicColumn SetAlias(string alias)
- {
- Alias = alias;
- return this;
- }
-
- /// Helper method setting
- ///
- /// to provided aggregate .
- /// Aggregate to set.
- /// Returns self.
- public DynamicColumn SetAggregate(string aggregate)
- {
- Aggregate = aggregate;
- return this;
- }
-
- /// Sets the begin block flag.
- /// If set to true [begin].
- /// Returns self.
- public DynamicColumn SetBeginBlock(bool begin = true)
- {
- BeginBlock = begin;
- return this;
- }
-
- /// Sets the end block flag.
- /// If set to true [end].
- /// Returns self.
- public DynamicColumn SetEndBlock(bool end = true)
- {
- EndBlock = end;
- return this;
- }
-
- /// Sets the or flag.
- /// If set to true [or].
- /// Returns self.
- public DynamicColumn SetOr(bool or = true)
- {
- Or = or;
- return this;
- }
-
- /// Sets the virtual column.
- /// Set virtual column value.
- /// Returns self.
- public DynamicColumn SetVirtualColumn(bool? virt)
- {
- VirtualColumn = virt;
- return this;
- }
-
- #endregion Other
-
- #endregion Query creation helpers
-
- #region Parsing
-
- /// Parse column for select query.
- /// Column format consist of Column Name , Alias and
- /// Aggregate function in this order separated by ': '.
- /// Column string.
- /// Instance of .
- public static DynamicColumn ParseSelectColumn(string column)
- {
- // Split column description
- string[] parts = column.Split(':');
-
- if (parts.Length > 0)
- {
- DynamicColumn ret = new DynamicColumn() { ColumnName = parts[0] };
-
- if (parts.Length > 1)
- ret.Alias = parts[1];
-
- if (parts.Length > 2)
- ret.Aggregate = parts[2];
-
- return ret;
- }
-
- return null;
- }
-
- /// Parse column for order by in query.
- /// Column format consist of Column Name and
- /// Direction in this order separated by ': '.
- /// Column string.
- /// Instance of .
- public static DynamicColumn ParseOrderByColumn(string column)
- {
- // Split column description
- string[] parts = column.Split(':');
-
- if (parts.Length > 0)
- {
- DynamicColumn ret = new DynamicColumn() { ColumnName = parts[0] };
-
- if (parts.Length > 1)
- ret.Order = parts[1].ToLower() == "d" || parts[1].ToLower() == "desc"
- ? SortOrder.Desc
- : SortOrder.Asc;
-
- if (parts.Length > 2)
- ret.Alias = parts[2];
-
- return ret;
- }
-
- return null;
- }
-
- #endregion Parsing
-
- #region ToSQL
-
- internal string ToSQLSelectColumn(DynamicDatabase db)
- {
- StringBuilder sb = new StringBuilder();
- ToSQLSelectColumn(db, sb);
- return sb.ToString();
- }
-
- internal void ToSQLSelectColumn(DynamicDatabase db, StringBuilder sb)
- {
- string column = ColumnName == "*" ? "*" : ColumnName;
-
- if (column != "*" &&
- (column.IndexOf(db.LeftDecorator) == -1 || column.IndexOf(db.RightDecorator) == -1) &&
- (column.IndexOf('(') == -1 || column.IndexOf(')') == -1))
- column = db.DecorateName(column);
-
- string alias = Alias;
-
- if (!string.IsNullOrEmpty(Aggregate))
- {
- sb.AppendFormat("{0}({1})", Aggregate, column);
-
- alias = string.IsNullOrEmpty(alias)
- ? ColumnName == "*" ? Guid.NewGuid().ToString() : ColumnName
- : alias;
- }
- else
- sb.Append(column);
-
- if (!string.IsNullOrEmpty(alias))
- sb.AppendFormat(" AS {0}", alias);
- }
-
- internal string ToSQLGroupByColumn(DynamicDatabase db)
- {
- StringBuilder sb = new StringBuilder();
- ToSQLGroupByColumn(db, sb);
- return sb.ToString();
- }
-
- internal void ToSQLGroupByColumn(DynamicDatabase db, StringBuilder sb)
- {
- sb.Append(db.DecorateName(ColumnName));
- }
-
- internal string ToSQLOrderByColumn(DynamicDatabase db)
- {
- StringBuilder sb = new StringBuilder();
- ToSQLOrderByColumn(db, sb);
- return sb.ToString();
- }
-
- internal void ToSQLOrderByColumn(DynamicDatabase db, StringBuilder sb)
- {
- if (!string.IsNullOrEmpty(Alias))
- sb.Append(Alias);
- else
- sb.Append(db.DecorateName(ColumnName));
-
- sb.AppendFormat(" {0}", Order.ToString().ToUpper());
- }
-
- #endregion ToSQL
- }
-
- /// Helper class to easy manage command.
- public class DynamicCommand : IDbCommand, IExtendedDisposable
- {
- private IDbCommand _command;
- private int? _commandTimeout = null;
- private DynamicConnection _con;
- private DynamicDatabase _db;
- ////private long _poolStamp = 0;
-
- /// Initializes a new instance of the class.
- /// The connection.
- /// The database manager.
- internal DynamicCommand(DynamicConnection con, DynamicDatabase db)
- {
- IsDisposed = false;
- _con = con;
- _db = db;
-
- lock (_db.SyncLock)
- {
- if (!_db.CommandsPool.ContainsKey(_con.Connection))
- throw new InvalidOperationException("Can't create command using disposed connection.");
- else
- {
- _command = _con.Connection.CreateCommand();
- _db.CommandsPool[_con.Connection].Add(this);
- }
- }
- }
-
- /// Initializes a new instance of the class.
- /// The database manager.
- /// Used internally to create command without context.
- internal DynamicCommand(DynamicDatabase db)
- {
- IsDisposed = false;
- _db = db;
- _command = db.Provider.CreateCommand();
- }
-
- /// Prepare command for execution.
- /// Returns edited instance.
- internal IDbCommand PrepareForExecution()
- {
- // TODO: Fix that
- ////if (_poolStamp < _db.PoolStamp)
- {
- _command.CommandTimeout = _commandTimeout ?? _db.CommandTimeout ?? _command.CommandTimeout;
-
- if (_db.TransactionPool[_command.Connection].Count > 0)
- _command.Transaction = _db.TransactionPool[_command.Connection].Peek();
- else
- _command.Transaction = null;
-
- ////_poolStamp = _db.PoolStamp;
- }
-
- if (_db.DumpCommands)
- _db.DumpCommand(_command);
-
- return _command;
- }
-
- #region IDbCommand Members
-
- ///
- /// Attempts to cancels the execution of an .
- ///
- public void Cancel()
- {
- _command.Cancel();
- }
-
- ///
- /// Gets or sets the text command to run against the data source.
- ///
- /// The text command to execute. The default value is an empty string ("").
- public string CommandText
- {
- get { return _command.CommandText; }
- set { _command.CommandText = value; }
- }
-
- ///
- /// Gets or sets the wait time before terminating the attempt to execute a command and generating an error.
- ///
- /// The time (in seconds) to wait for the command to execute. The default value is 30 seconds.
- /// The property value assigned is less than 0.
- public int CommandTimeout
- {
- get { return _commandTimeout ?? _command.CommandTimeout; }
- set { _commandTimeout = value; }
- }
-
- /// Gets or sets how the property is interpreted.
- public CommandType CommandType
- {
- get { return _command.CommandType; }
- set { _command.CommandType = value; }
- }
-
- /// Gets or sets the
- /// used by this instance of the .
- /// The connection to the data source.
- public IDbConnection Connection
- {
- get { return _con; }
-
- set
- {
- _con = value as DynamicConnection;
-
- if (_con != null)
- {
- ////_poolStamp = 0;
- _command.Connection = _con.Connection;
- }
- else if (value == null)
- {
- _command.Transaction = null;
- _command.Connection = null;
- }
- else
- throw new InvalidOperationException(
- "Can't assign direct IDbConnection implementation. This property accepts only DynamORM implementation of IDbConnection.");
- }
- }
-
- /// Creates a new instance of an
- /// object.
- /// An object.
- public IDbDataParameter CreateParameter()
- {
- return _command.CreateParameter();
- }
-
- /// Executes an SQL statement against the Connection object of a
- /// data provider, and returns the number of rows affected.
- /// The number of rows affected.
- public int ExecuteNonQuery()
- {
- try
- {
- return PrepareForExecution().ExecuteNonQuery();
- }
- catch (Exception ex)
- {
- throw new DynamicQueryException(ex, this);
- }
- }
-
- /// Executes the
- /// against the ,
- /// and builds an using one
- /// of the values.
- /// One of the
- /// values.
- /// An object.
- public IDataReader ExecuteReader(CommandBehavior behavior)
- {
- try
- {
- return PrepareForExecution().ExecuteReader(behavior);
- }
- catch (Exception ex)
- {
- throw new DynamicQueryException(ex, this);
- }
- }
-
- /// Executes the
- /// against the and
- /// builds an .
- /// An object.
- public IDataReader ExecuteReader()
- {
- try
- {
- return PrepareForExecution().ExecuteReader();
- }
- catch (Exception ex)
- {
- throw new DynamicQueryException(ex, this);
- }
- }
-
- /// Executes the query, and returns the first column of the
- /// first row in the result set returned by the query. Extra columns or
- /// rows are ignored.
- /// The first column of the first row in the result set.
- public object ExecuteScalar()
- {
- try
- {
- return PrepareForExecution().ExecuteScalar();
- }
- catch (Exception ex)
- {
- throw new DynamicQueryException(ex, this);
- }
- }
-
- /// Gets the .
- public IDataParameterCollection Parameters
- {
- get { return _command.Parameters; }
- }
-
- /// Creates a prepared (or compiled) version of the command on the data source.
- public void Prepare()
- {
- try
- {
- _command.Prepare();
- }
- catch (Exception ex)
- {
- throw new DynamicQueryException("Error preparing command.", ex, this);
- }
- }
-
- /// Gets or sets the transaction within which the Command
- /// object of a data provider executes.
- /// It's does nothing, transaction is peeked from transaction
- /// pool of a connection. This is only a dummy.
- public IDbTransaction Transaction
- {
- get { return null; }
- set { }
- }
-
- /// Gets or sets how command results are applied to the
- /// when used by the
- /// method of a .
- /// One of the values. The default is
- /// Both unless the command is automatically generated. Then the default is None.
- /// The value entered was not one of the
- /// values.
- public UpdateRowSource UpdatedRowSource
- {
- get { return _command.UpdatedRowSource; }
- set { _command.UpdatedRowSource = value; }
- }
-
- #endregion IDbCommand Members
-
- #region IExtendedDisposable Members
-
- /// Performs application-defined tasks associated with
- /// freeing, releasing, or resetting unmanaged resources.
- public void Dispose()
- {
- lock (_db.SyncLock)
- {
- if (_con != null)
- {
- List pool = _db.CommandsPool.TryGetValue(_con.Connection);
-
- if (pool != null && pool.Contains(this))
- pool.Remove(this);
- }
-
- IsDisposed = true;
-
- if (_command != null)
- {
- _command.Parameters.Clear();
-
- _command.Dispose();
- _command = null;
- }
- }
- }
-
- /// Gets a value indicating whether this instance is disposed.
- public bool IsDisposed { get; private set; }
-
- #endregion IExtendedDisposable Members
- }
-
- /// Connection wrapper.
- /// This class is only connection holder, connection is managed by
- /// instance.
- public class DynamicConnection : IDbConnection, IExtendedDisposable
- {
- private DynamicDatabase _db;
- private bool _singleTransaction;
-
- /// Gets underlying connection.
- internal IDbConnection Connection { get; private set; }
-
- /// Initializes a new instance of the class.
- /// Database connection manager.
- /// Active connection.
- /// Are we using single transaction mode? I so... act correctly.
- internal DynamicConnection(DynamicDatabase db, IDbConnection con, bool singleTransaction)
- {
- IsDisposed = false;
- _db = db;
- Connection = con;
- _singleTransaction = singleTransaction;
- }
-
- /// Begins a database transaction.
- /// One of the values.
- /// Custom parameter describing transaction options.
- /// This action is invoked when transaction is disposed.
- /// Returns representation.
- internal DynamicTransaction BeginTransaction(IsolationLevel? il, object custom, Action disposed)
- {
- return new DynamicTransaction(_db, this, _singleTransaction, il, disposed, null);
- }
-
- #region IDbConnection Members
-
- /// Creates and returns a Command object associated with the connection.
- /// A Command object associated with the connection.
- public IDbCommand CreateCommand()
- {
- return new DynamicCommand(this, _db);
- }
-
- /// Begins a database transaction.
- /// Returns representation.
- public IDbTransaction BeginTransaction()
- {
- return BeginTransaction(null, null, null);
- }
-
- /// Begins a database transaction with the specified
- /// value.
- /// One of the values.
- /// Returns representation.
- public IDbTransaction BeginTransaction(IsolationLevel il)
- {
- return BeginTransaction(il, null, null);
- }
-
- /// Begins a database transaction with the specified
- /// value.
- /// Custom parameter describing transaction options.
- /// Returns representation.
- public IDbTransaction BeginTransaction(object custom)
- {
- return BeginTransaction(null, custom, null);
- }
-
- /// Changes the current database for an open Connection object.
- /// The name of the database to use in place of the current database.
- /// This operation is not supported in DynamORM . and will throw .
- /// Thrown always.
- public void ChangeDatabase(string databaseName)
- {
- throw new NotSupportedException("This operation is not supported in DynamORM.");
- }
-
- /// Opens a database connection with the settings specified by
- /// the ConnectionString property of the provider-specific
- /// Connection object.
- /// Does nothing. handles
- /// opening connections.
- public void Open()
- {
- }
-
- /// Closes the connection to the database.
- /// Does nothing. handles
- /// closing connections. Only way to close it is to dispose connection.
- /// It will close if this is multi connection configuration, otherwise
- /// it will stay open until is not
- /// disposed.
- public void Close()
- {
- }
-
- /// Gets or sets the string used to open a database.
- /// Changing connection string operation is not supported in DynamORM .
- /// and will throw .
- /// Thrown always when set is attempted.
- public string ConnectionString
- {
- get { return Connection.ConnectionString; }
- set { throw new NotSupportedException("This operation is not supported in DynamORM."); }
- }
-
- /// Gets the time to wait while trying to establish a connection
- /// before terminating the attempt and generating an error.
- public int ConnectionTimeout
- {
- get { return Connection.ConnectionTimeout; }
- }
-
- /// Gets the name of the current database or the database
- /// to be used after a connection is opened.
- public string Database
- {
- get { return Connection.Database; }
- }
-
- /// Gets the current state of the connection.
- public ConnectionState State
- {
- get { return Connection.State; }
- }
-
- #endregion IDbConnection Members
-
- #region IExtendedDisposable Members
-
- /// Performs application-defined tasks associated with freeing,
- /// releasing, or resetting unmanaged resources.
- public void Dispose()
- {
- _db.Close(Connection);
- IsDisposed = true;
- }
-
- /// Gets a value indicating whether this instance is disposed.
- public bool IsDisposed { get; private set; }
-
- #endregion IExtendedDisposable Members
- }
-
- /// Dynamic database is a class responsible for managing database.
- public class DynamicDatabase : IExtendedDisposable
- {
- #region Internal fields and properties
-
- private DbProviderFactory _provider;
- private DynamicProcedureInvoker _proc;
- private string _connectionString;
- private bool _singleConnection;
- private bool _singleTransaction;
- private string _leftDecorator = "\"";
- private string _rightDecorator = "\"";
- private bool _leftDecoratorIsInInvalidMembersChars = true;
- private bool _rightDecoratorIsInInvalidMembersChars = true;
- private string _parameterFormat = "@{0}";
- private int? _commandTimeout = null;
- private long _poolStamp = 0;
-
- private DynamicConnection _tempConn = null;
-
- /// Provides lock object for this database instance.
- internal readonly object SyncLock = new object();
-
- /// Gets or sets timestamp of last transaction pool or configuration change.
- /// This property is used to allow commands to determine if
- /// they need to update transaction object or not.
- internal long PoolStamp
- {
- get
- {
- long r = 0;
-
- lock (SyncLock)
- r = _poolStamp;
-
- return r;
- }
-
- set
- {
- lock (SyncLock)
- _poolStamp = value;
- }
- }
-
- /// Gets pool of connections and transactions.
- internal Dictionary> TransactionPool { get; private set; }
-
- /// Gets pool of connections and commands.
- /// Pool should contain dynamic commands instead of native ones.
- internal Dictionary> CommandsPool { get; private set; }
-
- /// Gets schema columns cache.
- internal Dictionary> Schema { get; private set; }
-
- /// Gets active builders that weren't disposed.
- internal List RemainingBuilders { get; private set; }
-
-#if !DYNAMORM_OMMIT_OLDSYNTAX
-
- /// Gets tables cache for this database instance.
- internal Dictionary TablesCache { get; private set; }
-
-#endif
-
- #endregion Internal fields and properties
-
- #region Properties and Constructors
-
- /// Gets database options.
- public DynamicDatabaseOptions Options { get; private set; }
-
- /// Gets or sets command timeout.
- public int? CommandTimeout
- {
- get { return _commandTimeout; }
- set
- {
- _commandTimeout = value;
- _poolStamp = DateTime.Now.Ticks;
- }
- }
-
- /// Gets the database provider.
- public DbProviderFactory Provider
- {
- get { return _provider; }
- }
-
- /// Gets the procedures invoker.
- ///
- ///
- /// using (var db = GetORM())
- /// {
- /// db.Execute(@"CREATE OR ALTER PROCEDURE sp_Exp_Scalar AS SELECT 42;");
- /// var res0 = db.Procedures.sp_Exp_Scalar();
- /// var res1 = db.Procedures.sp_Exp_Scalar();
- ///
- /// db.Execute(@"CREATE OR ALTER PROCEDURE sp_Exp_ReturnInt AS RETURN 42;");
- /// var res2 = db.Procedures.sp_Exp_ReturnInt();
- ///
- /// db.Execute(@"CREATE OR ALTER PROCEDURE sp_Exp_SomeData AS
- /// SELECT 1 Id, 'Some Name 1' [Name], 'Some Desc 1' [Desc], GETDATE() [Date]
- /// UNION ALL SELECT 2 Id, 'Some Name 2', 'Some Desc 2', GETDATE() [Date];");
- /// var res3 = db.Procedures.sp_Exp_SomeData();
- /// var res4 = db.Procedures.sp_Exp_SomeData>();
- ///
- /// db.Execute(@"CREATE OR ALTER PROCEDURE sp_Exp_SomeInputAndOutput
- /// @Name nvarchar(50),
- /// @Result nvarchar(256) OUTPUT
- /// AS
- /// SELECT @Result = 'Hi, ' + @Name + ' your lucky number is 42!';");
- /// var res5 = db.Procedures.sp_Exp_SomeInputAndOutput(Name: "G4g4r1n", out_Result: new DynamicColumn
- /// {
- /// Schema = new DynamicSchemaColumn
- /// {
- /// Size = 256,
- /// },
- /// }, ret_Return: 0);
- /// var res6 = db.Procedures.sp_Exp_SomeInputAndOutput(Name: "G4g4r1n", out_Result: new DynamicSchemaColumn
- /// {
- /// Size = 256,
- /// }, ret_Return: 0);
- ///
- /// db.Execute(@"CREATE OR ALTER PROCEDURE sp_Exp_SomeInputAndOutputWithDataAndReturn
- /// @Name nvarchar(50),
- /// @Result nvarchar(256) OUTPUT
- /// AS
- /// SELECT @Result = 'Hi, ' + @Name + ' your lucky number is 42!'
- ///
- /// SELECT 1 Id, 'Some Name 1' [Name], 'Some Desc 1' [Desc], GETDATE() [Date]
- /// UNION ALL SELECT 2 Id, 'Some Name 2', 'Some Desc 2', GETDATE() [Date]
- ///
- /// RETURN 42;");
- /// var res7 = db.Procedures.sp_Exp_SomeInputAndOutputWithDataAndReturn, sp_Exp_SomeInputAndOutputWithDataAndReturn_Result>(Name: "G4g4r1n", out_Result: new DynamicColumn
- /// {
- /// Schema = new DynamicSchemaColumn
- /// {
- /// Size = 256,
- /// },
- /// }, ret_Return: 0);
- /// var res8 = db.Procedures.sp_Exp_SomeInputAndOutputWithDataAndReturn, sp_Exp_SomeInputAndOutputWithDataAndReturn_Result>(Name: "G4g4r1n", out_Result: new DynamicSchemaColumn
- /// {
- /// Size = 256,
- /// }, ret_Return: 0);
- /// }
- ///
- ///private class sp_Exp_SomeData_Result
- ///{
- /// public virtual int Id { get; set; }
- /// public virtual string Name { get; set; }
- /// public virtual string Desc { get; set; }
- /// public virtual DateTime Date { get; set; }
- ///}
- ///private class sp_Exp_SomeInputAndOutput_Result
- ///{
- /// public virtual string Result { get; set; }
- /// public virtual string Return { get; set; }
- ///}
- ///private class sp_Exp_SomeInputAndOutputWithDataAndReturn_Result
- ///{
- /// public class Data
- /// {
- /// public virtual int Id { get; set; }
- /// public virtual string Name { get; set; }
- /// public virtual string Desc { get; set; }
- /// public virtual DateTime Date { get; set; }
- /// }
- /// public virtual List sp_Exp_SomeInputAndOutputWithDataAndReturn { get; set; }
- /// public virtual string Result { get; set; }
- /// public virtual string Return { get; set; }
- ///}
- ///
- ///
- public dynamic Procedures
- {
- get
- {
- if (_proc == null)
- {
- if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) !=
- DynamicDatabaseOptions.SupportStoredProcedures)
- throw new InvalidOperationException("Database connection doesn't support stored procedures.");
-
- _proc = new DynamicProcedureInvoker(this);
- }
-
- return _proc;
- }
- }
-
- /// Gets or sets a value indicating whether
- /// dump commands to console or not.
- public bool DumpCommands { get; set; }
-
- /// Gets or sets the dump command delegate.
- /// The dump command delegate.
- public Action DumpCommandDelegate { get; set; }
-
-#if NETFRAMEWORK
- // https://github.com/dotnet/runtime/issues/26229
- /// Initializes a new instance of the class.
- /// Database provider by name.
- /// Connection string to provided database.
- /// Connection options.
- public DynamicDatabase(string provider, string connectionString, DynamicDatabaseOptions options)
- : this(DbProviderFactories.GetFactory(provider), connectionString, options)
- {
- }
-#endif
-
- /// Initializes a new instance of the class.
- /// Database provider.
- /// Connection string to provided database.
- /// Connection options.
- public DynamicDatabase(DbProviderFactory provider, string connectionString, DynamicDatabaseOptions options)
- {
- IsDisposed = false;
- _provider = provider;
-
- InitCommon(connectionString, options);
- }
-
- private DbProviderFactory FindDbProviderFactoryFromConnection(Type t)
- {
- foreach (var type in t.Assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(DbProviderFactory))))
- {
- DbProviderFactory provider = null;
- bool dispose = false;
-
- var pi = type.GetProperty("Instance",
- BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty);
- if (pi != null)
- provider = (DbProviderFactory)pi.GetValue(null, null);
- else
- {
- var fi = type.GetField("Instance",
- BindingFlags.Static | BindingFlags.Public | BindingFlags.GetField);
- if (fi != null)
- provider = (DbProviderFactory)fi.GetValue(null);
- }
-
- if (provider == null)
- {
- var ci = type.GetConstructor(Type.EmptyTypes);
- if (ci != null)
- {
- provider = ci.Invoke(null) as DbProviderFactory;
- dispose = true;
- }
- }
-
- try
- {
- if (provider != null)
- {
- using (var c = provider.CreateConnection())
- {
- if (c.GetType() == t)
- return provider;
- }
- }
- }
- finally
- {
- if (provider != null && dispose && provider is IDisposable)
- ((IDisposable)provider).Dispose();
- }
- }
-
- return null;
- }
-
- /// Initializes a new instance of the class.
- /// Active database connection.
- /// Connection options. required.
- public DynamicDatabase(IDbConnection connection, DynamicDatabaseOptions options)
- {
- // Try to find correct provider if possible
- _provider = FindDbProviderFactoryFromConnection(connection.GetType());
-
- IsDisposed = false;
- InitCommon(connection.ConnectionString, options);
- TransactionPool.Add(connection, new Stack());
-
- if (!_singleConnection)
- throw new InvalidOperationException(
- "This constructor accepts only connections with DynamicDatabaseOptions.SingleConnection option.");
- }
-
- private void InitCommon(string connectionString, DynamicDatabaseOptions options)
- {
- _connectionString = connectionString;
- Options = options;
-
- _singleConnection = (options & DynamicDatabaseOptions.SingleConnection) ==
- DynamicDatabaseOptions.SingleConnection;
- _singleTransaction = (options & DynamicDatabaseOptions.SingleTransaction) ==
- DynamicDatabaseOptions.SingleTransaction;
- DumpCommands = (options & DynamicDatabaseOptions.DumpCommands) == DynamicDatabaseOptions.DumpCommands;
-
- TransactionPool = new Dictionary>();
- CommandsPool = new Dictionary>();
- Schema = new Dictionary>();
- RemainingBuilders = new List();
-#if !DYNAMORM_OMMIT_OLDSYNTAX
- TablesCache = new Dictionary();
-#endif
- }
-
- #endregion Properties and Constructors
-
- #region Table
-
-#if !DYNAMORM_OMMIT_OLDSYNTAX
-
- /// Gets dynamic table which is a simple ORM using dynamic objects.
- /// The action with instance of as parameter.
- /// Table name.
- /// Override keys in schema.
- /// Owner of the table.
- public void Table(Action action, string table = "", string[] keys = null, string owner = "")
- {
- using (dynamic t = Table(table, keys, owner))
- action(t);
- }
-
- /// Gets dynamic table which is a simple ORM using dynamic objects.
- /// Type used to determine table name.
- /// The action with instance of as parameter.
- /// Override keys in schema.
- public void Table(Action action, string[] keys = null)
- {
- using (dynamic t = Table(keys))
- action(t);
- }
-
- /// Gets dynamic table which is a simple ORM using dynamic objects.
- /// Table name.
- /// Override keys in schema.
- /// Owner of the table.
- /// Instance of .
- public dynamic Table(string table = "", string[] keys = null, string owner = "")
- {
- string key = string.Concat(
- table == null ? string.Empty : table,
- keys == null ? string.Empty : string.Join("_|_", keys));
-
- DynamicTable dt = null;
- lock (SyncLock)
- dt = TablesCache.TryGetValue(key) ??
- TablesCache.AddAndPassValue(key,
- new DynamicTable(this, table, owner, keys));
-
- return dt;
- }
-
- /// Gets dynamic table which is a simple ORM using dynamic objects.
- /// Type used to determine table name.
- /// Override keys in schema.
- /// Instance of .
- public dynamic Table(string[] keys = null)
- {
- Type table = typeof(T);
- string key = string.Concat(
- table.FullName,
- keys == null ? string.Empty : string.Join("_|_", keys));
-
- DynamicTable dt = null;
- lock (SyncLock)
- dt = TablesCache.TryGetValue(key) ??
- TablesCache.AddAndPassValue(key,
- new DynamicTable(this, table, keys));
-
- return dt;
- }
-
- /// Removes cached table.
- /// Disposed dynamic table.
- internal void RemoveFromCache(DynamicTable dynamicTable)
- {
- foreach (KeyValuePair item in TablesCache.Where(kvp => kvp.Value == dynamicTable)
- .ToList())
- TablesCache.Remove(item.Key);
- }
-
-#endif
-
- #endregion Table
-
- /// Adds cached builder.
- /// New dynamic builder.
- internal void AddToCache(IDynamicQueryBuilder builder)
- {
- lock (SyncLock)
- RemainingBuilders.Add(builder);
- }
-
- /// Removes cached builder.
- /// Disposed dynamic builder.
- internal void RemoveFromCache(IDynamicQueryBuilder builder)
- {
- lock (SyncLock)
- RemainingBuilders.Remove(builder);
- }
-
- #region From/Insert/Update/Delete
-
- ///
- /// Adds to the FROM clause the contents obtained by parsing the dynamic lambda expressions given. The supported
- /// formats are:
- /// - Resolve to a string: x => "owner.Table AS Alias", where the alias part is optional.
- /// - Resolve to an expression: x => x.owner.Table.As( x.Alias ), where the alias part is optional.
- /// - Generic expression: x => x( expression ).As( x.Alias ), where the alias part is mandatory. In this
- /// case the alias is not annotated.
- ///
- /// The specification.
- /// This instance to permit chaining.
- public virtual IDynamicSelectQueryBuilder From(Func fn)
- {
- return new DynamicSelectQueryBuilder(this).From(fn);
- }
-
- /// Adds to the FROM clause using .
- /// Type which can be represented in database.
- /// Table alias.
- /// use no lock.
- /// This instance to permit chaining.
- public virtual IDynamicSelectQueryBuilder From(string alias = null, bool noLock = false)
- {
- // TODO: Make it more readable and maitainable
- if (noLock)
- {
- if (string.IsNullOrEmpty(alias))
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).NoLock());
- else
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).As(alias).NoLock());
- }
- else
- {
- if (string.IsNullOrEmpty(alias))
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)));
- else
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).As(alias));
- }
- }
-
- /// Adds to the FROM clause using .
- /// Type which can be represented in database.
- /// This instance to permit chaining.
- public virtual IDynamicSelectQueryBuilder From(Type t)
- {
- return new DynamicSelectQueryBuilder(this).From(x => x(t));
- }
-
- ///
- /// Adds to the INSERT INTO clause the contents obtained by parsing the dynamic lambda expressions given. The supported
- /// formats are:
- /// - Resolve to a string: x => "owner.Table".
- /// - Resolve to a type: x => typeof(SomeClass).
- /// - Resolve to an expression: x => x.owner.Table.
- /// - Generic expression: x => x( expression ). Expression can
- /// be or .
- ///
- /// The specification.
- /// This instance to permit chaining.
- public virtual IDynamicInsertQueryBuilder Insert(Func func)
- {
- return new DynamicInsertQueryBuilder(this).Table(func);
- }
-
- /// Adds to the INSERT INTO clause using .
- /// Type which can be represented in database.
- /// This instance to permit chaining.
- public virtual IDynamicInsertQueryBuilder Insert()
- {
- return new DynamicInsertQueryBuilder(this).Table(typeof(T));
- }
-
- /// Adds to the INSERT INTO clause using .
- /// Type which can be represented in database.
- /// This instance to permit chaining.
- public virtual IDynamicInsertQueryBuilder Insert(Type t)
- {
- return new DynamicInsertQueryBuilder(this).Table(t);
- }
-
- /// Bulk insert objects into database.
- /// Type of objects to insert.
- /// Enumerable containing instances of objects to insert.
- /// Number of inserted rows.
- public virtual int Insert(IEnumerable e) where T : class
- {
- return Insert(typeof(T), e);
- }
-
- /// Bulk insert objects into database.
- /// Type of objects to insert.
- /// Enumerable containing instances of objects to insert.
- /// Number of inserted rows.
- public virtual int Insert(Type t, IEnumerable e)
- {
- int affected = 0;
- DynamicTypeMap mapper = DynamicMapperCache.GetMapper(t);
-
- if (mapper != null)
- {
- using (IDbConnection con = Open())
- using (IDbTransaction tra = con.BeginTransaction())
- using (IDbCommand cmd = con.CreateCommand())
- {
- try
- {
- Dictionary parameters =
- new Dictionary();
-
- if (!string.IsNullOrEmpty(mapper.InsertCommandText))
- {
- cmd.CommandText = mapper.InsertCommandText;
-
- foreach (DynamicPropertyInvoker col in mapper.ColumnsMap.Values
- .Where(di => !di.Ignore && di.InsertCommandParameter != null)
- .OrderBy(di => di.InsertCommandParameter.Ordinal))
- {
- IDbDataParameter para = cmd.CreateParameter();
- para.ParameterName = col.InsertCommandParameter.Name;
- para.DbType = col.InsertCommandParameter.Type;
- cmd.Parameters.Add(para);
-
- parameters[para] = col;
- }
- }
- else
- PrepareBatchInsert(t, mapper, cmd, parameters);
-
- foreach (var o in e)
- {
- foreach (KeyValuePair m in parameters)
- m.Key.Value = m.Value.Get(o);
-
- affected += cmd.ExecuteNonQuery();
- }
-
- tra.Commit();
- }
- catch (Exception ex)
- {
- if (tra != null)
- tra.Rollback();
-
- affected = 0;
-
- StringBuilder problematicCommand = new StringBuilder();
- cmd.Dump(problematicCommand);
-
- throw new InvalidOperationException(problematicCommand.ToString(), ex);
- }
- }
- }
-
- return affected;
- }
-
- ///
- /// Adds to the UPDATE clause the contents obtained by parsing the dynamic lambda expressions given. The supported
- /// formats are:
- /// - Resolve to a string: x => "owner.Table".
- /// - Resolve to a type: x => typeof(SomeClass).
- /// - Resolve to an expression: x => x.owner.Table.
- /// - Generic expression: x => x( expression ). Expression can
- /// be or .
- ///
- /// The specification.
- /// This instance to permit chaining.
- public virtual IDynamicUpdateQueryBuilder Update(Func func)
- {
- return new DynamicUpdateQueryBuilder(this).Table(func);
- }
-
- /// Adds to the UPDATE clause using .
- /// Type which can be represented in database.
- /// This instance to permit chaining.
- public virtual IDynamicUpdateQueryBuilder Update()
- {
- return new DynamicUpdateQueryBuilder(this).Table(typeof(T));
- }
-
- /// Adds to the UPDATE clause using .
- /// Type which can be represented in database.
- /// This instance to permit chaining.
- public virtual IDynamicUpdateQueryBuilder Update(Type t)
- {
- return new DynamicUpdateQueryBuilder(this).Table(t);
- }
-
- /// Bulk update objects in database.
- /// Type of objects to update.
- /// Enumerable containing instances of objects to update.
- /// Number of updated rows.
- public virtual int Update(IEnumerable e) where T : class
- {
- return Update(typeof(T), e);
- }
-
- /// Bulk update objects in database.
- /// Type of objects to update.
- /// Enumerable containing instances of objects to update.
- /// Number of updated rows.
- public virtual int Update(Type t, IEnumerable e)
- {
- int affected = 0;
- DynamicTypeMap mapper = DynamicMapperCache.GetMapper(t);
-
- if (mapper != null)
- {
- using (IDbConnection con = Open())
- using (IDbTransaction tra = con.BeginTransaction())
- using (IDbCommand cmd = con.CreateCommand())
- {
- try
- {
- Dictionary parameters =
- new Dictionary();
-
- if (!string.IsNullOrEmpty(mapper.UpdateCommandText))
- {
- cmd.CommandText = mapper.UpdateCommandText;
-
- foreach (DynamicPropertyInvoker col in mapper.ColumnsMap.Values
- .Where(di => !di.Ignore && di.UpdateCommandParameter != null)
- .OrderBy(di => di.UpdateCommandParameter.Ordinal))
- {
- IDbDataParameter para = cmd.CreateParameter();
- para.ParameterName = col.UpdateCommandParameter.Name;
- para.DbType = col.UpdateCommandParameter.Type;
- cmd.Parameters.Add(para);
-
- parameters[para] = col;
- }
- }
- else
- PrepareBatchUpdate(t, mapper, cmd, parameters);
-
- foreach (var o in e)
- {
- foreach (KeyValuePair m in parameters)
- m.Key.Value = m.Value.Get(o);
-
- affected += cmd.ExecuteNonQuery();
- }
-
- tra.Commit();
- }
- catch (Exception ex)
- {
- if (tra != null)
- tra.Rollback();
-
- affected = 0;
-
- StringBuilder problematicCommand = new StringBuilder();
- cmd.Dump(problematicCommand);
-
- throw new InvalidOperationException(problematicCommand.ToString(), ex);
- }
- }
- }
-
- return affected;
- }
-
- /// Bulk update or insert objects into database.
- /// Type of objects to update or insert.
- /// Enumerable containing instances of objects to update or insert.
- /// Number of updated or inserted rows.
- public virtual int UpdateOrInsert(IEnumerable e) where T : class
- {
- return UpdateOrInsert(typeof(T), e);
- }
-
- /// Bulk update or insert objects into database.
- /// Type of objects to update or insert.
- /// Enumerable containing instances of objects to update or insert.
- /// Number of updated or inserted rows.
- public virtual int UpdateOrInsert(Type t, IEnumerable e)
- {
- int affected = 0;
- DynamicTypeMap mapper = DynamicMapperCache.GetMapper(t);
-
- if (mapper != null)
- {
- using (IDbConnection con = Open())
- using (IDbTransaction tra = con.BeginTransaction())
- using (IDbCommand cmdUp = con.CreateCommand())
- using (IDbCommand cmdIn = con.CreateCommand())
- {
- try
- {
- #region Update
-
- Dictionary parametersUp =
- new Dictionary();
-
- if (!string.IsNullOrEmpty(mapper.UpdateCommandText))
- {
- cmdUp.CommandText = mapper.UpdateCommandText;
-
- foreach (DynamicPropertyInvoker col in mapper.ColumnsMap.Values
- .Where(di => !di.Ignore && di.UpdateCommandParameter != null)
- .OrderBy(di => di.UpdateCommandParameter.Ordinal))
- {
- IDbDataParameter para = cmdUp.CreateParameter();
- para.ParameterName = col.UpdateCommandParameter.Name;
- para.DbType = col.UpdateCommandParameter.Type;
- cmdUp.Parameters.Add(para);
-
- parametersUp[para] = col;
- }
- }
- else
- PrepareBatchUpdate(t, mapper, cmdUp, parametersUp);
-
- #endregion Update
-
- #region Insert
-
- Dictionary parametersIn =
- new Dictionary();
-
- if (!string.IsNullOrEmpty(mapper.InsertCommandText))
- {
- cmdIn.CommandText = mapper.InsertCommandText;
-
- foreach (DynamicPropertyInvoker col in mapper.ColumnsMap.Values
- .Where(di => !di.Ignore && di.InsertCommandParameter != null)
- .OrderBy(di => di.InsertCommandParameter.Ordinal))
- {
- IDbDataParameter para = cmdIn.CreateParameter();
- para.ParameterName = col.InsertCommandParameter.Name;
- para.DbType = col.InsertCommandParameter.Type;
- cmdIn.Parameters.Add(para);
-
- parametersIn[para] = col;
- }
- }
- else
- PrepareBatchInsert(t, mapper, cmdIn, parametersIn);
-
- #endregion Insert
-
- foreach (var o in e)
- {
- foreach (KeyValuePair m in parametersUp)
- m.Key.Value = m.Value.Get(o);
-
- int a = cmdUp.ExecuteNonQuery();
- if (a == 0)
- {
- foreach (KeyValuePair m in parametersIn)
- m.Key.Value = m.Value.Get(o);
-
- a = cmdIn.ExecuteNonQuery();
- }
-
- affected += a;
- }
-
- tra.Commit();
- }
- catch (Exception ex)
- {
- if (tra != null)
- tra.Rollback();
-
- affected = 0;
-
- StringBuilder problematicCommand = new StringBuilder();
- cmdUp.Dump(problematicCommand);
-
- throw new InvalidOperationException(problematicCommand.ToString(), ex);
- }
- }
- }
-
- return affected;
- }
-
- ///
- /// Adds to the DELETE FROM clause the contents obtained by parsing the dynamic lambda expressions given. The supported
- /// formats are:
- /// - Resolve to a string: x => "owner.Table".
- /// - Resolve to a type: x => typeof(SomeClass).
- /// - Resolve to an expression: x => x.owner.Table.
- /// - Generic expression: x => x( expression ). Expression can
- /// be or .
- ///
- /// The specification.
- /// This instance to permit chaining.
- public virtual IDynamicDeleteQueryBuilder Delete(Func func)
- {
- return new DynamicDeleteQueryBuilder(this).Table(func);
- }
-
- /// Adds to the DELETE FROM clause using .
- /// Type which can be represented in database.
- /// This instance to permit chaining.
- public virtual IDynamicDeleteQueryBuilder Delete()
- {
- return new DynamicDeleteQueryBuilder(this).Table(typeof(T));
- }
-
- /// Adds to the DELETE FROM clause using .
- /// Type which can be represented in database.
- /// This instance to permit chaining.
- public virtual IDynamicDeleteQueryBuilder Delete(Type t)
- {
- return new DynamicDeleteQueryBuilder(this).Table(t);
- }
-
- /// Bulk delete objects in database.
- /// Type of objects to delete.
- /// Enumerable containing instances of objects to delete.
- /// Number of deleted rows.
- public virtual int Delete(IEnumerable e) where T : class
- {
- return Delete(typeof(T), e);
- }
-
- /// Bulk delete objects in database.
- /// Type of objects to delete.
- /// Enumerable containing instances of objects to delete.
- /// Number of deleted rows.
- public virtual int Delete(Type t, IEnumerable e)
- {
- int affected = 0;
- DynamicTypeMap mapper = DynamicMapperCache.GetMapper(t);
-
- if (mapper != null)
- {
- using (IDbConnection con = Open())
- using (IDbTransaction tra = con.BeginTransaction())
- using (IDbCommand cmd = con.CreateCommand())
- {
- try
- {
- Dictionary parameters =
- new Dictionary();
-
- if (!string.IsNullOrEmpty(mapper.DeleteCommandText))
- {
- cmd.CommandText = mapper.DeleteCommandText;
-
- foreach (DynamicPropertyInvoker col in mapper.ColumnsMap.Values
- .Where(di => !di.Ignore && di.DeleteCommandParameter != null)
- .OrderBy(di => di.DeleteCommandParameter.Ordinal))
- {
- IDbDataParameter para = cmd.CreateParameter();
- para.ParameterName = col.DeleteCommandParameter.Name;
- para.DbType = col.DeleteCommandParameter.Type;
- cmd.Parameters.Add(para);
-
- parameters[para] = col;
- }
- }
- else
- PrepareBatchDelete(t, mapper, cmd, parameters);
-
- foreach (var o in e)
- {
- foreach (KeyValuePair m in parameters)
- m.Key.Value = m.Value.Get(o);
-
- affected += cmd.ExecuteNonQuery();
- }
-
- tra.Commit();
- }
- catch (Exception ex)
- {
- if (tra != null)
- tra.Rollback();
-
- affected = 0;
-
- StringBuilder problematicCommand = new StringBuilder();
- cmd.Dump(problematicCommand);
-
- throw new InvalidOperationException(problematicCommand.ToString(), ex);
- }
- }
- }
-
- return affected;
- }
-
- private void PrepareBatchInsert(DynamicTypeMap mapper, IDbCommand cmd,
- Dictionary parameters)
- {
- PrepareBatchInsert(typeof(T), mapper, cmd, parameters);
- }
-
- private void PrepareBatchInsert(Type t, DynamicTypeMap mapper, IDbCommand cmd,
- Dictionary parameters)
- {
- DynamicPropertyInvoker currentprop = null;
- Dictionary temp = new Dictionary();
- Dictionary schema = this.GetSchema(t);
- int ord = 0;
-
- IDynamicInsertQueryBuilder ib = Insert(t)
- .SetVirtualMode(true)
- .CreateTemporaryParameterAction(p => temp[p.Name] = currentprop)
- .CreateParameterAction((p, cp) =>
- {
- parameters[cp] = temp[p.Name];
- parameters[cp].InsertCommandParameter = new DynamicPropertyInvoker.ParameterSpec
- {
- Name = cp.ParameterName,
- Type = cp.DbType,
- Ordinal = ord++,
- };
- });
-
- foreach (KeyValuePair prop in mapper.PropertyMap)
- if (!mapper.Ignored.Contains(prop.Key))
- {
- string col = mapper.PropertyMap.TryGetValue(prop.Key) ?? prop.Key;
- currentprop = mapper.ColumnsMap.TryGetValue(col.ToLower());
-
- if (currentprop.Ignore || (currentprop.Column != null && currentprop.Column.IsNoInsert))
- continue;
-
- if (currentprop.Get != null)
- ib.Insert(new DynamicColumn()
- {
- ColumnName = col,
- Schema = schema == null ? null : schema.TryGetNullable(col.ToLower()),
- Operator = DynamicColumn.CompareOperator.Eq,
- Value = null,
- VirtualColumn = true,
- });
- }
-
- ib.FillCommand(cmd);
-
- // Cache command
- mapper.InsertCommandText = cmd.CommandText;
- }
-
- private void PrepareBatchUpdate(DynamicTypeMap mapper, IDbCommand cmd,
- Dictionary parameters)
- {
- PrepareBatchUpdate(typeof(T), mapper, cmd, parameters);
- }
-
- private void PrepareBatchUpdate(Type t, DynamicTypeMap mapper, IDbCommand cmd,
- Dictionary parameters)
- {
- DynamicPropertyInvoker currentprop = null;
- Dictionary temp = new Dictionary();
- Dictionary schema = this.GetSchema(t);
- int ord = 0;
-
- IDynamicUpdateQueryBuilder ib = Update(t)
- .SetVirtualMode(true)
- .CreateTemporaryParameterAction(p => temp[p.Name] = currentprop)
- .CreateParameterAction((p, cp) =>
- {
- parameters[cp] = temp[p.Name];
- parameters[cp].UpdateCommandParameter = new DynamicPropertyInvoker.ParameterSpec
- {
- Name = cp.ParameterName,
- Type = cp.DbType,
- Ordinal = ord++,
- };
- });
-
- foreach (KeyValuePair prop in mapper.PropertyMap)
- if (!mapper.Ignored.Contains(prop.Key))
- {
- string col = mapper.PropertyMap.TryGetValue(prop.Key) ?? prop.Key;
- currentprop = mapper.ColumnsMap.TryGetValue(col.ToLower());
-
- if (currentprop.Ignore)
- continue;
-
- if (currentprop.Get != null)
- {
- DynamicSchemaColumn? colS = schema == null ? null : schema.TryGetNullable(col.ToLower());
-
- if (colS.HasValue)
- {
- if (colS.Value.IsKey)
- ib.Where(new DynamicColumn()
- {
- ColumnName = col,
- Schema = colS,
- Operator = DynamicColumn.CompareOperator.Eq,
- Value = null,
- VirtualColumn = true,
- });
- else if (currentprop.Column == null || !currentprop.Column.IsNoUpdate)
- ib.Values(new DynamicColumn()
- {
- ColumnName = col,
- Schema = colS,
- Operator = DynamicColumn.CompareOperator.Eq,
- Value = null,
- VirtualColumn = true,
- });
- }
- else if (currentprop.Column != null && currentprop.Column.IsKey)
- ib.Where(new DynamicColumn()
- {
- ColumnName = col,
- Schema = colS,
- Operator = DynamicColumn.CompareOperator.Eq,
- Value = null,
- VirtualColumn = true,
- });
- }
- }
-
- ib.FillCommand(cmd);
-
- // Cache command
- mapper.UpdateCommandText = cmd.CommandText;
- }
-
- private void PrepareBatchDelete(DynamicTypeMap mapper, IDbCommand cmd,
- Dictionary parameters)
- {
- PrepareBatchDelete(typeof(T), mapper, cmd, parameters);
- }
-
- private void PrepareBatchDelete(Type t, DynamicTypeMap mapper, IDbCommand cmd,
- Dictionary parameters)
- {
- DynamicPropertyInvoker currentprop = null;
- Dictionary temp = new Dictionary();
- Dictionary schema = this.GetSchema(t);
- int ord = 0;
-
- IDynamicDeleteQueryBuilder ib = Delete(t)
- .SetVirtualMode(true)
- .CreateTemporaryParameterAction(p => temp[p.Name] = currentprop)
- .CreateParameterAction((p, cp) =>
- {
- parameters[cp] = temp[p.Name];
- parameters[cp].DeleteCommandParameter = new DynamicPropertyInvoker.ParameterSpec
- {
- Name = cp.ParameterName,
- Type = cp.DbType,
- Ordinal = ord++,
- };
- });
-
- foreach (KeyValuePair prop in mapper.PropertyMap)
- if (!mapper.Ignored.Contains(prop.Key))
- {
- string col = mapper.PropertyMap.TryGetValue(prop.Key) ?? prop.Key;
- currentprop = mapper.ColumnsMap.TryGetValue(col.ToLower());
-
- if (currentprop.Ignore)
- continue;
-
- if (currentprop.Get != null)
- {
- DynamicSchemaColumn? colS = schema == null ? null : schema.TryGetNullable(col.ToLower());
-
- if (colS != null)
- {
- if (colS.Value.IsKey)
- ib.Where(new DynamicColumn()
- {
- ColumnName = col,
- Schema = colS,
- Operator = DynamicColumn.CompareOperator.Eq,
- Value = null,
- VirtualColumn = true,
- });
- }
- else if (currentprop.Column != null && currentprop.Column.IsKey)
- ib.Where(new DynamicColumn()
- {
- ColumnName = col,
- Schema = colS,
- Operator = DynamicColumn.CompareOperator.Eq,
- Value = null,
- VirtualColumn = true,
- });
- }
- }
-
- ib.FillCommand(cmd);
-
- // Cache command
- mapper.DeleteCommandText = cmd.CommandText;
- }
-
- #endregion From/Insert/Update/Delete
-
- #region Procedure
-
- /// Execute stored procedure.
- /// Name of stored procedure to execute.
- /// Number of affected rows.
- public virtual int Procedure(string procName)
- {
- return Procedure(procName, (DynamicExpando)null);
- }
-
- /// Execute stored procedure.
- /// Name of stored procedure to execute.
- /// Arguments (parameters) in form of expando object.
- /// Number of affected rows.
- public virtual int Procedure(string procName, params object[] args)
- {
- if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) !=
- DynamicDatabaseOptions.SupportStoredProcedures)
- throw new InvalidOperationException("Database connection desn't support stored procedures.");
-
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(CommandType.StoredProcedure, procName)
- .AddParameters(this, args)
- .ExecuteNonQuery();
- }
- }
-
- /// Execute stored procedure.
- /// Name of stored procedure to execute.
- /// Arguments (parameters) in form of expando object.
- /// Number of affected rows.
- public virtual int Procedure(string procName, DynamicExpando args)
- {
- if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) !=
- DynamicDatabaseOptions.SupportStoredProcedures)
- throw new InvalidOperationException("Database connection desn't support stored procedures.");
-
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(CommandType.StoredProcedure, procName)
- .AddParameters(this, args)
- .ExecuteNonQuery();
- }
- }
-
- /// Execute stored procedure.
- /// Name of stored procedure to execute.
- /// Arguments (parameters) in form of expando object.
- /// Number of affected rows.
- public virtual int Procedure(string procName, ExpandoObject args)
- {
- if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) !=
- DynamicDatabaseOptions.SupportStoredProcedures)
- throw new InvalidOperationException("Database connection desn't support stored procedures.");
-
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(CommandType.StoredProcedure, procName)
- .AddParameters(this, args)
- .ExecuteNonQuery();
- }
- }
-
- #endregion Procedure
-
- #region Execute
-
- /// Execute non query.
- /// SQL query containing numbered parameters in format provided by
- /// methods. Also names should be formatted with
- /// method.
- /// Arguments (parameters).
- /// Number of affected rows.
- public virtual int Execute(string sql, params object[] args)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(sql).AddParameters(this, args)
- .ExecuteNonQuery();
- }
- }
-
- /// Execute non query.
- /// Command builder.
- /// Number of affected rows.
- public virtual int Execute(IDynamicQueryBuilder builder)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(builder)
- .ExecuteNonQuery();
- }
- }
-
- /// Execute non query.
- /// Command builders.
- /// Number of affected rows.
- public virtual int Execute(IDynamicQueryBuilder[] builders)
- {
- int ret = 0;
-
- using (IDbConnection con = Open())
- {
- using (IDbTransaction trans = con.BeginTransaction())
- {
- foreach (IDynamicQueryBuilder builder in builders)
- using (IDbCommand cmd = con.CreateCommand())
- ret += cmd
- .SetCommand(builder)
- .ExecuteNonQuery();
-
- trans.Commit();
- }
- }
-
- return ret;
- }
-
- #endregion Execute
-
- #region Scalar
-
- /// Returns a single result.
- /// SQL query containing numbered parameters in format provided by
- /// methods. Also names should be formatted with
- /// method.
- /// Arguments (parameters).
- /// Result of a query.
- public virtual object Scalar(string sql, params object[] args)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(sql).AddParameters(this, args)
- .ExecuteScalar();
- }
- }
-
- /// Returns a single result.
- /// Command builder.
- /// Result of a query.
- public virtual object Scalar(IDynamicQueryBuilder builder)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(builder)
- .ExecuteScalar();
- }
- }
-
-#if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE
-
- /// Returns a single result.
- /// What kind of result is expected.
- /// SQL query containing numbered parameters in format provided by
- /// methods. Also names should be formatted with
- /// method.
- /// Arguments (parameters).
- /// Result of a query.
- public virtual T ScalarAs(string sql, params object[] args)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(sql).AddParameters(this, args)
- .ExecuteScalarAs();
- }
- }
-
- /// Returns a single result.
- /// What kind of result is expected.
- /// Command builder.
- /// Default value.
- /// Result of a query.
- public virtual T ScalarAs(IDynamicQueryBuilder builder, T defaultValue = default(T))
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- return cmd
- .SetCommand(builder)
- .ExecuteScalarAs(defaultValue);
- }
- }
-
-#endif
-
- #endregion Scalar
-
- #region Query
-
- /// Enumerate the reader and yield the result.
- /// SQL query containing numbered parameters in format provided by
- /// methods. Also names should be formatted with
- /// method.
- /// Arguments (parameters).
- /// Enumerator of objects expanded from query.
- public virtual IEnumerable Query(string sql, params object[] args)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- using (IDataReader rdr = cmd
- .SetCommand(sql)
- .AddParameters(this, args)
- .ExecuteReader())
- using (IDataReader cache = new DynamicCachedReader(rdr))
- {
- while (cache.Read())
- {
- dynamic val = null;
-
- // Work around to avoid yield being in try...catch block:
- // http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
- try
- {
- val = cache.RowToDynamic();
- }
- catch (ArgumentException argex)
- {
- StringBuilder sb = new StringBuilder();
- cmd.Dump(sb);
-
- throw new ArgumentException(
- string.Format("{0}{1}{2}", argex.Message, Environment.NewLine, sb),
- argex.InnerException.NullOr(a => a, argex));
- }
-
- yield return val;
- }
- }
- }
- }
-
- /// Enumerate the reader and yield the result.
- /// Command builder.
- /// Enumerator of objects expanded from query.
- public virtual IEnumerable Query(IDynamicQueryBuilder builder)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- using (IDataReader rdr = cmd
- .SetCommand(builder)
- .ExecuteReader())
- using (var cache = new DynamicCachedReader(rdr))
- while (cache.Read())
- {
- dynamic val = null;
-
- // Work around to avoid yield being in try...catch block:
- // http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
- try
- {
- val = cache.RowToDynamic();
- }
- catch (ArgumentException argex)
- {
- StringBuilder sb = new StringBuilder();
- cmd.Dump(sb);
-
- throw new ArgumentException(
- string.Format("{0}{1}{2}", argex.Message, Environment.NewLine, sb),
- argex.InnerException.NullOr(a => a, argex));
- }
-
- yield return val;
- }
- }
- }
-
- #endregion Query
-
- #region CachedQuery
-
- /// Enumerate the reader and yield the result.
- /// SQL query containing numbered parameters in format provided by
- /// methods. Also names should be formatted with
- /// method.
- /// Arguments (parameters).
- /// Enumerator of objects expanded from query.
- public virtual DynamicCachedReader CachedQuery(string sql, params object[] args)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- using (IDataReader rdr = cmd
- .SetCommand(sql)
- .AddParameters(this, args)
- .ExecuteReader())
- return new DynamicCachedReader(rdr);
- }
- }
-
- /// Enumerate the reader and yield the result.
- /// Command builder.
- /// Enumerator of objects expanded from query.
- public virtual DynamicCachedReader CachedQuery(IDynamicQueryBuilder builder)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand())
- {
- using (IDataReader rdr = cmd
- .SetCommand(builder)
- .ExecuteReader())
- return new DynamicCachedReader(rdr);
- }
- }
-
- #endregion Query
-
- #region Schema
-
- /// Builds query cache if necessary and returns it.
- /// The builder containing query to read schema from.
- /// Query schema.
- public Dictionary GetQuerySchema(IDynamicSelectQueryBuilder builder)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand().SetCommand(builder))
- return ReadSchema(cmd)
- .Distinct()
- .ToDictionary(k => k.Name.ToLower(), k => k);
- }
-
- /// Builds query cache if necessary and returns it.
- /// SQL query from which read schema.
- /// SQL query arguments.
- /// Query schema.
- public Dictionary GetQuerySchema(string sql, params object[] args)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand().SetCommand(sql, args))
- return ReadSchema(cmd)
- .Distinct()
- .ToDictionary(k => k.Name.ToLower(), k => k);
- }
-
- /// Builds table cache if necessary and returns it.
- /// Name of table for which build schema.
- /// Owner of table for which build schema.
- /// Table schema.
- public Dictionary GetSchema(string table, string owner = null)
- {
- Dictionary schema = null;
-
- lock (SyncLock)
- schema = Schema.TryGetValue(table.ToLower()) ??
- BuildAndCacheSchema(table, null, owner);
-
- return schema;
- }
-
- /// Builds table cache if necessary and returns it.
- /// Type of table for which build schema.
- /// Table schema or null if type was anonymous.
- public Dictionary GetSchema()
- {
- if (typeof(T).IsAnonymous())
- return null;
-
- Dictionary schema = null;
-
- lock (SyncLock)
- schema = Schema.TryGetValue(typeof(T).FullName) ??
- BuildAndCacheSchema(null, DynamicMapperCache.GetMapper());
-
- return schema;
- }
-
- /// Builds table cache if necessary and returns it.
- /// Type of table for which build schema.
- /// Table schema or null if type was anonymous.
- public Dictionary GetSchema(Type table)
- {
- if (table == null || table.IsAnonymous() || table.IsValueType)
- return null;
-
- Dictionary schema = null;
-
- lock (SyncLock)
- schema = Schema.TryGetValue(table.FullName) ??
- BuildAndCacheSchema(null, DynamicMapperCache.GetMapper(table));
-
- return schema;
- }
-
- /// Clears the schema from cache.
- /// Use this method to refresh table information.
- /// Name of table for which clear schema.
- /// Owner of table for which clear schema.
- public void ClearSchema(string table = null, string owner = null)
- {
- lock (SyncLock)
- if (Schema.ContainsKey(table.ToLower()))
- Schema.Remove(table.ToLower());
- }
-
- /// Clears the schema from cache.
- /// Use this method to refresh table information.
- /// Type of table for which clear schema.
- public void ClearSchema()
- {
- ClearSchema(typeof(T));
- }
-
- /// Clears the schema from cache.
- /// Use this method to refresh table information.
- /// Type of table for which clear schema.
- public void ClearSchema(Type table)
- {
- lock (SyncLock)
- if (Schema.ContainsKey(table.FullName))
- {
- if (Schema[table.FullName] != null)
- Schema[table.FullName].Clear();
- Schema.Remove(table.FullName);
- }
- }
-
- /// Clears the all schemas from cache.
- /// Use this method to refresh all table information.
- public void ClearSchema()
- {
- lock (SyncLock)
- {
- foreach (KeyValuePair> s in Schema)
- if (s.Value != null)
- s.Value.Clear();
-
- Schema.Clear();
- }
- }
-
- /// Get schema describing objects from reader.
- /// Table from which extract column info.
- /// Owner of table from which extract column info.
- /// List of objects .
- /// If your database doesn't get those values in upper case (like most of the databases) you should override this method.
- protected virtual IList ReadSchema(string table, string owner)
- {
- using (IDbConnection con = Open())
- using (IDbCommand cmd = con.CreateCommand()
- .SetCommand(string.Format("SELECT * FROM {0}{1} WHERE 1 = 0",
- !string.IsNullOrEmpty(owner) ? string.Format("{0}.", DecorateName(owner)) : string.Empty,
- DecorateName(table))))
- return ReadSchema(cmd)
- .ToList();
- }
-
- /// Get schema describing objects from reader.
- /// Command containing query to execute.
- /// List of objects .
- /// If your database doesn't get those values in upper case (like most of the databases) you should override this method.
- public virtual IEnumerable ReadSchema(IDbCommand cmd)
- {
- DataTable st = null;
-
- using (IDataReader rdr = cmd.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo))
- st = rdr.GetSchemaTable();
-
- using (st)
- foreach (DataRow col in st.Rows)
- {
- dynamic c = col.RowToDynamicUpper();
-
- yield return new DynamicSchemaColumn
- {
- Name = c.COLUMNNAME,
- Type = ReadSchemaType(c),
- IsKey = c.ISKEY ?? false,
- IsUnique = c.ISUNIQUE ?? false,
- AllowNull = c.ALLOWNULL ?? false,
- Size = (int)(c.COLUMNSIZE ?? 0),
- Precision = (byte)(c.NUMERICPRECISION ?? 0),
- Scale = (byte)(c.NUMERICSCALE ?? 0)
- };
- }
- }
-
- /// Reads the type of column from the schema.
- /// The schema.
- /// Generic parameter type.
- protected virtual DbType ReadSchemaType(dynamic schema)
- {
- Type type = (Type)schema.DATATYPE;
-
- // Small hack for SQL Server Provider
- if (type == typeof(string) && Provider != null && Provider.GetType().Name == "SqlClientFactory")
- {
- var map = schema as IDictionary;
- string typeName = (map.TryGetValue("DATATYPENAME") ?? string.Empty).ToString();
-
- switch (typeName)
- {
- case "varchar":
- return DbType.AnsiString;
-
- case "nvarchar":
- return DbType.String;
- }
- }
-
- return DynamicExtensions.TypeMap.TryGetNullable(type) ?? DbType.String;
- }
-
- private Dictionary BuildAndCacheSchema(string tableName, DynamicTypeMap mapper,
- string owner = null)
- {
- Dictionary schema = null;
-
- if (mapper != null)
- {
- tableName = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Name)
- ? mapper.Type.Name
- : mapper.Table.Name;
- owner = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Owner) ? null : mapper.Table.Owner;
- }
-
- bool databaseSchemaSupport = !string.IsNullOrEmpty(tableName) &&
- (Options & DynamicDatabaseOptions.SupportSchema) ==
- DynamicDatabaseOptions.SupportSchema;
- bool mapperSchema = mapper != null && mapper.Table != null &&
- (mapper.Table.Override || !databaseSchemaSupport);
-
- #region Database schema
-
- if (databaseSchemaSupport && !Schema.ContainsKey(tableName.ToLower()))
- {
- schema = ReadSchema(tableName, owner)
- .Where(x => x.Name != null)
- .DistinctBy(x => x.Name.ToLower())
- .ToDictionary(k => k.Name.ToLower(), k => k);
-
- Schema[tableName.ToLower()] = schema;
- }
-
- #endregion Database schema
-
- #region Type schema
-
- if ((mapperSchema && !Schema.ContainsKey(mapper.Type.FullName)) ||
- (schema == null && mapper != null && !mapper.Type.IsAnonymous()))
- {
- // TODO: Ged rid of this monster below...
- if (databaseSchemaSupport)
- {
- #region Merge with db schema
-
- schema = mapper.ColumnsMap.ToDictionary(k => k.Key, (v) =>
- {
- DynamicSchemaColumn? col = Schema[tableName.ToLower()].TryGetNullable(v.Key);
-
- return new DynamicSchemaColumn
- {
- Name = DynamicExtensions.Coalesce(
- v.Value.Column == null || string.IsNullOrEmpty(v.Value.Column.Name)
- ? null
- : v.Value.Column.Name,
- col.HasValue && !string.IsNullOrEmpty(col.Value.Name) ? col.Value.Name : null,
- v.Value.Name),
- IsKey = DynamicExtensions.CoalesceNullable(
- v.Value.Column != null ? v.Value.Column.IsKey : false,
- col.HasValue ? col.Value.IsKey : false).Value,
- Type = DynamicExtensions.CoalesceNullable(
- v.Value.Column != null ? v.Value.Column.Type : null,
- col.HasValue
- ? col.Value.Type
- : DynamicExtensions.TypeMap.TryGetNullable(v.Value.Type) ?? DbType.String).Value,
- IsUnique = DynamicExtensions.CoalesceNullable(
- v.Value.Column != null ? v.Value.Column.IsUnique : null,
- col.HasValue ? col.Value.IsUnique : false).Value,
- AllowNull = DynamicExtensions.CoalesceNullable(
- v.Value.Column != null ? v.Value.Column.AllowNull : true,
- col.HasValue ? col.Value.AllowNull : true).Value,
- Size = DynamicExtensions.CoalesceNullable(
- v.Value.Column != null ? v.Value.Column.Size : null,
- col.HasValue ? col.Value.Size : 0).Value,
- Precision = DynamicExtensions.CoalesceNullable(
- v.Value.Column != null ? v.Value.Column.Precision : null,
- col.HasValue ? col.Value.Precision : (byte)0).Value,
- Scale = DynamicExtensions.CoalesceNullable(
- v.Value.Column != null ? v.Value.Column.Scale : null,
- col.HasValue ? col.Value.Scale : (byte)0).Value,
- };
- });
-
- #endregion Merge with db schema
- }
- else
- {
- #region MapEnumerable based only on type
-
- schema = mapper.ColumnsMap.ToDictionary(k => k.Key,
- v => new DynamicSchemaColumn
- {
- Name = DynamicExtensions.Coalesce(
- v.Value.Column == null || string.IsNullOrEmpty(v.Value.Column.Name)
- ? null
- : v.Value.Column.Name, v.Value.Name),
- IsKey = DynamicExtensions
- .CoalesceNullable(v.Value.Column != null ? v.Value.Column.IsKey : false, false)
- .Value,
- Type = DynamicExtensions
- .CoalesceNullable(v.Value.Column != null ? v.Value.Column.Type : null,
- DynamicExtensions.TypeMap.TryGetNullable(v.Value.Type) ?? DbType.String).Value,
- IsUnique = DynamicExtensions
- .CoalesceNullable(v.Value.Column != null ? v.Value.Column.IsUnique : null, false)
- .Value,
- AllowNull = DynamicExtensions
- .CoalesceNullable(v.Value.Column != null ? v.Value.Column.AllowNull : true, true)
- .Value,
- Size = DynamicExtensions
- .CoalesceNullable(v.Value.Column != null ? v.Value.Column.Size : null, 0).Value,
- Precision = DynamicExtensions
- .CoalesceNullable(v.Value.Column != null ? v.Value.Column.Precision : null, 0)
- .Value,
- Scale = DynamicExtensions
- .CoalesceNullable(v.Value.Column != null ? v.Value.Column.Scale : null, 0).Value,
- });
-
- #endregion MapEnumerable based only on type
- }
- }
-
- if (mapper != null && schema != null)
- Schema[mapper.Type.FullName] = schema;
-
- #endregion Type schema
-
- return schema;
- }
-
- #endregion Schema
-
- #region Decorators
-
- /// Gets or sets left side decorator for database objects.
- public string LeftDecorator
- {
- get { return _leftDecorator; }
- set
- {
- _leftDecorator = value;
- _leftDecoratorIsInInvalidMembersChars =
- _leftDecorator.Length == 1 && StringExtensions.InvalidMemberChars.Contains(_leftDecorator[0]);
- }
- }
-
- /// Gets or sets right side decorator for database objects.
- public string RightDecorator
- {
- get { return _rightDecorator; }
- set
- {
- _rightDecorator = value;
- _rightDecoratorIsInInvalidMembersChars =
- _rightDecorator.Length == 1 && StringExtensions.InvalidMemberChars.Contains(_rightDecorator[0]);
- }
- }
-
- /// Gets or sets parameter name format.
- public string ParameterFormat
- {
- get { return _parameterFormat; }
- set { _parameterFormat = value; }
- }
-
- /// Decorate string representing name of database object.
- /// Name of database object.
- /// Decorated name of database object.
- public string DecorateName(string name)
- {
- return String.Concat(_leftDecorator, name, _rightDecorator);
- }
-
- /// Strip string representing name of database object from decorators.
- /// Decorated name of database object.
- /// Not decorated name of database object.
- public string StripName(string name)
- {
- string res = name.Trim(StringExtensions.InvalidMemberChars);
-
- if (!_leftDecoratorIsInInvalidMembersChars && res.StartsWith(_leftDecorator))
- res = res.Substring(_leftDecorator.Length);
-
- if (!_rightDecoratorIsInInvalidMembersChars && res.EndsWith(_rightDecorator))
- res = res.Substring(0, res.Length - _rightDecorator.Length);
-
- return res;
- }
-
- /// Decorate string representing name of database object.
- /// String builder to which add decorated name.
- /// Name of database object.
- public void DecorateName(StringBuilder sb, string name)
- {
- sb.Append(_leftDecorator);
- sb.Append(name);
- sb.Append(_rightDecorator);
- }
-
- /// Get database parameter name.
- /// Friendly parameter name or number.
- /// Formatted parameter name.
- public string GetParameterName(object parameter)
- {
- return String.Format(_parameterFormat, parameter).Replace(" ", "_");
- }
-
- /// Get database parameter name.
- /// String builder to which add parameter name.
- /// Friendly parameter name or number.
- public void GetParameterName(StringBuilder sb, object parameter)
- {
- sb.AppendFormat(_parameterFormat, parameter.ToString().Replace(" ", "_"));
- }
-
- /// Dumps the command into console output.
- /// The command to dump.
- public virtual void DumpCommand(IDbCommand cmd)
- {
- if (DumpCommandDelegate != null)
- DumpCommandDelegate(cmd, cmd.DumpToString());
- else
- cmd.Dump(Console.Out);
- }
-
- #endregion Decorators
-
- #region Connection
-
- /// Open managed connection.
- /// Opened connection.
- public IDbConnection Open()
- {
- IDbConnection conn = null;
- DynamicConnection ret = null;
- bool opened = false;
-
- lock (SyncLock)
- {
- if (_tempConn == null)
- {
- if (TransactionPool.Count == 0 || !_singleConnection)
- {
- conn = _provider.CreateConnection();
- conn.ConnectionString = _connectionString;
- conn.Open();
- opened = true;
-
- TransactionPool.Add(conn, new Stack());
- CommandsPool.Add(conn, new List());
- }
- else
- {
- conn = TransactionPool.Keys.First();
-
- if (conn.State != ConnectionState.Open)
- {
- conn.Open();
- opened = true;
- }
- }
-
- ret = new DynamicConnection(this, conn, _singleTransaction);
- }
- else
- ret = _tempConn;
- }
-
- if (opened)
- ExecuteInitCommands(ret);
-
- return ret;
- }
-
- /// Close connection if we are allowed to.
- /// Connection to manage.
- internal void Close(IDbConnection connection)
- {
- if (connection == null)
- return;
-
- if (!_singleConnection && connection != null && TransactionPool.ContainsKey(connection))
- {
- // Close all commands
- if (CommandsPool.ContainsKey(connection))
- {
- List tmp = CommandsPool[connection].ToList();
- tmp.ForEach(cmd => cmd.Dispose());
-
- CommandsPool[connection].Clear();
- }
-
- // Rollback remaining transactions
- while (TransactionPool[connection].Count > 0)
- {
- IDbTransaction trans = TransactionPool[connection].Pop();
- trans.Rollback();
- trans.Dispose();
- }
-
- // Close connection
- if (connection.State == ConnectionState.Open)
- connection.Close();
-
- // remove from pools
- lock (SyncLock)
- {
- TransactionPool.Remove(connection);
- CommandsPool.Remove(connection);
- }
-
- // Set stamp
- _poolStamp = DateTime.Now.Ticks;
-
- // Dispose the corpse
- connection.Dispose();
- connection = null;
- }
- }
-
- /// Gets or sets contains commands executed when connection is opened.
- public List InitCommands { get; set; }
-
- private void ExecuteInitCommands(IDbConnection conn)
- {
- if (InitCommands != null)
- using (IDbCommand command = conn.CreateCommand())
- foreach (string commandText in InitCommands)
- command
- .SetCommand(commandText)
- .ExecuteNonQuery();
- }
-
- #endregion Connection
-
- #region Transaction
-
- /// Begins a global database transaction.
- /// Using this method connection is set to single open
- /// connection until all transactions are finished.
- /// Returns representation.
- public IDbTransaction BeginTransaction()
- {
- _tempConn = Open() as DynamicConnection;
-
- return _tempConn.BeginTransaction(null, null, () =>
- {
- Stack t = TransactionPool.TryGetValue(_tempConn.Connection);
-
- if (t == null | t.Count == 0)
- {
- _tempConn.Dispose();
- _tempConn = null;
- }
- });
- }
-
- /// Begins a database transaction with the specified
- /// value.
- /// One of the values.
- /// Returns representation.
- public IDbTransaction BeginTransaction(IsolationLevel il)
- {
- _tempConn = Open() as DynamicConnection;
-
- return _tempConn.BeginTransaction(il, null, () =>
- {
- Stack t = TransactionPool.TryGetValue(_tempConn.Connection);
-
- if (t == null | t.Count == 0)
- {
- _tempConn.Dispose();
- _tempConn = null;
- }
- });
- }
-
- /// Begins a database transaction with the specified
- /// value.
- /// Custom parameter describing transaction options.
- /// Returns representation.
- public IDbTransaction BeginTransaction(object custom)
- {
- _tempConn = Open() as DynamicConnection;
-
- return _tempConn.BeginTransaction(null, custom, () =>
- {
- Stack t = TransactionPool.TryGetValue(_tempConn.Connection);
-
- if (t == null | t.Count == 0)
- {
- _tempConn.Dispose();
- _tempConn = null;
- }
- });
- }
-
- #endregion Transaction
-
- #region IExtendedDisposable Members
-
- /// Performs application-defined tasks associated with freeing,
- /// releasing, or resetting unmanaged resources.
- public void Dispose()
- {
-#if !DYNAMORM_OMMIT_OLDSYNTAX
- List tables = TablesCache.Values.ToList();
- TablesCache.Clear();
-
- tables.ForEach(t => t.Dispose());
- tables.Clear();
- tables = null;
-#endif
-
- foreach (KeyValuePair> con in TransactionPool)
- {
- // Close all commands
- if (CommandsPool.ContainsKey(con.Key))
- {
- List tmp = CommandsPool[con.Key].ToList();
- tmp.ForEach(cmd => cmd.Dispose());
-
- CommandsPool[con.Key].Clear();
- tmp.Clear();
- CommandsPool[con.Key] = tmp = null;
- }
-
- // Rollback remaining transactions
- while (con.Value.Count > 0)
- {
- IDbTransaction trans = con.Value.Pop();
- trans.Rollback();
- trans.Dispose();
- }
-
- // Close connection
- if (con.Key.State == ConnectionState.Open)
- con.Key.Close();
-
- // Dispose it
- con.Key.Dispose();
- }
-
- while (RemainingBuilders.Count > 0)
- RemainingBuilders.First().Dispose();
-
- // Clear pools
- lock (SyncLock)
- {
- TransactionPool.Clear();
- CommandsPool.Clear();
- RemainingBuilders.Clear();
-
- TransactionPool = null;
- CommandsPool = null;
- RemainingBuilders = null;
- }
-
- ClearSchema();
- if (_proc != null)
- _proc.Dispose();
-
- IsDisposed = true;
- }
-
- /// Gets a value indicating whether this instance is disposed.
- public bool IsDisposed { get; private set; }
-
- #endregion IExtendedDisposable Members
- }
-
- /// Represents database connection options.
- [Flags]
- [System.Reflection.ObfuscationAttribute(Feature = "renaming", ApplyToMembers = true)]
- public enum DynamicDatabaseOptions
- {
- /// No specific options.
- None = 0x00000000,
-
- /// Only single persistent database connection.
- SingleConnection = 0x00000001,
-
- /// Only one transaction.
- SingleTransaction = 0x00000002,
-
- /// Database supports top syntax (SELECT TOP x ... FROM ...).
- SupportTop = 0x00000080,
-
- /// Database supports limit offset syntax (SELECT ... FROM ... LIMIT x OFFSET y).
- SupportLimitOffset = 0x00000040,
-
- /// Database supports limit offset syntax (SELECT FIRST x SKIP y ... FROM ...).
- SupportFirstSkip = 0x00000020,
-
- /// Database support standard schema.
- SupportSchema = 0x00000010,
-
- /// Database support stored procedures (EXEC procedure ...).
- SupportStoredProcedures = 0x00000100,
-
- /// Database support stored procedures results (Return value).
- SupportStoredProceduresResult = 0x00000200,
-
- /// Database support with no lock syntax.
- SupportNoLock = 0x00001000,
-
- /// Debug option allowing to enable command dumps by default.
- DumpCommands = 0x01000000,
- }
-
- /// Dynamic expando is a simple and temporary class to resolve memory leaks inside ExpandoObject.
- public class DynamicExpando : DynamicObject, IDictionary, ICollection>,
- IEnumerable>, IEnumerable
- {
- /// Class containing information about last accessed property of dynamic object.
- public class PropertyAccess
- {
- /// Enum describing type of access to object.
- public enum TypeOfAccess
- {
- /// Get member.
- Get,
-
- /// Set member.
- Set,
- }
-
- /// Gets the type of operation.
- public TypeOfAccess Operation { get; internal set; }
-
- /// Gets the name of property.
- public string Name { get; internal set; }
-
- /// Gets the type from binder.
- public Type RequestedType { get; internal set; }
-
- /// Gets the type of value stored in object.
- public Type Type { get; internal set; }
-
- /// Gets the value stored in object.
- public object Value { get; internal set; }
-
- /// Gets the last access time.
- public long Ticks { get; internal set; }
- }
-
- private Dictionary _data = new Dictionary();
-
- private PropertyAccess _lastProp = new PropertyAccess();
-
- /// Initializes a new instance of the class.
- public DynamicExpando()
- {
- }
-
- /// Gets the last accesses property.
- /// Description of last accessed property.
- public PropertyAccess GetLastAccessesProperty()
- {
- return _lastProp;
- }
-
- /// Tries to get member value.
- /// Returns true , if get member was tried, false otherwise.
- /// The context binder.
- /// The invocation result.
- public override bool TryGetMember(GetMemberBinder binder, out object result)
- {
- result = _data.TryGetValue(binder.Name);
-
- _lastProp.Operation = PropertyAccess.TypeOfAccess.Get;
- _lastProp.RequestedType = binder.ReturnType;
- _lastProp.Name = binder.Name;
- _lastProp.Value = result;
- _lastProp.Type = result == null ? typeof(void) : result.GetType();
- _lastProp.Ticks = DateTime.Now.Ticks;
-
- return true;
- }
-
- /// Tries to set member.
- /// Returns true , if set member was tried, false otherwise.
- /// The context binder.
- /// Value which will be set.
- public override bool TrySetMember(SetMemberBinder binder, object value)
- {
- _data[binder.Name] = value;
-
- _lastProp.Operation = PropertyAccess.TypeOfAccess.Set;
- _lastProp.RequestedType = binder.ReturnType;
- _lastProp.Name = binder.Name;
- _lastProp.Value = value;
- _lastProp.Type = value == null ? typeof(void) : value.GetType();
- _lastProp.Ticks = DateTime.Now.Ticks;
-
- return true;
- }
-
- #region IDictionary implementation
-
- bool IDictionary.ContainsKey(string key)
- {
- return _data.ContainsKey(key);
- }
-
- void IDictionary.Add(string key, object value)
- {
- _data.Add(key, value);
- }
-
- bool IDictionary.Remove(string key)
- {
- return _data.Remove(key);
- }
-
- bool IDictionary.TryGetValue(string key, out object value)
- {
- return _data.TryGetValue(key, out value);
- }
-
- object IDictionary.this[string index]
- {
- get { return _data[index]; }
- set { _data[index] = value; }
- }
-
- ICollection IDictionary.Keys
- {
- get { return _data.Keys; }
- }
-
- ICollection IDictionary.Values
- {
- get { return _data.Values; }
- }
-
- #endregion IDictionary implementation
-
- #region ICollection implementation
-
- void ICollection>.Add(KeyValuePair item)
- {
- ((ICollection>)_data).Add(item);
- }
-
- void ICollection>.Clear()
- {
- _data.Clear();
- }
-
- bool ICollection>.Contains(KeyValuePair item)
- {
- return ((ICollection>)_data).Contains(item);
- }
-
- void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex)
- {
- ((ICollection>)_data).CopyTo(array, arrayIndex);
- }
-
- bool ICollection>.Remove(KeyValuePair item)
- {
- return ((ICollection>)_data).Remove(item);
- }
-
- int ICollection>.Count
- {
- get { return _data.Count; }
- }
-
- bool ICollection>.IsReadOnly
- {
- get { return ((ICollection>)_data).IsReadOnly; }
- }
-
- #endregion ICollection implementation
-
- #region IEnumerable implementation
-
- IEnumerator> IEnumerable>.GetEnumerator()
- {
- return _data.GetEnumerator();
- }
-
- #endregion IEnumerable implementation
-
- #region IEnumerable implementation
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable)_data).GetEnumerator();
- }
-
- #endregion IEnumerable implementation
- }
-
- /// Extension to ORM objects.
- public static class DynamicExtensions
- {
- #region Type column map
-
- /// MapEnumerable of .NET types to .
- public static readonly Dictionary TypeMap = new Dictionary()
- {
- { typeof(byte), DbType.Byte },
- { typeof(sbyte), DbType.SByte },
- { typeof(short), DbType.Int16 },
- { typeof(ushort), DbType.UInt16 },
- { typeof(int), DbType.Int32 },
- { typeof(uint), DbType.UInt32 },
- { typeof(long), DbType.Int64 },
- { typeof(ulong), DbType.UInt64 },
- { typeof(float), DbType.Single },
- { typeof(double), DbType.Double },
- { typeof(decimal), DbType.Decimal },
- { typeof(bool), DbType.Boolean },
- { typeof(string), DbType.String },
- { typeof(char), DbType.StringFixedLength },
- { typeof(Guid), DbType.Guid },
- { typeof(DateTime), DbType.DateTime },
- { typeof(TimeSpan), DbType.Time },
- { typeof(DateTimeOffset), DbType.DateTimeOffset },
- { typeof(byte[]), DbType.Binary },
- { typeof(byte?), DbType.Byte },
- { typeof(sbyte?), DbType.SByte },
- { typeof(short?), DbType.Int16 },
- { typeof(ushort?), DbType.UInt16 },
- { typeof(int?), DbType.Int32 },
- { typeof(uint?), DbType.UInt32 },
- { typeof(long?), DbType.Int64 },
- { typeof(ulong?), DbType.UInt64 },
- { typeof(float?), DbType.Single },
- { typeof(double?), DbType.Double },
- { typeof(decimal?), DbType.Decimal },
- { typeof(bool?), DbType.Boolean },
- { typeof(char?), DbType.StringFixedLength },
- { typeof(Guid?), DbType.Guid },
- { typeof(DateTime?), DbType.DateTime },
- { typeof(TimeSpan?), DbType.Time },
- { typeof(DateTimeOffset?), DbType.DateTimeOffset },
- };
-
- #endregion Type column map
-
- #region Command extensions
-
- /// Set connection on the fly.
- /// in which changes will be made.
- /// which will be set to instance.
- /// Returns edited instance.
- public static IDbCommand SetConnection(this IDbCommand command, IDbConnection connection)
- {
- command.Connection = connection;
-
- return command;
- }
-
- /// Set connection on the fly.
- /// in which changes will be made.
- /// which will be set to instance.
- /// Returns edited instance.
- public static IDbCommand SetTransaction(this IDbCommand command, IDbTransaction transaction)
- {
- command.Transaction = transaction;
-
- return command;
- }
-
- #region SetCommand
-
- /// Set properties on the fly.
- /// in which changes will be made.
- /// Indicates or specifies how the property is interpreted.
- /// The wait time before terminating the attempt to execute a command and generating an error.
- /// The text command to run against the data source.
- /// Arguments used to format command.
- /// Returns edited instance.
- public static IDbCommand SetCommand(this IDbCommand command, CommandType commandType, int commandTimeout,
- string commandText, params object[] args)
- {
- command.CommandType = commandType;
- command.CommandTimeout = commandTimeout;
-
- if (args != null && args.Length > 0)
- command.CommandText = string.Format(commandText, args);
- else
- command.CommandText = commandText;
-
- return command;
- }
-
- /// Set properties on the fly.
- /// in which changes will be made.
- /// The wait time before terminating the attempt to execute a command and generating an error.
- /// The text command to run against the data source.
- /// Arguments used to format command.
- /// Returns edited instance.
- public static IDbCommand SetCommand(this IDbCommand command, int commandTimeout, string commandText,
- params object[] args)
- {
- command.CommandTimeout = commandTimeout;
-
- if (args != null && args.Length > 0)
- command.CommandText = string.Format(commandText, args);
- else
- command.CommandText = commandText;
-
- return command;
- }
-
- /// Set properties on the fly.
- /// in which changes will be made.
- /// Indicates or specifies how the property is interpreted.
- /// The text command to run against the data source.
- /// Arguments used to format command.
- /// Returns edited instance.
- public static IDbCommand SetCommand(this IDbCommand command, CommandType commandType, string commandText,
- params object[] args)
- {
- command.CommandType = commandType;
-
- if (args != null && args.Length > 0)
- command.CommandText = string.Format(commandText, args);
- else
- command.CommandText = commandText;
-
- return command;
- }
-
- /// Set properties on the fly.
- /// in which changes will be made.
- /// The text command to run against the data source.
- /// Arguments used to format command.
- /// Returns edited instance.
- public static IDbCommand SetCommand(this IDbCommand command, string commandText, params object[] args)
- {
- if (args != null && args.Length > 0)
- command.CommandText = string.Format(commandText, args);
- else
- command.CommandText = commandText;
-
- return command;
- }
-
- /// Set properties on the fly.
- /// in which changes will be made.
- /// Command builder.
- /// Returns edited instance.
- public static IDbCommand SetCommand(this IDbCommand command, IDynamicQueryBuilder builder)
- {
- builder.FillCommand(command);
-
- return command;
- }
-
- #endregion SetCommand
-
- #region AddParameter
-
- /// Extension method for adding in a bunch of parameters.
- /// Command to handle.
- /// Database object required to get proper formatting.
- /// Items to add.
- /// Returns edited instance.
- public static IDbCommand AddParameters(this IDbCommand cmd, DynamicDatabase database, params object[] args)
- {
- if (args != null && args.Count() > 0)
- foreach (object item in args)
- {
- if (item is DynamicExpando)
- cmd.AddParameters(database, (DynamicExpando)item);
- else if (item is ExpandoObject)
- cmd.AddParameters(database, (ExpandoObject)item);
- else
- cmd.AddParameter(database, item);
- }
-
- return cmd;
- }
-
- /// Extension method for adding in a bunch of parameters.
- /// Command to handle.
- /// Database object required to get proper formatting.
- /// Items to add in an expando object.
- /// Returns edited instance.
- public static IDbCommand AddParameters(this IDbCommand cmd, DynamicDatabase database, ExpandoObject args)
- {
- if (args != null && args.Count() > 0)
- foreach (KeyValuePair item in args.ToDictionary())
- cmd.AddParameter(database, item.Key, item.Value);
-
- return cmd;
- }
-
- /// Extension method for adding in a bunch of parameters.
- /// Command to handle.
- /// Database object required to get proper formatting.
- /// Items to add in an expando object.
- /// Returns edited instance.
- public static IDbCommand AddParameters(this IDbCommand cmd, DynamicDatabase database, DynamicExpando args)
- {
- if (args != null && args.Count() > 0)
- foreach (KeyValuePair item in args.ToDictionary())
- cmd.AddParameter(database, item.Key, item.Value);
-
- return cmd;
- }
-
- /// Extension for adding single parameter determining only type of object.
- /// Command to handle.
- /// Database object required to get proper formatting.
- /// Items to add.
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand cmd, DynamicDatabase database, object item)
- {
- return cmd.AddParameter(database, database.GetParameterName(cmd.Parameters.Count), item);
- }
-
- /// Extension for adding single parameter determining only type of object.
- /// Command to handle.
- /// Database object required to get proper formatting.
- /// Name of parameter.
- /// Items to add.
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand cmd, DynamicDatabase database, string name, object item)
- {
- IDbDataParameter p = cmd.CreateParameter();
- p.ParameterName = name;
-
- if (item == null || item == DBNull.Value)
- p.Value = DBNull.Value;
- else
- {
- Type type = item.GetType();
-
- p.DbType = TypeMap.TryGetNullable(type) ?? DbType.String;
-
- if (type == typeof(DynamicExpando) || type == typeof(ExpandoObject))
- p.Value = CorrectValue(p.DbType, ((IDictionary)item).Values.FirstOrDefault());
- else
- p.Value = CorrectValue(p.DbType, item);
-
- if (p.DbType == DbType.String)
- p.Size = item.ToString().Length > 4000 ? -1 : 4000;
- else if (p.DbType == DbType.AnsiString)
- p.Size = item.ToString().Length > 8000 ? -1 : 8000;
- }
-
- cmd.Parameters.Add(p);
-
- return cmd;
- }
-
- /// Extension for adding single parameter determining only type of object.
- /// Command to handle.
- /// Query builder containing schema.
- /// Column schema to use.
- /// Parameter value.
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand cmd, IDynamicQueryBuilder builder,
- DynamicSchemaColumn? col, object value)
- {
- IDbDataParameter p = cmd.CreateParameter();
- p.ParameterName = builder.Database.GetParameterName(cmd.Parameters.Count);
-
- if (col.HasValue)
- {
- p.DbType = col.Value.Type;
-
- if ((builder.Database.Options & DynamicDatabaseOptions.SupportSchema) ==
- DynamicDatabaseOptions.SupportSchema)
- {
- p.Size = col.Value.Size;
- p.Precision = col.Value.Precision;
- p.Scale = col.Value.Scale;
-
- // Quick fix - review that
- // Quick fix 2 - use item.Schema in that case
- if (p.Scale > p.Precision)
- p.Scale = 4;
- }
-
- p.Value = CorrectValue(p.DbType, value);
- }
- else if (value == null || value == DBNull.Value)
- p.Value = DBNull.Value;
- else
- {
- p.DbType = TypeMap.TryGetNullable(value.GetType()) ?? DbType.String;
-
- if (p.DbType == DbType.AnsiString)
- p.Size = value.ToString().Length > 8000 ? -1 : 8000;
- else if (p.DbType == DbType.String)
- p.Size = value.ToString().Length > 4000 ? -1 : 4000;
-
- p.Value = CorrectValue(p.DbType, value);
- }
-
- cmd.Parameters.Add(p);
-
- return cmd;
- }
-
- private static object CorrectValue(DbType type, object value)
- {
- if (value == null || value == DBNull.Value)
- return DBNull.Value;
-
- if ((type == DbType.String || type == DbType.AnsiString || type == DbType.StringFixedLength ||
- type == DbType.AnsiStringFixedLength) &&
- !(value is string))
- return value.ToString();
- else if (type == DbType.Guid && value is string)
- return Guid.Parse(value.ToString());
- else if (type == DbType.Guid && value is byte[] && ((byte[])value).Length == 16)
- return new Guid((byte[])value);
- else if
- (type == DbType.DateTime &&
- value is TimeSpan) // HACK: This is specific for SQL Server, to be verified with other databases
- return DateTime.Today.Add((TimeSpan)value);
-
- return value;
- }
-
- /// Extension for adding single parameter determining only type of object.
- /// Command to handle.
- /// Query builder containing schema.
- /// Column item to add.
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand cmd, IDynamicQueryBuilder builder, DynamicColumn item)
- {
- IDbDataParameter p = cmd.CreateParameter();
- p.ParameterName = builder.Database.GetParameterName(cmd.Parameters.Count);
-
- DynamicSchemaColumn? col = item.Schema ?? (builder as DynamicQueryBuilder)
- .NullOr(b => b.GetColumnFromSchema(item.ColumnName),
- builder.Tables.FirstOrDefault()
- .NullOr(t => t.Schema
- .NullOr(s => s.TryGetNullable(item.ColumnName.ToLower()), null), null));
-
- if (col.HasValue)
- {
- p.DbType = col.Value.Type;
-
- if (builder.SupportSchema)
- {
- p.Size = col.Value.Size;
- p.Precision = col.Value.Precision;
- p.Scale = col.Value.Scale;
-
- // Quick fix - review that
- // Quick fix 2 - use item.Schema in that case
- if (p.Scale > p.Precision)
- p.Scale = 4;
- }
-
- p.Value = item.Value == null ? DBNull.Value : CorrectValue(p.DbType, item.Value);
- }
- else if (item.Value == null || item.Value == DBNull.Value)
- p.Value = DBNull.Value;
- else
- {
- p.DbType = TypeMap.TryGetNullable(item.Value.GetType()) ?? DbType.String;
-
- if (p.DbType == DbType.AnsiString)
- p.Size = item.Value.ToString().Length > 8000 ? -1 : 8000;
- else if (p.DbType == DbType.String)
- p.Size = item.Value.ToString().Length > 4000 ? -1 : 4000;
-
- p.Value = CorrectValue(p.DbType, item.Value);
- }
-
- cmd.Parameters.Add(p);
-
- return cmd;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// Value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value .
- /// The of the .
- /// The size of the parameter.
- /// Indicates the precision of numeric parameters.
- /// Indicates the scale of numeric parameters.
- /// The value of the .
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName,
- ParameterDirection parameterDirection, DbType databaseType, int size, byte precision, byte scale,
- object value)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.Direction = parameterDirection;
- param.DbType = databaseType;
- param.Size = size;
- param.Precision = precision;
- param.Scale = scale;
- param.Value = CorrectValue(param.DbType, value);
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// Value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value .
- /// The of the .
- /// The size of the parameter.
- /// Indicates the precision of numeric parameters.
- /// Indicates the scale of numeric parameters.
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName,
- ParameterDirection parameterDirection, DbType databaseType, int size, byte precision, byte scale)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.Direction = parameterDirection;
- param.DbType = databaseType;
- param.Size = size;
- param.Precision = precision;
- param.Scale = scale;
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// Value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value .
- /// The of the .
- /// Indicates the precision of numeric parameters.
- /// Indicates the scale of numeric parameters.
- /// The value of the .
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName,
- ParameterDirection parameterDirection, DbType databaseType, byte precision, byte scale, object value)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.Direction = parameterDirection;
- param.DbType = databaseType;
- param.Precision = precision;
- param.Scale = scale;
- param.Value = CorrectValue(param.DbType, value);
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// The of the .
- /// Indicates the precision of numeric parameters.
- /// Indicates the scale of numeric parameters.
- /// The value of the .
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName, DbType databaseType,
- byte precision, byte scale, object value)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.DbType = databaseType;
- param.Precision = precision;
- param.Scale = scale;
- param.Value = CorrectValue(param.DbType, value);
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// The of the .
- /// Indicates the precision of numeric parameters.
- /// Indicates the scale of numeric parameters.
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName, DbType databaseType,
- byte precision, byte scale)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.DbType = databaseType;
- param.Precision = precision;
- param.Scale = scale;
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// Value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value .
- /// The of the .
- /// The size of the parameter.
- /// The value of the .
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName,
- ParameterDirection parameterDirection, DbType databaseType, int size, object value)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.Direction = parameterDirection;
- param.DbType = databaseType;
- param.Size = size;
- param.Value = CorrectValue(param.DbType, value ?? DBNull.Value);
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// The of the .
- /// The size of the parameter.
- /// The value of the .
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName, DbType databaseType,
- int size, object value)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.DbType = databaseType;
- param.Size = size;
- param.Value = CorrectValue(param.DbType, value ?? DBNull.Value);
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// The of the .
- /// The value of the .
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName, DbType databaseType,
- object value)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.DbType = databaseType;
- param.Value = CorrectValue(param.DbType, value ?? DBNull.Value);
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// The of the .
- /// The size of the parameter.
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName, DbType databaseType,
- int size)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.DbType = databaseType;
- param.Size = size;
- command.Parameters.Add(param);
-
- return command;
- }
-
- /// Add to on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// The of the .
- /// Returns edited instance.
- public static IDbCommand AddParameter(this IDbCommand command, string parameterName, DbType databaseType)
- {
- IDbDataParameter param = command.CreateParameter();
- param.ParameterName = parameterName;
- param.DbType = databaseType;
- command.Parameters.Add(param);
-
- return command;
- }
-
- #endregion AddParameter
-
- #region SetParameter
-
- /// Set value for on the fly.
- /// to which parameter will be added.
- /// The name of the .
- /// Value to set on this parameter.
- /// Returns edited instance.
- public static IDbCommand SetParameter(this IDbCommand command, string parameterName, object value)
- {
- try
- {
- var p = ((IDbDataParameter)command.Parameters[parameterName]);
- p.Value = CorrectValue(p.DbType, value);
- }
- catch (Exception ex)
- {
- throw new ArgumentException(
- string.Format("Error setting parameter {0} in command {1}", parameterName,
- command.CommandText ?? string.Empty), ex);
- }
-
- return command;
- }
-
- /// Set value for on the fly.
- /// to which parameter will be added.
- /// Index of the .
- /// Value to set on this parameter.
- /// Returns edited instance.
- public static IDbCommand SetParameter(this IDbCommand command, int index, object value)
- {
- try
- {
- var p = ((IDbDataParameter)command.Parameters[index]);
- p.Value = CorrectValue(p.DbType, value);
- }
- catch (Exception ex)
- {
- throw new ArgumentException(
- string.Format("Error setting parameter {0} in command {1}", index,
- command.CommandText ?? string.Empty), ex);
- }
-
- return command;
- }
-
- #endregion SetParameter
-
- #region Generic Execution
-
-#if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE
-
- /// Execute scalar and return string if possible.
- /// Type to parse to.
- /// which will be executed.
- /// Returns resulting instance of T from query.
- public static T ExecuteScalarAs(this IDbCommand command)
- {
- return ExecuteScalarAs(command, default(T), null);
- }
-
- /// Execute scalar and return string if possible.
- /// Type to parse to.
- /// which will be executed.
- /// Handler of a try parse method.
- /// Returns resulting instance of T from query.
- public static T ExecuteScalarAs(this IDbCommand command, DynamicExtensions.TryParseHandler handler)
- {
- return ExecuteScalarAs(command, default(T), handler);
- }
-
- /// Execute scalar and return string if possible.
- /// Type to parse to.
- /// which will be executed.
- /// Default result value.
- /// Returns resulting instance of T from query.
- public static T ExecuteScalarAs(this IDbCommand command, T defaultValue)
- {
- return ExecuteScalarAs(command, defaultValue, null);
- }
-
- /// Execute scalar and return string if possible.
- /// Type to parse to.
- /// which will be executed.
- /// Default result value.
- /// Handler of a try parse method.
- /// Returns resulting instance of T from query.
- public static T ExecuteScalarAs(this IDbCommand command, T defaultValue,
- DynamicExtensions.TryParseHandler handler)
- {
- T ret = defaultValue;
-
- object o = command.ExecuteScalar();
-
- if (o is T)
- return (T)o;
- else if (o != DBNull.Value && o != null)
- {
- if (handler != null)
- ret = o.ToString().TryParseDefault(defaultValue, handler);
- else if (o is IConvertible && typeof(T).GetInterfaces().Any(i => i == typeof(IConvertible)))
- ret = (T)Convert.ChangeType(o, typeof(T));
- else if (typeof(T) == typeof(Guid))
- {
- if (o.GetType() == typeof(byte[]))
- ret = (T)(object)new Guid((byte[])o);
- else
- ret = (T)(object)Guid.Parse(o.ToString());
- }
- else if (typeof(T) == typeof(string))
- ret = (T)(o.ToString() as object);
- else if (typeof(T) == typeof(object))
- ret = (T)o;
- else
- {
- MethodInfo method = typeof(T).GetMethod(
- "TryParse",
- new Type[]
- {
- typeof(string),
- Type.GetType(string.Format("{0}&", typeof(T).FullName))
- });
-
- if (method != null)
- ret = o.ToString().TryParseDefault(defaultValue, delegate(string v, out T r)
- {
- r = defaultValue;
- return (bool)method.Invoke(null, new object[] { v, r });
- });
- else
- throw new InvalidOperationException("Provided type can't be parsed using generic approach.");
- }
- }
-
- return ret;
- }
-
- /// Execute enumerator of specified type.
- /// Type to parse to.
- /// which will be executed.
- /// Default result value.
- /// Handler of a try parse method.
- /// Returns enumerator of specified type from query.
- public static IEnumerable ExecuteEnumeratorOf(this IDbCommand command, T defaultValue,
- DynamicExtensions.TryParseHandler handler) where T : struct
- {
- using (IDataReader reader = command.ExecuteReader())
- {
- MethodInfo method = typeof(T).GetMethod(
- "TryParse",
- new[]
- {
- typeof(string),
- Type.GetType(string.Format("{0}&", typeof(T).FullName))
- });
-
- while (reader.Read())
- {
- T ret = defaultValue;
-
- if (!reader.IsDBNull(0))
- {
- object o = reader.GetValue(0);
-
- if (o is T)
- ret = (T)o;
- else if (o != DBNull.Value)
- {
- if (handler != null)
- ret = o.ToString().TryParseDefault(defaultValue, handler);
- else if (o is IConvertible && typeof(T).GetInterfaces().Any(i => i == typeof(IConvertible)))
- ret = (T)Convert.ChangeType(o, typeof(T));
- else if (typeof(T) == typeof(Guid))
- {
- if (o.GetType() == typeof(byte[]))
- ret = (T)(object)new Guid((byte[])o);
- else
- ret = (T)(object)Guid.Parse(o.ToString());
- }
- else if (typeof(T) == typeof(string))
- ret = (T)(o.ToString() as object);
- else if (typeof(T) == typeof(object))
- ret = (T)o;
- else if (method != null)
- ret = o.ToString().TryParseDefault(defaultValue, delegate(string v, out T r)
- {
- r = defaultValue;
- return (bool)method.Invoke(null, new object[] { v, r });
- });
- else
- throw new InvalidOperationException(
- "Provided type can't be parsed using generic approach.");
- }
- }
-
- yield return ret;
- }
- }
- }
-
-#endif
-
- #endregion Generic Execution
-
- /// Dump command into string.
- /// Command to dump.
- /// Returns dumped instance in string form.
- public static string DumpToString(this IDbCommand command)
- {
- StringBuilder sb = new StringBuilder();
- command.Dump(sb);
- return sb.ToString();
- }
-
- /// Dump command into text writer.
- /// Command to dump.
- /// Builder to which write output.
- /// Returns dumped instance.
- public static IDbCommand Dump(this IDbCommand command, StringBuilder buider)
- {
- using (StringWriter sw = new StringWriter(buider))
- return command.Dump(sw);
- }
-
- /// Dump command into text writer.
- /// Command to dump.
- /// Writer to which write output.
- /// Returns dumped instance.
- public static IDbCommand Dump(this IDbCommand command, TextWriter writer)
- {
- try
- {
- writer.WriteLine("Type: {0}; Timeout: {1}; Query: {2}", command.CommandType, command.CommandTimeout,
- command.CommandText);
-
- if (command.Parameters.Count > 0)
- {
- writer.WriteLine("Parameters:");
-
- foreach (IDbDataParameter param in command.Parameters)
- {
- writer.WriteLine(" '{0}' ({1} (s:{2} p:{3} s:{4})) = '{5}' ({6});",
- param.ParameterName,
- param.DbType,
- param.Scale,
- param.Precision,
- param.Scale,
- param.Value is byte[]
- ? ConvertByteArrayToHexString((byte[])param.Value)
- : param.Value ?? "NULL",
- param.Value != null ? param.Value.GetType().Name : "DBNull");
- }
-
- writer.WriteLine();
- }
- }
- catch (NullReferenceException)
- {
- writer.WriteLine("Command disposed.");
- }
-
- return command;
- }
-
- /// Convert byte array to hex formatted string without separators.
- /// Byte Array Data.
- /// Hex string representation of byte array.
- private static string ConvertByteArrayToHexString(byte[] data)
- {
- return ConvertByteArrayToHexString(data, 0);
- }
-
- /// Convert byte array to hex formatted string.
- /// Byte Array Data.
- /// Put '-' each separatorEach characters.
- /// Hex string representation of byte array.
- private static string ConvertByteArrayToHexString(byte[] data, int separatorEach)
- {
- int len = data.Length * 2;
- System.Text.StringBuilder sb = new System.Text.StringBuilder();
- for (int i = 0; i < len; i++)
- {
- sb.AppendFormat("{0:X}", data[(i / 2)] >> (((i % 2) == 0) ? 4 : 0) & 0x0F);
- if ((separatorEach > 0) && ((i + 1) % separatorEach == 0))
- sb.AppendFormat("-");
- }
-
- return sb.ToString();
- }
-
- #endregion Command extensions
-
- #region Dynamic builders extensions
-
- /// Turns an to a Dynamic list of things.
- /// Ready to execute builder.
- /// List of things.
- public static List ToList(this IDynamicSelectQueryBuilder b)
- {
- return b.Execute().ToList();
- }
-
- /// Turns an to a Dynamic list of things with specified type.
- /// Type of object to map on.
- /// Ready to execute builder.
- /// List of things.
- public static List ToList(this IDynamicSelectQueryBuilder b) where T : class
- {
- return b.Execute().ToList();
- }
-
- /// Sets the on create temporary parameter action.
- /// Class implementing interface.
- /// The builder on which set delegate.
- /// Action to invoke.
- /// Returns instance of builder on which action is set.
- public static T CreateTemporaryParameterAction(this T b, Action a) where T : IDynamicQueryBuilder
- {
- if (a != null)
- {
- if (b.OnCreateTemporaryParameter == null)
- b.OnCreateTemporaryParameter = new List>();
-
- b.OnCreateTemporaryParameter.Add(a);
- }
-
- return b;
- }
-
- /// Sets the on create real parameter action.
- /// Class implementing interface.
- /// The builder on which set delegate.
- /// Action to invoke.
- /// Returns instance of builder on which action is set.
- public static T CreateParameterAction(this T b, Action a)
- where T : IDynamicQueryBuilder
- {
- if (a != null)
- {
- if (b.OnCreateParameter == null)
- b.OnCreateParameter = new List>();
-
- b.OnCreateParameter.Add(a);
- }
-
- return b;
- }
-
- /// Sets the virtual mode on builder.
- /// Class implementing interface.
- /// The builder on which set virtual mode.
- /// Virtual mode.
- /// Returns instance of builder on which virtual mode is set.
- public static T SetVirtualMode(this T b, bool virtualMode) where T : IDynamicQueryBuilder
- {
- b.VirtualMode = virtualMode;
- return b;
- }
-
- /// Creates sub query that can be used inside of from/join/expressions.
- /// Class implementing interface.
- /// The builder that will be parent of new sub query.
- /// Instance of sub query.
- public static IDynamicSelectQueryBuilder SubQuery(this T b) where T : IDynamicQueryBuilder
- {
- return new DynamicSelectQueryBuilder(b.Database, b as DynamicQueryBuilder);
- }
-
- /// Creates sub query that can be used inside of from/join/expressions.
- /// Class implementing interface.
- /// The builder that will be parent of new sub query.
- /// The specification for sub query.
- /// The specification for sub query.
- /// Instance of sub query.
- public static IDynamicSelectQueryBuilder SubQuery(this T b, Func fn,
- params Func[] func) where T : IDynamicQueryBuilder
- {
- return new DynamicSelectQueryBuilder(b.Database, b as DynamicQueryBuilder).From(fn, func);
- }
-
- /// Creates sub query that can be used inside of from/join/expressions.
- /// Class implementing interface.
- /// The builder that will be parent of new sub query.
- /// First argument is parent query, second one is a sub query.
- /// This instance to permit chaining.
- public static T SubQuery(this T b, Action subquery)
- where T : IDynamicQueryBuilder
- {
- IDynamicSelectQueryBuilder sub = b.SubQuery();
-
- subquery(b, sub);
- try
- {
- (b as DynamicQueryBuilder).ParseCommand(sub as DynamicQueryBuilder, b.Parameters);
- }
- catch (ArgumentException)
- {
- // This might occur if join was made to subquery
- }
-
- return b;
- }
-
- /// Creates sub query that can be used inside of from/join/expressions.
- /// Class implementing interface.
- /// The builder that will be parent of new sub query.
- /// First argument is parent query, second one is a sub query.
- /// The specification for sub query.
- /// The specification for sub query.
- /// This instance to permit chaining.
- public static T SubQuery(this T b, Action subquery, Func fn,
- params Func[] func) where T : IDynamicQueryBuilder
- {
- IDynamicSelectQueryBuilder sub = b.SubQuery(fn, func);
-
- subquery(b, sub);
-
- (b as DynamicQueryBuilder).ParseCommand(sub as DynamicQueryBuilder, b.Parameters);
-
- return b;
- }
-
- #endregion Dynamic builders extensions
-
- #region Dynamic extensions
-
- /// Turns an to a Dynamic list of things.
- /// Reader from which read data.
- /// List of things.
- public static List ToList(this IDataReader r)
- {
- List result = new List();
-
- while (r.Read())
- result.Add(r.RowToDynamic());
-
- return result;
- }
-
- /// Turns the dictionary into an ExpandoObject.
- /// Dictionary to convert.
- /// Converted dictionary.
- public static dynamic ToDynamic(this IDictionary d)
- {
- DynamicExpando result = new DynamicExpando();
- IDictionary dict = (IDictionary)result;
-
- foreach (KeyValuePair prop in d)
- dict.Add(prop.Key, prop.Value);
-
- return result;
- }
-
- /// Turns the dictionary into an ExpandoObject.
- /// Dictionary to convert.
- /// Converted dictionary.
- public static dynamic ToExpando(this IDictionary d)
- {
- ExpandoObject result = new ExpandoObject();
- IDictionary dict = (IDictionary)result;
-
- foreach (KeyValuePair prop in d)
- dict.Add(prop.Key, prop.Value);
-
- return result;
- }
-
- /// Turns the object into an ExpandoObject.
- /// Object to convert.
- /// Converted object.
- public static dynamic ToDynamic(this object o)
- {
- Type ot = o.GetType();
-
- if (ot == typeof(DynamicExpando) || ot == typeof(ExpandoObject))
- return o;
-
- DynamicExpando result = new DynamicExpando();
- IDictionary dict = (IDictionary)result;
-
- if (o is IDictionary)
- ((IDictionary)o)
- .ToList()
- .ForEach(kvp => dict.Add(kvp.Key, kvp.Value));
- else if (ot == typeof(NameValueCollection) || ot.IsSubclassOf(typeof(NameValueCollection)))
- {
- NameValueCollection nameValue = (NameValueCollection)o;
- nameValue.Cast()
- .Select(key => new KeyValuePair(key, nameValue[key]))
- .ToList()
- .ForEach(i => dict.Add(i));
- }
- else
- {
- DynamicTypeMap mapper = DynamicMapperCache.GetMapper(ot);
-
- if (mapper != null)
- {
- foreach (DynamicPropertyInvoker item in mapper.ColumnsMap.Values)
- if (item.Get != null)
- dict.Add(item.Name, item.Get(o));
- }
- else
- {
- PropertyInfo[] props = ot.GetProperties();
-
- foreach (PropertyInfo item in props)
- if (item.CanRead)
- dict.Add(item.Name, item.GetValue(o, null));
- }
- }
-
- return result;
- }
-
- /// Turns the object into an ExpandoObject.
- /// Object to convert.
- /// Converted object.
- public static dynamic ToExpando(this object o)
- {
- Type ot = o.GetType();
-
- if (ot == typeof(ExpandoObject) || ot == typeof(DynamicExpando))
- return o;
-
- ExpandoObject result = new ExpandoObject();
- IDictionary dict = (IDictionary)result;
-
- if (o is IDictionary)
- ((IDictionary)o)
- .ToList()
- .ForEach(kvp => dict.Add(kvp.Key, kvp.Value));
- else if (ot == typeof(NameValueCollection) || ot.IsSubclassOf(typeof(NameValueCollection)))
- {
- NameValueCollection nameValue = (NameValueCollection)o;
- nameValue.Cast()
- .Select(key => new KeyValuePair(key, nameValue[key]))
- .ToList()
- .ForEach(i => dict.Add(i));
- }
- else
- {
- DynamicTypeMap mapper = DynamicMapperCache.GetMapper(ot);
-
- if (mapper != null)
- {
- foreach (DynamicPropertyInvoker item in mapper.ColumnsMap.Values)
- if (item.Get != null)
- dict.Add(item.Name, item.Get(o));
- }
- else
- {
- PropertyInfo[] props = ot.GetProperties();
-
- foreach (PropertyInfo item in props)
- if (item.CanRead)
- dict.Add(item.Name, item.GetValue(o, null));
- }
- }
-
- return result;
- }
-
- /// Convert data row row into dynamic object.
- /// DataRow from which read.
- /// Generated dynamic object.
- public static dynamic RowToDynamic(this DataRow r)
- {
- dynamic e = new DynamicExpando();
-
- int len = r.Table.Columns.Count;
-
- for (int i = 0; i < len; i++)
- ((IDictionary)e).Add(r.Table.Columns[i].ColumnName, r.IsNull(i) ? null : r[i]);
-
- return e;
- }
-
- /// Convert data row row into dynamic object.
- /// DataRow from which read.
- /// Generated dynamic object.
- public static dynamic RowToExpando(this DataRow r)
- {
- dynamic e = new ExpandoObject();
-
- int len = r.Table.Columns.Count;
-
- for (int i = 0; i < len; i++)
- ((IDictionary)e).Add(r.Table.Columns[i].ColumnName, r.IsNull(i) ? null : r[i]);
-
- return e;
- }
-
- /// Convert data row row into dynamic object (upper case key).
- /// DataRow from which read.
- /// Generated dynamic object.
- public static dynamic RowToDynamicUpper(this DataRow r)
- {
- dynamic e = new DynamicExpando();
-
- int len = r.Table.Columns.Count;
-
- for (int i = 0; i < len; i++)
- ((IDictionary)e).Add(r.Table.Columns[i].ColumnName.ToUpper(),
- r.IsNull(i) ? null : r[i]);
-
- return e;
- }
-
- /// Convert data row row into dynamic object (upper case key).
- /// DataRow from which read.
- /// Generated dynamic object.
- public static dynamic RowToExpandoUpper(this DataRow r)
- {
- // ERROR: Memory leak
- dynamic e = new ExpandoObject();
-
- int len = r.Table.Columns.Count;
-
- for (int i = 0; i < len; i++)
- ((IDictionary)e).Add(r.Table.Columns[i].ColumnName.ToUpper(),
- r.IsNull(i) ? null : r[i]);
-
- return e;
- }
-
- internal static Dictionary RowToDynamicUpperDict(this DataRow r)
- {
- dynamic e = new Dictionary();
-
- int len = r.Table.Columns.Count;
-
- for (int i = 0; i < len; i++)
- e.Add(r.Table.Columns[i].ColumnName.ToUpper(), r.IsNull(i) ? null : r[i]);
-
- return e;
- }
-
- /// Convert reader row into dynamic object.
- /// Reader from which read.
- /// Generated dynamic object.
- public static dynamic RowToDynamic(this IDataReader r)
- {
- dynamic e = new DynamicExpando();
- IDictionary d = e as IDictionary;
-
- int c = r.FieldCount;
- for (int i = 0; i < c; i++)
- try
- {
- d.Add(r.GetName(i), r.IsDBNull(i) ? null : r[i]);
- }
- catch (ArgumentException argex)
- {
- throw new ArgumentException(
- string.Format("Field '{0}' is defined more than once in a query.", r.GetName(i)),
- "Column name or alias", argex);
- }
-
- return e;
- }
-
- /// Convert reader row into dynamic object.
- /// Reader from which read.
- /// Generated dynamic object.
- public static dynamic RowToExpando(this IDataReader r)
- {
- dynamic e = new ExpandoObject();
- IDictionary d = e as IDictionary;
-
- int c = r.FieldCount;
- for (int i = 0; i < c; i++)
- try
- {
- d.Add(r.GetName(i), r.IsDBNull(i) ? null : r[i]);
- }
- catch (ArgumentException argex)
- {
- throw new ArgumentException(
- string.Format("Field '{0}' is defined more than once in a query.", r.GetName(i)),
- "Column name or alias", argex);
- }
-
- return e;
- }
-
- /// Turns the object into a Dictionary.
- /// Object to convert.
- /// Resulting dictionary.
- public static IDictionary ToDictionary(this ExpandoObject o)
- {
- return (IDictionary)o;
- }
-
- /// Turns the object into a Dictionary.
- /// Object to convert.
- /// Resulting dictionary.
- public static IDictionary ToDictionary(this DynamicExpando o)
- {
- return (IDictionary