diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs
index 6e7bc22..9d47c3d 100644
--- a/AmalgamationTool/DynamORM.Amalgamation.cs
+++ b/AmalgamationTool/DynamORM.Amalgamation.cs
@@ -2000,46 +2000,28 @@ namespace DynamORM
return new DynamicSelectQueryBuilder(this).From(fn);
}
- /// Adds to the FROM clause using .
- /// Type which can be represented in database.
- /// This instance to permit chaining.
- public virtual IDynamicSelectQueryBuilder From()
- {
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)));
- }
-
- /// Adds to the FROM clause using .
- /// Type which can be represented in database.
- /// Table alias.
- /// This instance to permit chaining.
- public virtual IDynamicSelectQueryBuilder From(string alias)
- {
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).As(alias));
- }
-
- /// Adds to the FROM clause using .
- /// Type which can be represented in database.
- /// use no lock.
- /// This instance to permit chaining.
- public virtual IDynamicSelectQueryBuilder From(bool noLock)
- {
- if (noLock)
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).NoLock());
- else
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)));
- }
-
/// 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, bool noLock)
+ public virtual IDynamicSelectQueryBuilder From(string alias = null, bool noLock = false)
{
+ // TODO: Make it more readable and maitainable
if (noLock)
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).As(alias).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
- return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).As(alias));
+ {
+ 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 .
@@ -4523,7 +4505,7 @@ namespace DynamORM
});
if (method != null)
- ret = o.ToString().TryParseDefault(defaultValue, delegate (string v, out T r)
+ ret = o.ToString().TryParseDefault(defaultValue, delegate(string v, out T r)
{
r = defaultValue;
return (bool)method.Invoke(null, new object[] { v, r });
@@ -4582,7 +4564,7 @@ namespace DynamORM
else if (typeof(T) == typeof(object))
ret = (T)o;
else if (method != null)
- ret = o.ToString().TryParseDefault(defaultValue, delegate (string v, out T r)
+ ret = o.ToString().TryParseDefault(defaultValue, delegate(string v, out T r)
{
r = defaultValue;
return (bool)method.Invoke(null, new object[] { v, r });
@@ -4643,7 +4625,7 @@ namespace DynamORM
param.Scale,
param.Precision,
param.Scale,
- param.Value is byte[]? ConvertByteArrayToHexString((byte[])param.Value) : param.Value ?? "NULL",
+ param.Value is byte[] ? ConvertByteArrayToHexString((byte[])param.Value) : param.Value ?? "NULL",
param.Value != null ? param.Value.GetType().Name : "DBNull");
}
@@ -4822,7 +4804,7 @@ namespace DynamORM
public static List ToList(this IDataReader r)
{
List result = new List();
-
+
while (r.Read())
result.Add(r.RowToDynamic());
@@ -7150,7 +7132,7 @@ namespace DynamORM
}
namespace Builders
- {
+ {
/// Dynamic delete query builder interface.
/// This interface it publicly available. Implementation should be hidden.
public interface IDynamicDeleteQueryBuilder : IDynamicQueryBuilder
@@ -7158,7 +7140,7 @@ namespace DynamORM
/// Execute this builder.
/// Result of an execution..
int Execute();
-
+
///
/// Adds to the 'Where' clause the contents obtained from parsing the dynamic lambda expression given. The condition
/// is parsed to the appropriate syntax, where the specific customs virtual methods supported by the parser are used
@@ -7170,25 +7152,25 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicDeleteQueryBuilder Where(Func func);
-
+
/// Add where condition.
/// Condition column with operator and value.
/// Builder instance.
IDynamicDeleteQueryBuilder Where(DynamicColumn column);
-
+
/// Add where condition.
/// Condition column.
/// Condition operator.
/// Condition value.
/// Builder instance.
IDynamicDeleteQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value);
-
+
/// Add where condition.
/// Condition column.
/// Condition value.
/// Builder instance.
IDynamicDeleteQueryBuilder Where(string column, object value);
-
+
/// Add where condition.
/// Set conditions as properties and values of an object.
/// If true use schema to determine key columns and ignore those which
@@ -7196,7 +7178,7 @@ namespace DynamORM
/// Builder instance.
IDynamicDeleteQueryBuilder Where(object conditions, bool schema = false);
}
-
+
/// Dynamic insert query builder interface.
/// This interface it publicly available. Implementation should be hidden.
public interface IDynamicInsertQueryBuilder : IDynamicQueryBuilder
@@ -7204,7 +7186,7 @@ namespace DynamORM
/// Execute this builder.
/// Result of an execution..
int Execute();
-
+
///
/// Specifies the columns to insert using the dynamic lambda expressions given. Each expression correspond to one
/// column, and can:
@@ -7215,59 +7197,59 @@ namespace DynamORM
/// The specifications.
/// This instance to permit chaining.
IDynamicInsertQueryBuilder Values(Func fn, params Func[] func);
-
+
/// Add insert fields.
/// Insert column.
/// Insert value.
/// Builder instance.
IDynamicInsertQueryBuilder Insert(string column, object value);
-
+
/// Add insert fields.
/// Set insert value as properties and values of an object.
/// Builder instance.
IDynamicInsertQueryBuilder Insert(object o);
}
-
+
/// Dynamic query builder base interface.
/// This interface it publicly available. Implementation should be hidden.
public interface IDynamicQueryBuilder : IExtendedDisposable
{
/// Gets instance.
DynamicDatabase Database { get; }
-
+
/// Gets tables information.
IList Tables { get; }
-
+
/// Gets the tables used in this builder.
IDictionary Parameters { get; }
-
+
/// Gets or sets a value indicating whether add virtual parameters.
bool VirtualMode { get; set; }
-
+
/// Gets a value indicating whether database supports standard schema.
bool SupportSchema { get; }
-
+
/// Fill command with query.
/// Command to fill.
/// Filled instance of .
IDbCommand FillCommand(IDbCommand command);
-
+
///
/// Generates the text this command will execute against the underlying database.
///
/// The text to execute against the underlying database.
/// This method must be override by derived classes.
string CommandText();
-
+
/// Gets or sets the on create temporary parameter actions.
/// This is exposed to allow setting schema of column.
List> OnCreateTemporaryParameter { get; set; }
-
+
/// Gets or sets the on create real parameter actions.
/// This is exposed to allow modification of parameter.
List> OnCreateParameter { get; set; }
}
-
+
/// Dynamic select query builder interface.
/// This interface it publicly available. Implementation should be hidden.
public interface IDynamicSelectQueryBuilder : IDynamicQueryBuilder ////, IEnumerable
@@ -7275,32 +7257,32 @@ namespace DynamORM
/// Execute this builder.
/// Enumerator of objects expanded from query.
IEnumerable Execute();
-
+
/// Execute this builder and map to given type.
/// Type of object to map on.
/// Enumerator of objects expanded from query.
IEnumerable Execute() where T : class;
-
+
/// Execute this builder as a data reader.
/// Action containing reader.
void ExecuteDataReader(Action reader);
-
+
/// Returns a single result.
/// Result of a query.
object Scalar();
-
-#if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE
-
+
+ #if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE
+
/// Returns a single result.
/// Type to parse to.
/// Default value.
/// Result of a query.
T ScalarAs(T defaultValue = default(T));
-
-#endif
-
+
+ #endif
+
#region From/Join
-
+
///
/// Adds to the 'From' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
/// formats are:
@@ -7313,7 +7295,7 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicSelectQueryBuilder From(Func fn, params Func[] func);
-
+
///
/// Adds to the 'Join' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
/// formats are:
@@ -7331,11 +7313,11 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicSelectQueryBuilder Join(params Func[] func);
-
+
#endregion From/Join
-
+
#region Where
-
+
///
/// Adds to the 'Where' clause the contents obtained from parsing the dynamic lambda expression given. The condition
/// is parsed to the appropriate syntax, where the specific customs virtual methods supported by the parser are used
@@ -7347,36 +7329,36 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicSelectQueryBuilder Where(Func func);
-
+
/// Add where condition.
/// Condition column with operator and value.
/// Builder instance.
IDynamicSelectQueryBuilder Where(DynamicColumn column);
-
+
/// Add where condition.
/// Condition column.
/// Condition operator.
/// Condition value.
/// Builder instance.
IDynamicSelectQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value);
-
+
/// Add where condition.
/// Condition column.
/// Condition value.
/// Builder instance.
IDynamicSelectQueryBuilder Where(string column, object value);
-
+
/// Add where condition.
/// Set conditions as properties and values of an object.
/// If true use schema to determine key columns and ignore those which
/// aren't keys.
/// Builder instance.
IDynamicSelectQueryBuilder Where(object conditions, bool schema = false);
-
+
#endregion Where
-
+
#region Select
-
+
///
/// Adds to the 'Select' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
/// formats are:
@@ -7390,23 +7372,23 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicSelectQueryBuilder Select(Func fn, params Func[] func);
-
+
/// Add select columns.
/// Columns to add to object.
/// Builder instance.
IDynamicSelectQueryBuilder SelectColumn(params DynamicColumn[] columns);
-
+
/// Add select columns.
/// Columns to add to object.
/// Column format consist of Column Name , Alias and
/// Aggregate function in this order separated by ': '.
/// Builder instance.
IDynamicSelectQueryBuilder SelectColumn(params string[] columns);
-
+
#endregion Select
-
+
#region GroupBy
-
+
///
/// Adds to the 'Group By' clause the contents obtained from from parsing the dynamic lambda expression given.
///
@@ -7414,23 +7396,23 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicSelectQueryBuilder GroupBy(Func fn, params Func[] func);
-
+
/// Add select columns.
/// Columns to group by.
/// Builder instance.
IDynamicSelectQueryBuilder GroupByColumn(params DynamicColumn[] columns);
-
+
/// Add select columns.
/// Columns to group by.
/// Column format consist of Column Name and
/// Alias in this order separated by ': '.
/// Builder instance.
IDynamicSelectQueryBuilder GroupByColumn(params string[] columns);
-
+
#endregion GroupBy
-
+
#region Having
-
+
///
/// Adds to the 'Having' clause the contents obtained from parsing the dynamic lambda expression given. The condition
/// is parsed to the appropriate syntax, Having the specific customs virtual methods supported by the parser are used
@@ -7442,36 +7424,36 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicSelectQueryBuilder Having(Func func);
-
+
/// Add Having condition.
/// Condition column with operator and value.
/// Builder instance.
IDynamicSelectQueryBuilder Having(DynamicColumn column);
-
+
/// Add Having condition.
/// Condition column.
/// Condition operator.
/// Condition value.
/// Builder instance.
IDynamicSelectQueryBuilder Having(string column, DynamicColumn.CompareOperator op, object value);
-
+
/// Add Having condition.
/// Condition column.
/// Condition value.
/// Builder instance.
IDynamicSelectQueryBuilder Having(string column, object value);
-
+
/// Add Having condition.
/// Set conditions as properties and values of an object.
/// If true use schema to determine key columns and ignore those which
/// aren't keys.
/// Builder instance.
IDynamicSelectQueryBuilder Having(object conditions, bool schema = false);
-
+
#endregion Having
-
+
#region OrderBy
-
+
///
/// Adds to the 'Order By' clause the contents obtained from from parsing the dynamic lambda expression given. It
/// accepts a multipart column specification followed by an optional Ascending() or Descending() virtual methods
@@ -7482,46 +7464,46 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicSelectQueryBuilder OrderBy(Func fn, params Func[] func);
-
+
/// Add select columns.
/// Columns to order by.
/// Builder instance.
IDynamicSelectQueryBuilder OrderByColumn(params DynamicColumn[] columns);
-
+
/// Add select columns.
/// Columns to order by.
/// Column format consist of Column Name and
/// Alias in this order separated by ': '.
/// Builder instance.
IDynamicSelectQueryBuilder OrderByColumn(params string[] columns);
-
+
#endregion OrderBy
-
+
#region Top/Limit/Offset/Distinct
-
+
/// Set top if database support it.
/// How many objects select.
/// Builder instance.
IDynamicSelectQueryBuilder Top(int? top);
-
+
/// Set top if database support it.
/// How many objects select.
/// Builder instance.
IDynamicSelectQueryBuilder Limit(int? limit);
-
+
/// Set top if database support it.
/// How many objects skip selecting.
/// Builder instance.
IDynamicSelectQueryBuilder Offset(int? offset);
-
+
/// Set distinct mode.
/// Distinct mode.
/// Builder instance.
IDynamicSelectQueryBuilder Distinct(bool distinct = true);
-
+
#endregion Top/Limit/Offset/Distinct
}
-
+
/// Dynamic update query builder interface.
/// This interface it publicly available. Implementation should be hidden.
public interface IDynamicUpdateQueryBuilder : IDynamicQueryBuilder
@@ -7529,24 +7511,24 @@ namespace DynamORM
/// Execute this builder.
/// Result of an execution..
int Execute();
-
+
#region Update
-
+
/// Add update value or where condition using schema.
/// Update or where column name.
/// Column value.
/// Builder instance.
IDynamicUpdateQueryBuilder Update(string column, object value);
-
+
/// Add update values and where condition columns using schema.
/// Set values or conditions as properties and values of an object.
/// Builder instance.
IDynamicUpdateQueryBuilder Update(object conditions);
-
+
#endregion Update
-
+
#region Values
-
+
///
/// Specifies the columns to update using the dynamic lambda expressions given. Each expression correspond to one
/// column, and can:
@@ -7556,22 +7538,22 @@ namespace DynamORM
/// The specifications.
/// This instance to permit chaining.
IDynamicUpdateQueryBuilder Set(params Func[] func);
-
+
/// Add insert fields.
/// Insert column.
/// Insert value.
/// Builder instance.
IDynamicUpdateQueryBuilder Values(string column, object value);
-
+
/// Add insert fields.
/// Set insert value as properties and values of an object.
/// Builder instance.
IDynamicUpdateQueryBuilder Values(object o);
-
+
#endregion Values
-
+
#region Where
-
+
///
/// Adds to the 'Where' clause the contents obtained from parsing the dynamic lambda expression given. The condition
/// is parsed to the appropriate syntax, where the specific customs virtual methods supported by the parser are used
@@ -7583,102 +7565,102 @@ namespace DynamORM
/// The specification.
/// This instance to permit chaining.
IDynamicUpdateQueryBuilder Where(Func func);
-
+
/// Add where condition.
/// Condition column with operator and value.
/// Builder instance.
IDynamicUpdateQueryBuilder Where(DynamicColumn column);
-
+
/// Add where condition.
/// Condition column.
/// Condition operator.
/// Condition value.
/// Builder instance.
IDynamicUpdateQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value);
-
+
/// Add where condition.
/// Condition column.
/// Condition value.
/// Builder instance.
IDynamicUpdateQueryBuilder Where(string column, object value);
-
+
/// Add where condition.
/// Set conditions as properties and values of an object.
/// If true use schema to determine key columns and ignore those which
/// aren't keys.
/// Builder instance.
IDynamicUpdateQueryBuilder Where(object conditions, bool schema = false);
-
+
#endregion Where
}
-
+
/// Interface describing parameter info.
public interface IParameter : IExtendedDisposable
{
/// Gets the parameter position in command.
/// Available after filling the command.
int Ordinal { get; }
-
+
/// Gets the parameter temporary name.
string Name { get; }
-
+
/// Gets or sets the parameter value.
object Value { get; set; }
-
+
/// Gets or sets a value indicating whether name of temporary parameter is well known.
bool WellKnown { get; set; }
-
+
/// Gets or sets a value indicating whether this is virtual.
bool Virtual { get; set; }
-
+
/// Gets or sets the parameter schema information.
DynamicSchemaColumn? Schema { get; set; }
}
-
+
/// Interface describing table information.
public interface ITableInfo : IExtendedDisposable
{
/// Gets table owner name.
string Owner { get; }
-
+
/// Gets table name.
string Name { get; }
-
+
/// Gets table alias.
string Alias { get; }
-
+
/// Gets table no lock status.
bool NoLock { get; }
-
+
/// Gets table schema.
Dictionary Schema { get; }
}
namespace Extensions
- {
+ {
internal static class DynamicHavingQueryExtensions
{
#region Where
-
+
internal static T InternalHaving(this T builder, Func func) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithHaving
{
return builder.InternalHaving(false, false, func);
}
-
+
internal static T InternalHaving(this T builder, bool addBeginBrace, bool addEndBrace, Func func) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithHaving
{
if (func == null) throw new ArgumentNullException("Array of functions cannot be null.");
-
+
using (DynamicParser parser = DynamicParser.Parse(func))
{
string condition = null;
bool and = true;
-
+
object result = parser.Result;
if (result is string)
{
condition = (string)result;
-
+
if (condition.ToUpper().IndexOf("OR") == 0)
{
and = false;
@@ -7701,19 +7683,19 @@ namespace DynamORM
object[] args = ((DynamicParser.Node.Method)node).Arguments;
if (args == null) throw new ArgumentNullException("arg", string.Format("{0} is not a parameterless method.", name));
if (args.Length != 1) throw new ArgumentException(string.Format("{0} requires one and only one parameter: {1}.", name, args.Sketch()));
-
+
and = name == "AND" ? true : false;
result = args[0];
}
}
-
+
// Just parsing the contents now...
condition = builder.Parse(result, pars: builder.Parameters).Validated("Where condition");
}
-
+
if (addBeginBrace) builder.HavingOpenBracketsCount++;
if (addEndBrace) builder.HavingOpenBracketsCount--;
-
+
if (builder.HavingCondition == null)
builder.HavingCondition = string.Format("{0}{1}{2}",
addBeginBrace ? "(" : string.Empty, condition, addEndBrace ? ")" : string.Empty);
@@ -7721,27 +7703,27 @@ namespace DynamORM
builder.HavingCondition = string.Format("{0} {1} {2}{3}{4}", builder.HavingCondition, and ? "AND" : "OR",
addBeginBrace ? "(" : string.Empty, condition, addEndBrace ? ")" : string.Empty);
}
-
+
return builder;
}
-
+
internal static T InternalHaving(this T builder, DynamicColumn column) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithHaving
{
bool virt = builder.VirtualMode;
if (column.VirtualColumn.HasValue)
builder.VirtualMode = column.VirtualColumn.Value;
-
+
Action modParam = (p) =>
{
if (column.Schema.HasValue)
p.Schema = column.Schema;
-
+
if (!p.Schema.HasValue)
p.Schema = column.Schema ?? builder.GetColumnFromSchema(column.ColumnName);
};
-
+
builder.CreateTemporaryParameterAction(modParam);
-
+
// It's kind of uglu, but... well it works.
if (column.Or)
switch (column.Operator)
@@ -7773,32 +7755,32 @@ namespace DynamORM
case DynamicColumn.CompareOperator.Gte: builder.InternalHaving(column.BeginBlock, column.EndBlock, x => x(builder.FixObjectName(column.ColumnName)) >= column.Value); break;
case DynamicColumn.CompareOperator.Between: builder.InternalHaving(column.BeginBlock, column.EndBlock, x => x(builder.FixObjectName(column.ColumnName)).Between(column.Value)); break;
}
-
+
builder.OnCreateTemporaryParameter.Remove(modParam);
builder.VirtualMode = virt;
-
+
return builder;
}
-
+
internal static T InternalHaving(this T builder, string column, DynamicColumn.CompareOperator op, object value) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithHaving
{
if (value is DynamicColumn)
{
DynamicColumn v = (DynamicColumn)value;
-
+
if (string.IsNullOrEmpty(v.ColumnName))
v.ColumnName = column;
-
+
return builder.InternalHaving(v);
}
else if (value is IEnumerable)
{
foreach (DynamicColumn v in (IEnumerable)value)
builder.InternalHaving(v);
-
+
return builder;
}
-
+
return builder.InternalHaving(new DynamicColumn
{
ColumnName = column,
@@ -7806,12 +7788,12 @@ namespace DynamORM
Value = value
});
}
-
+
internal static T InternalHaving(this T builder, string column, object value) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithHaving
{
return builder.InternalHaving(column, DynamicColumn.CompareOperator.Eq, value);
}
-
+
internal static T InternalHaving(this T builder, object conditions, bool schema = false) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithHaving
{
if (conditions is DynamicColumn)
@@ -7820,58 +7802,58 @@ namespace DynamORM
{
foreach (DynamicColumn v in (IEnumerable)conditions)
builder.InternalHaving(v);
-
+
return builder;
}
-
+
IDictionary dict = conditions.ToDictionary();
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(conditions.GetType());
string table = dict.TryGetValue("_table").NullOr(x => x.ToString(), string.Empty);
-
+
foreach (KeyValuePair condition in dict)
{
if (mapper.Ignored.Contains(condition.Key) || condition.Key == "_table")
continue;
-
+
string colName = mapper != null ? mapper.PropertyMap.TryGetValue(condition.Key) ?? condition.Key : condition.Key;
-
+
DynamicSchemaColumn? col = null;
-
+
// This should be used on typed queries or update/delete steatements, which usualy operate on a single table.
if (schema)
{
col = builder.GetColumnFromSchema(colName, mapper, table);
-
+
if ((!col.HasValue || !col.Value.IsKey) &&
(mapper == null || mapper.ColumnsMap.TryGetValue(colName).NullOr(m => m.Ignore || m.Column.NullOr(c => !c.IsKey, true), true)))
continue;
-
+
colName = col.HasValue ? col.Value.Name : colName;
}
-
+
if (!string.IsNullOrEmpty(table))
builder.InternalHaving(x => x(builder.FixObjectName(string.Format("{0}.{1}", table, colName))) == condition.Value);
else
builder.InternalHaving(x => x(builder.FixObjectName(colName)) == condition.Value);
}
-
+
return builder;
}
-
+
#endregion Where
}
-
+
internal static class DynamicModifyBuilderExtensions
{
internal static T Table(this T builder, Func func) where T : DynamicModifyBuilder
{
if (func == null)
throw new ArgumentNullException("Function cannot be null.");
-
+
using (DynamicParser parser = DynamicParser.Parse(func))
{
object result = parser.Result;
-
+
// If the expression result is string.
if (result is string)
return builder.Table((string)result);
@@ -7881,38 +7863,38 @@ namespace DynamORM
{
// Or if it resolves to a dynamic node
DynamicParser.Node node = (DynamicParser.Node)result;
-
+
string owner = null;
string main = null;
-
+
while (true)
{
// Deny support for the AS() virtual method...
if (node is DynamicParser.Node.Method && ((DynamicParser.Node.Method)node).Name.ToUpper() == "AS")
throw new ArgumentException(string.Format("Alias is not supported on modification builders. (Parsing: {0})", result));
-
+
// Support for table specifications...
if (node is DynamicParser.Node.GetMember)
{
if (owner != null)
throw new ArgumentException(string.Format("Owner '{0}.{1}' is already set when parsing '{2}'.", owner, main, result));
-
+
if (main != null)
owner = ((DynamicParser.Node.GetMember)node).Name;
else
main = ((DynamicParser.Node.GetMember)node).Name;
-
+
node = node.Host;
continue;
}
-
+
// Support for generic sources...
if (node is DynamicParser.Node.Invoke)
{
if (owner == null && main == null)
{
DynamicParser.Node.Invoke invoke = (DynamicParser.Node.Invoke)node;
-
+
if (invoke.Arguments.Length == 1 && invoke.Arguments[0] is Type)
return builder.Table((Type)invoke.Arguments[0]);
else if (invoke.Arguments.Length == 1 && invoke.Arguments[0] is String)
@@ -7925,51 +7907,51 @@ namespace DynamORM
else if (main != null)
throw new ArgumentException(string.Format("Main '{0}' is already set when parsing '{1}'.", main, result));
}
-
+
if (!string.IsNullOrEmpty(main))
return builder.Table(string.Format("{0}{1}",
string.IsNullOrEmpty(owner) ? string.Empty : string.Format("{0}.", owner),
main));
}
}
-
+
throw new ArgumentException(string.Format("Unable to set table parsing '{0}'", result));
}
}
-
+
internal static T Table(this T builder, string tableName, Dictionary schema = null) where T : DynamicModifyBuilder
{
Tuple tuple = tableName.Validated("Table Name").SplitSomethingAndAlias();
-
+
if (!string.IsNullOrEmpty(tuple.Item2))
throw new ArgumentException(string.Format("Can not use aliases in INSERT steatement. ({0})", tableName), "tableName");
-
+
string[] parts = tuple.Item1.Split('.');
-
+
if (parts.Length > 2)
throw new ArgumentException(string.Format("Table name can consist only from name or owner and name. ({0})", tableName), "tableName");
-
+
builder.Tables.Clear();
builder.Tables.Add(new DynamicQueryBuilder.TableInfo(builder.Database,
builder.Database.StripName(parts.Last()).Validated("Table"), null,
parts.Length == 2 ? builder.Database.StripName(parts.First()).Validated("Owner", canbeNull: true) : null));
-
+
if (schema != null)
(builder.Tables[0] as DynamicQueryBuilder.TableInfo).Schema = schema;
-
+
return builder;
}
-
+
internal static T Table(this T builder, Type type) where T : DynamicQueryBuilder
{
if (type.IsAnonymous())
throw new InvalidOperationException(string.Format("Cant assign anonymous type as a table ({0}).", type.FullName));
-
+
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(type);
-
+
if (mapper == null)
throw new InvalidOperationException("Cant assign unmapable type as a table.");
-
+
if (builder is DynamicModifyBuilder)
{
builder.Tables.Clear();
@@ -7977,34 +7959,34 @@ namespace DynamORM
}
else if (builder is DynamicSelectQueryBuilder)
(builder as DynamicSelectQueryBuilder).From(x => x(type));
-
+
return builder;
}
}
-
+
internal static class DynamicWhereQueryExtensions
{
#region Where
-
+
internal static T InternalWhere(this T builder, Func func) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithWhere
{
return builder.InternalWhere(false, false, func);
}
-
+
internal static T InternalWhere(this T builder, bool addBeginBrace, bool addEndBrace, Func func) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithWhere
{
if (func == null) throw new ArgumentNullException("Array of functions cannot be null.");
-
+
using (DynamicParser parser = DynamicParser.Parse(func))
{
string condition = null;
bool and = true;
-
+
object result = parser.Result;
if (result is string)
{
condition = (string)result;
-
+
if (condition.ToUpper().IndexOf("OR") == 0)
{
and = false;
@@ -8027,19 +8009,19 @@ namespace DynamORM
object[] args = ((DynamicParser.Node.Method)node).Arguments;
if (args == null) throw new ArgumentNullException("arg", string.Format("{0} is not a parameterless method.", name));
if (args.Length != 1) throw new ArgumentException(string.Format("{0} requires one and only one parameter: {1}.", name, args.Sketch()));
-
+
and = name == "AND" ? true : false;
result = args[0];
}
}
-
+
// Just parsing the contents now...
condition = builder.Parse(result, pars: builder.Parameters).Validated("Where condition");
}
-
+
if (addBeginBrace) builder.WhereOpenBracketsCount++;
if (addEndBrace) builder.WhereOpenBracketsCount--;
-
+
if (builder.WhereCondition == null)
builder.WhereCondition = string.Format("{0}{1}{2}",
addBeginBrace ? "(" : string.Empty, condition, addEndBrace ? ")" : string.Empty);
@@ -8047,27 +8029,27 @@ namespace DynamORM
builder.WhereCondition = string.Format("{0} {1} {2}{3}{4}", builder.WhereCondition, and ? "AND" : "OR",
addBeginBrace ? "(" : string.Empty, condition, addEndBrace ? ")" : string.Empty);
}
-
+
return builder;
}
-
+
internal static T InternalWhere(this T builder, DynamicColumn column) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithWhere
{
bool virt = builder.VirtualMode;
if (column.VirtualColumn.HasValue)
builder.VirtualMode = column.VirtualColumn.Value;
-
+
Action modParam = (p) =>
{
if (column.Schema.HasValue)
p.Schema = column.Schema;
-
+
if (!p.Schema.HasValue)
p.Schema = column.Schema ?? builder.GetColumnFromSchema(column.ColumnName);
};
-
+
builder.CreateTemporaryParameterAction(modParam);
-
+
// It's kind of uglu, but... well it works.
if (column.Or)
switch (column.Operator)
@@ -8099,32 +8081,32 @@ namespace DynamORM
case DynamicColumn.CompareOperator.Gte: builder.InternalWhere(column.BeginBlock, column.EndBlock, x => x(builder.FixObjectName(column.ColumnName)) >= column.Value); break;
case DynamicColumn.CompareOperator.Between: builder.InternalWhere(column.BeginBlock, column.EndBlock, x => x(builder.FixObjectName(column.ColumnName)).Between(column.Value)); break;
}
-
+
builder.OnCreateTemporaryParameter.Remove(modParam);
builder.VirtualMode = virt;
-
+
return builder;
}
-
+
internal static T InternalWhere(this T builder, string column, DynamicColumn.CompareOperator op, object value) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithWhere
{
if (value is DynamicColumn)
{
DynamicColumn v = (DynamicColumn)value;
-
+
if (string.IsNullOrEmpty(v.ColumnName))
v.ColumnName = column;
-
+
return builder.InternalWhere(v);
}
else if (value is IEnumerable)
{
foreach (DynamicColumn v in (IEnumerable)value)
builder.InternalWhere(v);
-
+
return builder;
}
-
+
return builder.InternalWhere(new DynamicColumn
{
ColumnName = column,
@@ -8132,12 +8114,12 @@ namespace DynamORM
Value = value
});
}
-
+
internal static T InternalWhere(this T builder, string column, object value) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithWhere
{
return builder.InternalWhere(column, DynamicColumn.CompareOperator.Eq, value);
}
-
+
internal static T InternalWhere(this T builder, object conditions, bool schema = false) where T : DynamicQueryBuilder, DynamicQueryBuilder.IQueryWithWhere
{
if (conditions is DynamicColumn)
@@ -8146,50 +8128,50 @@ namespace DynamORM
{
foreach (DynamicColumn v in (IEnumerable)conditions)
builder.InternalWhere(v);
-
+
return builder;
}
-
+
IDictionary dict = conditions.ToDictionary();
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(conditions.GetType());
string table = dict.TryGetValue("_table").NullOr(x => x.ToString(), string.Empty);
-
+
foreach (KeyValuePair condition in dict)
{
if (mapper.Ignored.Contains(condition.Key) || condition.Key == "_table")
continue;
-
+
string colName = mapper != null ? mapper.PropertyMap.TryGetValue(condition.Key) ?? condition.Key : condition.Key;
-
+
DynamicSchemaColumn? col = null;
-
+
// This should be used on typed queries or update/delete steatements, which usualy operate on a single table.
if (schema)
{
col = builder.GetColumnFromSchema(colName, mapper, table);
-
+
if ((!col.HasValue || !col.Value.IsKey) &&
(mapper == null || mapper.ColumnsMap.TryGetValue(colName).NullOr(m => m.Ignore || m.Column.NullOr(c => !c.IsKey, true), true)))
continue;
-
+
colName = col.HasValue ? col.Value.Name : colName;
}
-
+
if (!string.IsNullOrEmpty(table))
builder.InternalWhere(x => x(builder.FixObjectName(string.Format("{0}.{1}", table, colName))) == condition.Value);
else
builder.InternalWhere(x => x(builder.FixObjectName(colName)) == condition.Value);
}
-
+
return builder;
}
-
+
#endregion Where
}
}
namespace Implementation
- {
+ {
/// Implementation of dynamic delete query builder.
internal class DynamicDeleteQueryBuilder : DynamicModifyBuilder, IDynamicDeleteQueryBuilder, DynamicQueryBuilder.IQueryWithWhere
{
@@ -8201,7 +8183,7 @@ namespace DynamORM
: base(db)
{
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -8211,7 +8193,7 @@ namespace DynamORM
: base(db, tableName)
{
}
-
+
/// Generates the text this command will execute against the underlying database.
/// The text to execute against the underlying database.
/// This method must be override by derived classes.
@@ -8224,9 +8206,9 @@ namespace DynamORM
string.IsNullOrEmpty(WhereCondition) ? string.Empty : " WHERE ",
WhereCondition);
}
-
+
#region Where
-
+
///
/// Adds to the 'Where' clause the contents obtained from parsing the dynamic lambda expression given. The condition
/// is parsed to the appropriate syntax, where the specific customs virtual methods supported by the parser are used
@@ -8241,7 +8223,7 @@ namespace DynamORM
{
return this.InternalWhere(func);
}
-
+
/// Add where condition.
/// Condition column with operator and value.
/// Builder instance.
@@ -8249,7 +8231,7 @@ namespace DynamORM
{
return this.InternalWhere(column);
}
-
+
/// Add where condition.
/// Condition column.
/// Condition operator.
@@ -8259,7 +8241,7 @@ namespace DynamORM
{
return this.InternalWhere(column, op, value);
}
-
+
/// Add where condition.
/// Condition column.
/// Condition value.
@@ -8268,7 +8250,7 @@ namespace DynamORM
{
return this.InternalWhere(column, value);
}
-
+
/// Add where condition.
/// Set conditions as properties and values of an object.
/// If true use schema to determine key columns and ignore those which
@@ -8278,16 +8260,16 @@ namespace DynamORM
{
return this.InternalWhere(conditions, schema);
}
-
+
#endregion Where
}
-
+
/// Implementation of dynamic insert query builder.
internal class DynamicInsertQueryBuilder : DynamicModifyBuilder, IDynamicInsertQueryBuilder
{
private string _columns;
private string _values;
-
+
///
/// Initializes a new instance of the class.
///
@@ -8296,7 +8278,7 @@ namespace DynamORM
: base(db)
{
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -8306,7 +8288,7 @@ namespace DynamORM
: base(db, tableName)
{
}
-
+
/// Generates the text this command will execute against the underlying database.
/// The text to execute against the underlying database.
/// This method must be override by derived classes.
@@ -8317,9 +8299,9 @@ namespace DynamORM
string.IsNullOrEmpty(info.Owner) ? string.Empty : string.Format("{0}.", Database.DecorateName(info.Owner)),
Database.DecorateName(info.Name), _columns, _values);
}
-
+
#region Insert
-
+
///
/// Specifies the columns to insert using the dynamic lambda expressions given. Each expression correspond to one
/// column, and can:
@@ -8333,42 +8315,42 @@ namespace DynamORM
{
if (fn == null)
throw new ArgumentNullException("Array of specifications cannot be null.");
-
+
int index = InsertFunc(-1, fn);
-
+
if (func != null)
foreach (Func f in func)
index = InsertFunc(index, f);
-
+
return this;
}
-
+
private int InsertFunc(int index, Func f)
{
index++;
-
+
if (f == null)
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
-
+
using (DynamicParser parser = DynamicParser.Parse(f))
{
object result = parser.Result;
if (result == null)
throw new ArgumentException(string.Format("Specification #{0} resolves to null.", index));
-
+
string main = null;
string value = null;
string str = null;
-
+
// When 'x => x.Table.Column = value' or 'x => x.Column = value'...
if (result is DynamicParser.Node.SetMember)
{
DynamicParser.Node.SetMember node = (DynamicParser.Node.SetMember)result;
-
+
DynamicSchemaColumn? col = GetColumnFromSchema(node.Name);
main = Database.DecorateName(node.Name);
value = Parse(node.Value, ref col, pars: Parameters, nulls: true);
-
+
_columns = _columns == null ? main : string.Format("{0}, {1}", _columns, main);
_values = _values == null ? value : string.Format("{0}, {1}", _values, value);
return index;
@@ -8378,7 +8360,7 @@ namespace DynamORM
Insert(result);
return index;
}
-
+
// Other specifications are considered invalid...
string err = string.Format("Specification '{0}' is invalid.", result);
str = Parse(result);
@@ -8386,7 +8368,7 @@ namespace DynamORM
throw new ArgumentException(err);
}
}
-
+
/// Add insert fields.
/// Insert column.
/// Insert value.
@@ -8396,20 +8378,20 @@ namespace DynamORM
if (value is DynamicColumn)
{
DynamicColumn v = (DynamicColumn)value;
-
+
if (string.IsNullOrEmpty(v.ColumnName))
v.ColumnName = column;
-
+
return Insert(v);
}
-
+
return Insert(new DynamicColumn
{
ColumnName = column,
Value = value,
});
}
-
+
/// Add insert fields.
/// Set insert value as properties and values of an object.
/// Builder instance.
@@ -8419,19 +8401,19 @@ namespace DynamORM
{
DynamicColumn column = (DynamicColumn)o;
DynamicSchemaColumn? col = column.Schema ?? GetColumnFromSchema(column.ColumnName);
-
+
string main = FixObjectName(column.ColumnName, onlyColumn: true);
string value = Parse(column.Value, ref col, pars: Parameters, nulls: true);
-
+
_columns = _columns == null ? main : string.Format("{0}, {1}", _columns, main);
_values = _values == null ? value : string.Format("{0}, {1}", _values, value);
-
+
return this;
}
-
+
IDictionary dict = o.ToDictionary();
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(o.GetType());
-
+
if (mapper != null)
{
foreach (KeyValuePair con in dict)
@@ -8439,7 +8421,7 @@ namespace DynamORM
{
string colName = mapper.PropertyMap.TryGetValue(con.Key) ?? con.Key;
DynamicPropertyInvoker propMap = mapper.ColumnsMap.TryGetValue(colName.ToLower());
-
+
if (propMap == null || propMap.Column == null || !propMap.Column.IsNoInsert)
Insert(colName, con.Value);
}
@@ -8447,26 +8429,26 @@ namespace DynamORM
else
foreach (KeyValuePair con in dict)
Insert(con.Key, con.Value);
-
+
return this;
}
-
+
#endregion Insert
-
+
#region IExtendedDisposable
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
public override void Dispose()
{
base.Dispose();
-
+
_columns = _values = null;
}
-
+
#endregion IExtendedDisposable
}
-
+
/// Base query builder for insert/update/delete statements.
internal abstract class DynamicModifyBuilder : DynamicQueryBuilder
{
@@ -8479,7 +8461,7 @@ namespace DynamORM
{
VirtualMode = false;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -8491,7 +8473,7 @@ namespace DynamORM
VirtualMode = false;
this.Table(tableName);
}
-
+
/// Execute this builder.
/// Result of an execution..
public virtual int Execute()
@@ -8505,7 +8487,7 @@ namespace DynamORM
}
}
}
-
+
/// Implementation of dynamic query builder base interface.
internal abstract class DynamicQueryBuilder : IDynamicQueryBuilder
{
@@ -8514,25 +8496,25 @@ namespace DynamORM
{
/// Gets or sets the where condition.
string WhereCondition { get; set; }
-
+
/// Gets or sets the amount of not closed brackets in where statement.
int WhereOpenBracketsCount { get; set; }
}
-
+
/// Empty interface to allow having query builder implementation use universal approach.
internal interface IQueryWithHaving
{
/// Gets or sets the having condition.
string HavingCondition { get; set; }
-
+
/// Gets or sets the amount of not closed brackets in having statement.
int HavingOpenBracketsCount { get; set; }
}
-
+
private DynamicQueryBuilder _parent = null;
-
+
#region TableInfo
-
+
/// Table information.
internal class TableInfo : ITableInfo
{
@@ -8543,7 +8525,7 @@ namespace DynamORM
{
IsDisposed = false;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -8559,11 +8541,11 @@ namespace DynamORM
Alias = alias;
Owner = owner;
NoLock = nolock;
-
+
if (!name.ContainsAny(StringExtensions.InvalidMemberChars))
Schema = db.GetSchema(name, owner: owner);
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -8576,49 +8558,49 @@ namespace DynamORM
: this()
{
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(type);
-
+
Name = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Name) ?
mapper.Type.Name : mapper.Table.Name;
-
+
Owner = (mapper.Table != null) ? mapper.Table.Owner : owner;
Alias = alias;
NoLock = nolock;
-
+
Schema = db.GetSchema(type);
}
-
+
/// Gets or sets table owner name.
public string Owner { get; internal set; }
-
+
/// Gets or sets table name.
public string Name { get; internal set; }
-
+
/// Gets or sets table alias.
public string Alias { get; internal set; }
-
+
/// Gets or sets table alias.
public bool NoLock { get; internal set; }
-
+
/// Gets or sets table schema.
public Dictionary Schema { get; internal set; }
-
+
/// Gets a value indicating whether this instance is disposed.
public bool IsDisposed { get; private set; }
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
public virtual void Dispose()
{
IsDisposed = true;
-
+
////if (Schema != null)
//// Schema.Clear();
-
+
Owner = Name = Alias = null;
Schema = null;
}
}
-
+
/// Generic based table information.
/// Type of class that is represented in database.
internal class TableInfo : TableInfo
@@ -8634,11 +8616,11 @@ namespace DynamORM
{
}
}
-
+
#endregion TableInfo
-
+
#region Parameter
-
+
/// Interface describing parameter info.
internal class Parameter : IParameter
{
@@ -8648,44 +8630,44 @@ namespace DynamORM
{
IsDisposed = false;
}
-
+
/// Gets or sets the parameter position in command.
/// Available after filling the command.
public int Ordinal { get; internal set; }
-
+
/// Gets or sets the parameter temporary name.
public string Name { get; internal set; }
-
+
/// Gets or sets the parameter value.
public object Value { get; set; }
-
+
/// Gets or sets a value indicating whether name of temporary parameter is well known.
public bool WellKnown { get; set; }
-
+
/// Gets or sets a value indicating whether this is virtual.
public bool Virtual { get; set; }
-
+
/// Gets or sets the parameter schema information.
public DynamicSchemaColumn? Schema { get; set; }
-
+
/// Gets a value indicating whether this instance is disposed.
public bool IsDisposed { get; private set; }
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
public virtual void Dispose()
{
IsDisposed = true;
-
+
Name = null;
Schema = null;
}
}
-
+
#endregion Parameter
-
+
#region Constructor
-
+
///
/// Initializes a new instance of the class.
///
@@ -8698,18 +8680,18 @@ namespace DynamORM
Parameters = new Dictionary();
OnCreateTemporaryParameter = new List>();
OnCreateParameter = new List>();
-
+
WhereCondition = null;
WhereOpenBracketsCount = 0;
-
+
Database = db;
if (Database != null)
Database.AddToCache(this);
-
+
SupportSchema = (db.Options & DynamicDatabaseOptions.SupportSchema) == DynamicDatabaseOptions.SupportSchema;
SupportNoLock = (db.Options & DynamicDatabaseOptions.SupportNoLock) == DynamicDatabaseOptions.SupportNoLock;
}
-
+
/// Initializes a new instance of the class.
/// The database.
/// The parent query.
@@ -8718,54 +8700,54 @@ namespace DynamORM
{
_parent = parent;
}
-
+
#endregion Constructor
-
+
#region IQueryWithWhere
-
+
/// Gets or sets the where condition.
public string WhereCondition { get; set; }
-
+
/// Gets or sets the amount of not closed brackets in where statement.
public int WhereOpenBracketsCount { get; set; }
-
+
#endregion IQueryWithWhere
-
+
#region IDynamicQueryBuilder
-
+
/// Gets instance.
public DynamicDatabase Database { get; private set; }
-
+
/// Gets the tables used in this builder.
public IList Tables { get; private set; }
-
+
/// Gets the tables used in this builder.
public IDictionary Parameters { get; private set; }
-
+
/// Gets or sets a value indicating whether add virtual parameters.
public bool VirtualMode { get; set; }
-
+
/// Gets or sets the on create temporary parameter actions.
/// This is exposed to allow setting schema of column.
public List> OnCreateTemporaryParameter { get; set; }
-
+
/// Gets or sets the on create real parameter actions.
/// This is exposed to allow modification of parameter.
public List> OnCreateParameter { get; set; }
-
+
/// Gets a value indicating whether database supports standard schema.
public bool SupportSchema { get; private set; }
-
+
/// Gets a value indicating whether database supports with no lock syntax.
public bool SupportNoLock { get; private set; }
-
+
///
/// Generates the text this command will execute against the underlying database.
///
/// The text to execute against the underlying database.
/// This method must be override by derived classes.
public abstract string CommandText();
-
+
/// Fill command with query.
/// Command to fill.
/// Filled instance of .
@@ -8780,19 +8762,19 @@ namespace DynamORM
WhereOpenBracketsCount--;
}
}
-
+
// End not ended having statement
if (this is IQueryWithHaving)
{
IQueryWithHaving h = this as IQueryWithHaving;
-
+
while (h.HavingOpenBracketsCount > 0)
{
h.HavingCondition += ")";
h.HavingOpenBracketsCount--;
}
}
-
+
return command.SetCommand(CommandText()
.FillStringWithVariables(s =>
{
@@ -8801,21 +8783,21 @@ namespace DynamORM
IDbDataParameter param = (IDbDataParameter)command
.AddParameter(this, p.Schema, p.Value)
.Parameters[command.Parameters.Count - 1];
-
+
(p as Parameter).Ordinal = command.Parameters.Count - 1;
-
+
if (OnCreateParameter != null)
OnCreateParameter.ForEach(x => x(p, param));
-
+
return param.ParameterName;
}, s);
}));
}
-
+
#endregion IDynamicQueryBuilder
-
+
#region Parser
-
+
/// Parses the arbitrary object given and translates it into a string with the appropriate
/// syntax for the database this parser is specific to.
/// The object to parse and translate. It can be any arbitrary object, including null values (if
@@ -8833,10 +8815,10 @@ namespace DynamORM
internal virtual string Parse(object node, IDictionary pars = null, bool rawstr = false, bool nulls = false, bool decorate = true, bool isMultiPart = true)
{
DynamicSchemaColumn? c = null;
-
+
return Parse(node, ref c, pars, rawstr, nulls, decorate, isMultiPart);
}
-
+
/// Parses the arbitrary object given and translates it into a string with the appropriate
/// syntax for the database this parser is specific to.
/// The object to parse and translate. It can be any arbitrary object, including null values (if
@@ -8859,31 +8841,31 @@ namespace DynamORM
{
if (!nulls)
throw new ArgumentNullException("node", "Null nodes are not accepted.");
-
+
return Dispatch(node, ref columnSchema, pars, decorate);
}
-
+
// Nodes that are strings are parametrized or not depending the "rawstr" flag...
if (node is string)
{
if (rawstr) return (string)node;
else return Dispatch(node, ref columnSchema, pars, decorate);
}
-
+
// If node is a delegate, parse it to create the logical tree...
if (node is Delegate)
{
using (DynamicParser p = DynamicParser.Parse((Delegate)node))
{
node = p.Result;
-
+
return Parse(node, ref columnSchema, pars, rawstr, decorate: decorate); // Intercept containers as in (x => "string")
}
}
-
+
return Dispatch(node, ref columnSchema, pars, decorate, isMultiPart);
}
-
+
private string Dispatch(object node, ref DynamicSchemaColumn? columnSchema, IDictionary pars = null, bool decorate = true, bool isMultiPart = true)
{
if (node != null)
@@ -8898,38 +8880,38 @@ namespace DynamORM
else if (node is DynamicParser.Node.Invoke) return ParseInvoke((DynamicParser.Node.Invoke)node, ref columnSchema, pars);
else if (node is DynamicParser.Node.Convert) return ParseConvert((DynamicParser.Node.Convert)node, pars);
}
-
+
// All other cases are considered constant parameters...
return ParseConstant(node, pars, columnSchema);
}
-
+
internal virtual string ParseCommand(DynamicQueryBuilder node, IDictionary pars = null)
{
// Getting the command's text...
string str = node.CommandText(); // Avoiding spurious "OUTPUT XXX" statements
-
+
// If there are parameters to transform, but cannot store them, it is an error
if (node.Parameters.Count != 0 && pars == null)
return string.Format("({0})", str);
-
+
// TODO: Make special condiion
////throw new InvalidOperationException(string.Format("The parameters in this command '{0}' cannot be added to a null collection.", node.Parameters));
-
+
// Copy parameters to new comand
foreach (KeyValuePair parameter in node.Parameters)
pars.Add(parameter.Key, parameter.Value);
-
+
return string.Format("({0})", str);
}
-
+
protected virtual string ParseArgument(DynamicParser.Node.Argument node, bool isMultiPart = true, bool isOwner = false)
{
if (!string.IsNullOrEmpty(node.Name) && (isOwner || (isMultiPart && IsTableAlias(node.Name))))
return node.Name;
-
+
return null;
}
-
+
protected virtual string ParseGetMember(DynamicParser.Node.GetMember node, ref DynamicSchemaColumn? columnSchema, IDictionary pars = null, bool decorate = true, bool isMultiPart = true)
{
if (node.Host is DynamicParser.Node.Argument && IsTableAlias(node.Name))
@@ -8937,7 +8919,7 @@ namespace DynamORM
decorate = false;
isMultiPart = false;
}
-
+
// This hack allows to use argument as alias, but when it is not nesesary use other column.
// Let say we hace a table Users with alias usr, and we join to table with alias ua which also has a column Users
// This allow use of usr => usr.ua.Users to result in ua."Users" instead of "Users" or usr."ua"."Users", se tests for examples.
@@ -8954,17 +8936,17 @@ namespace DynamORM
else if (isMultiPart)
parent = Parse(node.Host, pars, isMultiPart: isMultiPart);
}
-
+
////string parent = node.Host == null || !isMultiPart ? null : Parse(node.Host, pars, isMultiPart: !IsTable(node.Name, node.Host.Name));
string name = parent == null ?
decorate ? Database.DecorateName(node.Name) : node.Name :
string.Format("{0}.{1}", parent, decorate ? Database.DecorateName(node.Name) : node.Name);
-
+
columnSchema = GetColumnFromSchema(name);
-
+
return name;
}
-
+
protected virtual string ParseSetMember(DynamicParser.Node.SetMember node, ref DynamicSchemaColumn? columnSchema, IDictionary pars = null, bool decorate = true, bool isMultiPart = true)
{
if (node.Host is DynamicParser.Node.Argument && IsTableAlias(node.Name))
@@ -8972,7 +8954,7 @@ namespace DynamORM
decorate = false;
isMultiPart = false;
}
-
+
string parent = null;
if (node.Host != null)
{
@@ -8986,18 +8968,18 @@ namespace DynamORM
else if (isMultiPart)
parent = Parse(node.Host, pars, isMultiPart: isMultiPart);
}
-
+
////string parent = node.Host == null || !isMultiPart ? null : Parse(node.Host, pars, isMultiPart: !IsTable(node.Name, node.Host.Name));
string name = parent == null ?
decorate ? Database.DecorateName(node.Name) : node.Name :
string.Format("{0}.{1}", parent, decorate ? Database.DecorateName(node.Name) : node.Name);
-
+
columnSchema = GetColumnFromSchema(name);
-
+
string value = Parse(node.Value, ref columnSchema, pars, nulls: true);
return string.Format("{0} = ({1})", name, value);
}
-
+
protected virtual string ParseUnary(DynamicParser.Node.Unary node, IDictionary pars = null)
{
switch (node.Operation)
@@ -9005,19 +8987,19 @@ namespace DynamORM
// Artifacts from the DynamicParser class that are not usefull here...
case ExpressionType.IsFalse:
case ExpressionType.IsTrue: return Parse(node.Target, pars);
-
+
// Unary supported operations...
case ExpressionType.Not: return string.Format("(NOT {0})", Parse(node.Target, pars));
case ExpressionType.Negate: return string.Format("!({0})", Parse(node.Target, pars));
}
-
+
throw new ArgumentException("Not supported unary operation: " + node);
}
-
+
protected virtual string ParseBinary(DynamicParser.Node.Binary node, IDictionary pars = null)
{
string op = string.Empty;
-
+
switch (node.Operation)
{
// Arithmetic binary operations...
@@ -9027,35 +9009,35 @@ namespace DynamORM
case ExpressionType.Divide: op = "/"; break;
case ExpressionType.Modulo: op = "%"; break;
case ExpressionType.Power: op = "^"; break;
-
+
case ExpressionType.And: op = "AND"; break;
case ExpressionType.Or: op = "OR"; break;
-
+
// Logical comparisons...
case ExpressionType.GreaterThan: op = ">"; break;
case ExpressionType.GreaterThanOrEqual: op = ">="; break;
case ExpressionType.LessThan: op = "<"; break;
case ExpressionType.LessThanOrEqual: op = "<="; break;
-
+
// Comparisons against 'NULL' require the 'IS' or 'IS NOT' operator instead the numeric ones...
case ExpressionType.Equal: op = node.Right == null && !VirtualMode ? "IS" : "="; break;
case ExpressionType.NotEqual: op = node.Right == null && !VirtualMode ? "IS NOT" : "<>"; break;
-
+
default: throw new ArgumentException("Not supported operator: '" + node.Operation);
}
-
+
DynamicSchemaColumn? columnSchema = null;
string left = Parse(node.Left, ref columnSchema, pars); // Not nulls: left is assumed to be an object
string right = Parse(node.Right, ref columnSchema, pars, nulls: true);
return string.Format("({0} {1} {2})", left, op, right);
}
-
+
protected virtual string ParseMethod(DynamicParser.Node.Method node, ref DynamicSchemaColumn? columnSchema, IDictionary pars = null)
{
string method = node.Name.ToUpper();
string parent = node.Host == null ? null : Parse(node.Host, ref columnSchema, pars: pars);
string item = null;
-
+
// Root-level methods...
if (node.Host == null)
{
@@ -9067,7 +9049,7 @@ namespace DynamORM
return string.Format("(NOT {0})", item);
}
}
-
+
// Column-level methods...
if (node.Host != null)
{
@@ -9077,47 +9059,47 @@ namespace DynamORM
{
if (node.Arguments == null || node.Arguments.Length == 0)
throw new ArgumentException("BETWEEN method expects at least one argument: " + node.Arguments.Sketch());
-
+
if (node.Arguments.Length > 2)
throw new ArgumentException("BETWEEN method expects at most two arguments: " + node.Arguments.Sketch());
-
+
object[] arguments = node.Arguments;
-
+
if (arguments.Length == 1 && (arguments[0] is IEnumerable || arguments[0] is Array) && !(arguments[0] is byte[]))
{
IEnumerable vals = arguments[0] as IEnumerable;
-
+
if (vals == null && arguments[0] is Array)
vals = ((Array)arguments[0]).Cast() as IEnumerable;
-
+
if (vals != null)
arguments = vals.ToArray();
else
throw new ArgumentException("BETWEEN method expects single argument to be enumerable of exactly two elements: " + node.Arguments.Sketch());
}
-
+
return string.Format("{0} BETWEEN {1} AND {2}", parent, Parse(arguments[0], ref columnSchema, pars: pars), Parse(arguments[1], ref columnSchema, pars: pars));
}
-
+
case "IN":
{
if (node.Arguments == null || node.Arguments.Length == 0)
throw new ArgumentException("IN method expects at least one argument: " + node.Arguments.Sketch());
-
+
bool firstParam = true;
StringBuilder sbin = new StringBuilder();
foreach (object arg in node.Arguments)
{
if (!firstParam)
sbin.Append(", ");
-
+
if ((arg is IEnumerable || arg is Array) && !(arg is byte[]))
{
IEnumerable vals = arg as IEnumerable;
-
+
if (vals == null && arg is Array)
vals = ((Array)arg).Cast() as IEnumerable;
-
+
if (vals != null)
foreach (object val in vals)
{
@@ -9125,7 +9107,7 @@ namespace DynamORM
sbin.Append(", ");
else
firstParam = false;
-
+
sbin.Append(Parse(val, ref columnSchema, pars: pars));
}
else
@@ -9133,32 +9115,32 @@ namespace DynamORM
}
else
sbin.Append(Parse(arg, ref columnSchema, pars: pars));
-
+
firstParam = false;
}
-
+
return string.Format("{0} IN({1})", parent, sbin.ToString());
}
-
+
case "NOTIN":
{
if (node.Arguments == null || node.Arguments.Length == 0)
throw new ArgumentException("IN method expects at least one argument: " + node.Arguments.Sketch());
-
+
bool firstParam = true;
StringBuilder sbin = new StringBuilder();
foreach (object arg in node.Arguments)
{
if (!firstParam)
sbin.Append(", ");
-
+
if ((arg is IEnumerable || arg is Array) && !(arg is byte[]))
{
IEnumerable vals = arg as IEnumerable;
-
+
if (vals == null && arg is Array)
vals = ((Array)arg).Cast() as IEnumerable;
-
+
if (vals != null)
foreach (object val in vals)
{
@@ -9166,7 +9148,7 @@ namespace DynamORM
sbin.Append(", ");
else
firstParam = false;
-
+
sbin.Append(Parse(val, ref columnSchema, pars: pars));
}
else
@@ -9174,106 +9156,106 @@ namespace DynamORM
}
else
sbin.Append(Parse(arg, ref columnSchema, pars: pars));
-
+
firstParam = false;
}
-
+
return string.Format("{0} NOT IN({1})", parent, sbin.ToString());
}
-
+
case "LIKE":
if (node.Arguments == null || node.Arguments.Length != 1)
throw new ArgumentException("LIKE method expects one argument: " + node.Arguments.Sketch());
-
+
return string.Format("{0} LIKE {1}", parent, Parse(node.Arguments[0], ref columnSchema, pars: pars));
-
+
case "NOTLIKE":
if (node.Arguments == null || node.Arguments.Length != 1)
throw new ArgumentException("NOT LIKE method expects one argument: " + node.Arguments.Sketch());
-
+
return string.Format("{0} NOT LIKE {1}", parent, Parse(node.Arguments[0], ref columnSchema, pars: pars));
-
+
case "AS":
if (node.Arguments == null || node.Arguments.Length != 1)
throw new ArgumentException("AS method expects one argument: " + node.Arguments.Sketch());
-
+
item = Parse(node.Arguments[0], pars: null, rawstr: true, isMultiPart: false); // pars=null to avoid to parameterize aliases
item = item.Validated("Alias"); // Intercepting null and empty aliases
return string.Format("{0} AS {1}", parent, item);
-
+
case "NOLOCK":
if (!SupportNoLock)
return parent;
-
+
if (node.Arguments != null && node.Arguments.Length > 1)
throw new ArgumentException("NOLOCK method expects no arguments.");
-
+
return string.Format("{0} {1}", parent, "WITH(NOLOCK)");
-
+
case "COUNT":
if (node.Arguments != null && node.Arguments.Length > 1)
throw new ArgumentException("COUNT method expects one or none argument: " + node.Arguments.Sketch());
-
+
if (node.Arguments == null || node.Arguments.Length == 0)
return "COUNT(*)";
-
+
return string.Format("COUNT({0})", Parse(node.Arguments[0], ref columnSchema, pars: Parameters, nulls: true));
-
+
case "COUNT0":
if (node.Arguments != null && node.Arguments.Length > 0)
throw new ArgumentException("COUNT0 method doesn't expect arguments");
-
+
return "COUNT(0)";
}
}
-
+
// Default case: parsing the method's name along with its arguments...
method = parent == null ? node.Name : string.Format("{0}.{1}", parent, node.Name);
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}(", method);
-
+
if (node.Arguments != null && node.Arguments.Length != 0)
{
bool first = true;
-
+
foreach (object argument in node.Arguments)
{
if (!first)
sb.Append(", ");
else
first = false;
-
+
sb.Append(Parse(argument, ref columnSchema, pars, nulls: true)); // We don't accept raw strings here!!!
}
}
-
+
sb.Append(")");
return sb.ToString();
}
-
+
protected virtual string ParseInvoke(DynamicParser.Node.Invoke node, ref DynamicSchemaColumn? columnSchema, IDictionary pars = null)
{
// This is used as an especial syntax to merely concatenate its arguments. It is used as a way to extend the supported syntax without the need of treating all the possible cases...
if (node.Arguments == null || node.Arguments.Length == 0)
return string.Empty;
-
+
StringBuilder sb = new StringBuilder();
foreach (object arg in node.Arguments)
{
if (arg is string)
{
sb.Append((string)arg);
-
+
if (node.Arguments.Length == 1 && !columnSchema.HasValue)
columnSchema = GetColumnFromSchema((string)arg);
}
else
sb.Append(Parse(arg, ref columnSchema, pars, rawstr: true, nulls: true));
}
-
+
return sb.ToString();
}
-
+
protected virtual string ParseConvert(DynamicParser.Node.Convert node, IDictionary pars = null)
{
// The cast mechanism is left for the specific database implementation, that should override this method
@@ -9281,16 +9263,16 @@ namespace DynamORM
string r = Parse(node.Target, pars);
return r;
}
-
+
protected virtual string ParseConstant(object node, IDictionary pars = null, DynamicSchemaColumn? columnSchema = null)
{
if (node == null && !VirtualMode)
return ParseNull();
-
+
if (pars != null)
{
bool wellKnownName = VirtualMode && node is String && ((String)node).StartsWith("[$") && ((String)node).EndsWith("]") && ((String)node).Length > 4;
-
+
// If we have a list of parameters to store it, let's parametrize it
Parameter par = new Parameter()
{
@@ -9300,60 +9282,60 @@ namespace DynamORM
Virtual = VirtualMode,
Schema = columnSchema,
};
-
+
// If we are adding parameter we inform external sources about this.
if (OnCreateTemporaryParameter != null)
OnCreateTemporaryParameter.ForEach(x => x(par));
-
+
pars.Add(par.Name, par);
-
+
return string.Format("[${0}]", par.Name);
}
-
+
return node.ToString(); // Last resort case
}
-
+
protected virtual string ParseNull()
{
return "NULL"; // Override if needed
}
-
+
#endregion Parser
-
+
#region Helpers
-
+
internal bool IsTableAlias(string name)
{
DynamicQueryBuilder builder = this;
-
+
while (builder != null)
{
if (builder.Tables.Any(t => t.Alias == name))
return true;
-
+
builder = builder._parent;
}
-
+
return false;
}
-
+
internal bool IsTable(string name, string owner)
{
DynamicQueryBuilder builder = this;
-
+
while (builder != null)
{
if ((string.IsNullOrEmpty(owner) && builder.Tables.Any(t => t.Name.ToLower() == name.ToLower())) ||
(!string.IsNullOrEmpty(owner) && builder.Tables.Any(t => t.Name.ToLower() == name.ToLower() &&
!string.IsNullOrEmpty(t.Owner) && t.Owner.ToLower() == owner.ToLower())))
return true;
-
+
builder = builder._parent;
}
-
+
return false;
}
-
+
internal string FixObjectName(string main, bool onlyColumn = false)
{
if (main.IndexOf("(") > 0 && main.IndexOf(")") > 0)
@@ -9361,133 +9343,133 @@ namespace DynamORM
else
return FixObjectNamePrivate(main, onlyColumn);
}
-
+
private string FixObjectNamePrivate(string f, bool onlyColumn = false)
{
IEnumerable objects = f.Split('.')
.Select(x => Database.StripName(x));
-
+
if (onlyColumn || objects.Count() == 1)
f = Database.DecorateName(objects.Last());
else if (!IsTableAlias(objects.First()))
f = string.Join(".", objects.Select(o => Database.DecorateName(o)));
else
f = string.Format("{0}.{1}", objects.First(), string.Join(".", objects.Skip(1).Select(o => Database.DecorateName(o))));
-
+
return f;
}
-
+
internal DynamicSchemaColumn? GetColumnFromSchema(string colName, DynamicTypeMap mapper = null, string table = null)
{
// This is tricky and will not always work unfortunetly.
////if (colName.ContainsAny(StringExtensions.InvalidMultipartMemberChars))
//// return null;
-
+
// First we need to get real column name and it's owner if exist.
string[] parts = colName.Split('.');
for (int i = 0; i < parts.Length; i++)
parts[i] = Database.StripName(parts[i]);
-
+
string columnName = parts.Last();
-
+
// Get table name from mapper
string tableName = table;
-
+
if (string.IsNullOrEmpty(tableName))
{
tableName = (mapper != null && mapper.Table != null) ? mapper.Table.Name : string.Empty;
-
+
if (parts.Length > 1 && string.IsNullOrEmpty(tableName))
{
// OK, we have a multi part identifier, that's good, we can get table name
tableName = string.Join(".", parts.Take(parts.Length - 1));
}
}
-
+
// Try to get table info from cache
ITableInfo tableInfo = !string.IsNullOrEmpty(tableName) ?
Tables.FirstOrDefault(x => !string.IsNullOrEmpty(x.Alias) && x.Alias.ToLower() == tableName) ??
Tables.FirstOrDefault(x => x.Name.ToLower() == tableName.ToLower()) ?? Tables.FirstOrDefault() :
this is DynamicModifyBuilder || Tables.Count == 1 ? Tables.FirstOrDefault() : null;
-
+
// Try to get column from schema
if (tableInfo != null && tableInfo.Schema != null)
return tableInfo.Schema.TryGetNullable(columnName.ToLower());
-
+
// Well, we failed to find a column
return null;
}
-
+
#endregion Helpers
-
+
#region IExtendedDisposable
-
+
/// Gets a value indicating whether this instance is disposed.
public bool IsDisposed { get; private set; }
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
public virtual void Dispose()
{
IsDisposed = true;
-
+
if (Database != null)
Database.RemoveFromCache(this);
-
+
if (Parameters != null)
{
foreach (KeyValuePair p in Parameters)
p.Value.Dispose();
-
+
Parameters.Clear();
Parameters = null;
}
-
+
if (Tables != null)
{
foreach (ITableInfo t in Tables)
if (t != null)
t.Dispose();
-
+
Tables.Clear();
Tables = null;
}
-
+
WhereCondition = null;
Database = null;
}
-
+
#endregion IExtendedDisposable
}
-
+
/// Implementation of dynamic select query builder.
internal class DynamicSelectQueryBuilder : DynamicQueryBuilder, IDynamicSelectQueryBuilder, DynamicQueryBuilder.IQueryWithWhere, DynamicQueryBuilder.IQueryWithHaving
{
private int? _limit = null;
private int? _offset = null;
private bool _distinct = false;
-
+
private string _select;
private string _from;
private string _join;
private string _groupby;
private string _orderby;
-
+
#region IQueryWithHaving
-
+
/// Gets or sets the having condition.
public string HavingCondition { get; set; }
-
+
/// Gets or sets the amount of not closed brackets in having statement.
public int HavingOpenBracketsCount { get; set; }
-
+
#endregion IQueryWithHaving
-
+
///
/// Gets a value indicating whether this instance has select columns.
///
public bool HasSelectColumns { get { return !string.IsNullOrEmpty(_select); } }
-
+
///
/// Initializes a new instance of the class.
///
@@ -9496,7 +9478,7 @@ namespace DynamORM
: base(db)
{
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -9506,17 +9488,17 @@ namespace DynamORM
: base(db, parent)
{
}
-
+
/// Generates the text this command will execute against the underlying database.
/// The text to execute against the underlying database.
public override string CommandText()
{
bool lused = false;
bool oused = false;
-
+
StringBuilder sb = new StringBuilder("SELECT");
if (_distinct) sb.AppendFormat(" DISTINCT");
-
+
if (_limit.HasValue)
{
if ((Database.Options & DynamicDatabaseOptions.SupportTop) == DynamicDatabaseOptions.SupportTop)
@@ -9530,13 +9512,13 @@ namespace DynamORM
lused = true;
}
}
-
+
if (_offset.HasValue && (Database.Options & DynamicDatabaseOptions.SupportFirstSkip) == DynamicDatabaseOptions.SupportFirstSkip)
{
sb.AppendFormat(" SKIP {0}", _offset);
oused = true;
}
-
+
if (_select != null) sb.AppendFormat(" {0}", _select); else sb.Append(" *");
if (_from != null) sb.AppendFormat(" FROM {0}", _from);
if (_join != null) sb.AppendFormat(" {0}", _join);
@@ -9548,12 +9530,12 @@ namespace DynamORM
sb.AppendFormat(" LIMIT {0}", _limit);
if (_offset.HasValue && !oused && (Database.Options & DynamicDatabaseOptions.SupportLimitOffset) == DynamicDatabaseOptions.SupportLimitOffset)
sb.AppendFormat(" OFFSET {0}", _offset);
-
+
return sb.ToString();
}
-
+
#region Execution
-
+
/// Execute this builder.
/// Enumerator of objects expanded from query.
public virtual IEnumerable Execute()
@@ -9566,11 +9548,11 @@ namespace DynamORM
.SetCommand(this)
.ExecuteReader())
cache = new DynamicCachedReader(rdr);
-
+
while (cache.Read())
{
dynamic val = null;
-
+
// Work around to avoid yield being in try...catchblock:
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
try
@@ -9581,16 +9563,16 @@ namespace DynamORM
{
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;
}
}
}
-
+
/// Execute this builder and map to given type.
/// Type of object to map on.
/// Enumerator of objects expanded from query.
@@ -9598,10 +9580,10 @@ namespace DynamORM
{
DynamicCachedReader cache = null;
DynamicTypeMap mapper = DynamicMapperCache.GetMapper();
-
+
if (mapper == null)
throw new InvalidOperationException("Type can't be mapped for unknown reason.");
-
+
using (IDbConnection con = Database.Open())
using (IDbCommand cmd = con.CreateCommand())
{
@@ -9609,11 +9591,11 @@ namespace DynamORM
.SetCommand(this)
.ExecuteReader())
cache = new DynamicCachedReader(rdr);
-
+
while (cache.Read())
{
dynamic val = null;
-
+
// Work around to avoid yield being in try...catchblock:
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
try
@@ -9624,16 +9606,16 @@ namespace DynamORM
{
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 mapper.Create(val) as T;
}
}
}
-
+
/// Execute this builder as a data reader.
/// Action containing reader.
public virtual void ExecuteDataReader(Action reader)
@@ -9645,24 +9627,24 @@ namespace DynamORM
.ExecuteReader())
reader(rdr);
}
-
+
/// Execute this builder as a data reader, but
/// first makes a full reader copy in memory.
/// Action containing reader.
public virtual void ExecuteCachedDataReader(Action reader)
{
DynamicCachedReader cache = null;
-
+
using (IDbConnection con = Database.Open())
using (IDbCommand cmd = con.CreateCommand())
using (IDataReader rdr = cmd
.SetCommand(this)
.ExecuteReader())
cache = new DynamicCachedReader(rdr);
-
+
reader(cache);
}
-
+
/// Returns a single result.
/// Result of a query.
public virtual object Scalar()
@@ -9675,9 +9657,9 @@ namespace DynamORM
.ExecuteScalar();
}
}
-
-#if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE
-
+
+ #if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE
+
/// Returns a single result.
/// Type to parse to.
/// Default value.
@@ -9692,13 +9674,13 @@ namespace DynamORM
.ExecuteScalarAs(defaultValue);
}
}
-
-#endif
-
+
+ #endif
+
#endregion Execution
-
+
#region From/Join
-
+
///
/// Adds to the 'From' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
/// formats are:
@@ -9714,25 +9696,25 @@ namespace DynamORM
{
if (fn == null)
throw new ArgumentNullException("Array of functions cannot be or contain null.");
-
+
int index = FromFunc(-1, fn);
foreach (Func f in func)
index = FromFunc(index, f);
-
+
return this;
}
-
+
private int FromFunc(int index, Func f)
{
if (f == null)
throw new ArgumentNullException("Array of functions cannot be or contain null.");
-
+
index++;
ITableInfo tableInfo = null;
using (DynamicParser parser = DynamicParser.Parse(f))
{
object result = parser.Result;
-
+
// If the expression result is string.
if (result is string)
{
@@ -9749,25 +9731,25 @@ namespace DynamORM
Type type = (Type)result;
if (type.IsAnonymous())
throw new InvalidOperationException(string.Format("Cant assign anonymous type as a table ({0}). Parsing {1}", type.FullName, result));
-
+
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(type);
-
+
if (mapper == null)
throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}). Parsing {1}", type.FullName, result));
-
+
tableInfo = new TableInfo(Database, type);
}
else if (result is DynamicParser.Node)
{
// Or if it resolves to a dynamic node
DynamicParser.Node node = (DynamicParser.Node)result;
-
+
string owner = null;
string main = null;
string alias = null;
bool nolock = false;
Type type = null;
-
+
while (true)
{
// Support for the AS() virtual method...
@@ -9775,62 +9757,62 @@ namespace DynamORM
{
if (alias != null)
throw new ArgumentException(string.Format("Alias '{0}' is already set when parsing '{1}'.", alias, result));
-
+
object[] args = ((DynamicParser.Node.Method)node).Arguments;
-
+
if (args == null)
throw new ArgumentNullException("arg", "AS() is not a parameterless method.");
-
+
if (args.Length != 1)
throw new ArgumentException("AS() requires one and only one parameter: " + args.Sketch());
-
+
alias = Parse(args[0], rawstr: true, decorate: false).Validated("Alias");
-
+
node = node.Host;
continue;
}
-
+
// Support for the NoLock() virtual method...
if (node is DynamicParser.Node.Method && ((DynamicParser.Node.Method)node).Name.ToUpper() == "NOLOCK")
{
object[] args = ((DynamicParser.Node.Method)node).Arguments;
-
+
if (args != null && args.Length > 0)
throw new ArgumentNullException("arg", "NoLock() doesn't support arguments.");
-
+
nolock = true;
-
+
node = node.Host;
continue;
}
-
+
/*if (node is DynamicParser.Node.Method && ((DynamicParser.Node.Method)node).Name.ToUpper() == "subquery")
{
main = Parse(this.SubQuery(((DynamicParser.Node.Method)node).Arguments.Where(p => p is Func).Cast>().ToArray()), Parameters);
continue;
}*/
-
+
// Support for table specifications...
if (node is DynamicParser.Node.GetMember)
{
if (owner != null)
throw new ArgumentException(string.Format("Owner '{0}.{1}' is already set when parsing '{2}'.", owner, main, result));
-
+
if (main != null)
owner = ((DynamicParser.Node.GetMember)node).Name;
else
main = ((DynamicParser.Node.GetMember)node).Name;
-
+
node = node.Host;
continue;
}
-
+
// Support for generic sources...
if (node is DynamicParser.Node.Invoke)
{
if (owner != null)
throw new ArgumentException(string.Format("Owner '{0}.{1}' is already set when parsing '{2}'.", owner, main, result));
-
+
if (main != null)
owner = string.Format("{0}", Parse(node, rawstr: true, pars: Parameters));
else
@@ -9841,69 +9823,69 @@ namespace DynamORM
type = (Type)invoke.Arguments[0];
if (type.IsAnonymous())
throw new InvalidOperationException(string.Format("Cant assign anonymous type as a table ({0}). Parsing {1}", type.FullName, result));
-
+
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(type);
-
+
if (mapper == null)
throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}). Parsing {1}", type.FullName, result));
-
+
main = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Name) ?
mapper.Type.Name : mapper.Table.Name;
-
+
owner = (mapper.Table != null) ? mapper.Table.Owner : owner;
}
else
main = string.Format("{0}", Parse(node, rawstr: true, pars: Parameters));
}
-
+
node = node.Host;
continue;
}
-
+
// Just finished the parsing...
if (node is DynamicParser.Node.Argument) break;
-
+
// All others are assumed to be part of the main element...
if (main != null)
main = Parse(node, pars: Parameters);
else
main = Parse(node, pars: Parameters);
-
+
break;
}
-
+
if (!string.IsNullOrEmpty(main))
tableInfo = type == null ? new TableInfo(Database, main, alias, owner, nolock) : new TableInfo(Database, type, alias, owner, nolock);
else
throw new ArgumentException(string.Format("Specification #{0} is invalid: {1}", index, result));
}
-
+
// Or it is a not supported expression...
if (tableInfo == null)
throw new ArgumentException(string.Format("Specification #{0} is invalid: {1}", index, result));
-
+
Tables.Add(tableInfo);
-
+
// We finally add the contents...
StringBuilder sb = new StringBuilder();
-
+
if (!string.IsNullOrEmpty(tableInfo.Owner))
sb.AppendFormat("{0}.", Database.DecorateName(tableInfo.Owner));
-
+
sb.Append(tableInfo.Name.ContainsAny(StringExtensions.InvalidMemberChars) ? tableInfo.Name : Database.DecorateName(tableInfo.Name));
-
+
if (!string.IsNullOrEmpty(tableInfo.Alias))
sb.AppendFormat(" AS {0}", tableInfo.Alias);
-
+
if (SupportNoLock && tableInfo.NoLock)
sb.AppendFormat(" WITH(NOLOCK)");
-
+
_from = string.IsNullOrEmpty(_from) ? sb.ToString() : string.Format("{0}, {1}", _from, sb.ToString());
}
-
+
return index;
}
-
+
///
/// Adds to the 'Join' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
/// formats are:
@@ -9925,7 +9907,7 @@ namespace DynamORM
// We need to do two passes to add aliases first.
return JoinInternal(true, func).JoinInternal(false, func);
}
-
+
///
/// Adds to the 'Join' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
/// formats are:
@@ -9946,22 +9928,22 @@ namespace DynamORM
protected virtual DynamicSelectQueryBuilder JoinInternal(bool justAddTables, params Func[] func)
{
if (func == null) throw new ArgumentNullException("Array of functions cannot be null.");
-
+
int index = -1;
-
+
foreach (Func f in func)
{
index++;
ITableInfo tableInfo = null;
-
+
if (f == null)
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
-
+
using (DynamicParser parser = DynamicParser.Parse(f))
{
object result = parser.Result;
if (result == null) throw new ArgumentException(string.Format("Specification #{0} resolves to null.", index));
-
+
string type = null;
string main = null;
string owner = null;
@@ -9969,14 +9951,14 @@ namespace DynamORM
string condition = null;
bool nolock = false;
Type tableType = null;
-
+
// If the expression resolves to a string...
if (result is string)
{
string node = (string)result;
-
+
int n = node.ToUpper().IndexOf("JOIN ");
-
+
if (n < 0)
main = node;
else
@@ -9985,15 +9967,15 @@ namespace DynamORM
type = node.Substring(0, n + 4);
main = node.Substring(n + 4);
}
-
+
n = main.ToUpper().IndexOf("ON");
-
+
if (n >= 0)
{
condition = main.Substring(n + 3);
main = main.Substring(0, n).Trim();
}
-
+
Tuple tuple = main.SplitSomethingAndAlias(); // In this case we split on the remaining 'main'
string[] parts = tuple.Item1.Split('.');
main = Database.StripName(parts.Last()).Validated("Table");
@@ -10011,78 +9993,78 @@ namespace DynamORM
{
if (condition != null)
throw new ArgumentException(string.Format("Condition '{0}' is already set when parsing '{1}'.", alias, result));
-
+
object[] args = ((DynamicParser.Node.Method)node).Arguments;
if (args == null)
throw new ArgumentNullException("arg", "ON() is not a parameterless method.");
-
+
if (args.Length != 1)
throw new ArgumentException("ON() requires one and only one parameter: " + args.Sketch());
-
+
condition = Parse(args[0], rawstr: true, pars: justAddTables ? null : Parameters);
-
+
node = node.Host;
continue;
}
-
+
// Support for the AS() virtual method...
if (node is DynamicParser.Node.Method && ((DynamicParser.Node.Method)node).Name.ToUpper() == "AS")
{
if (alias != null)
throw new ArgumentException(string.Format("Alias '{0}' is already set when parsing '{1}'.", alias, result));
-
+
object[] args = ((DynamicParser.Node.Method)node).Arguments;
-
+
if (args == null)
throw new ArgumentNullException("arg", "AS() is not a parameterless method.");
-
+
if (args.Length != 1)
throw new ArgumentException("AS() requires one and only one parameter: " + args.Sketch());
-
+
alias = Parse(args[0], rawstr: true, decorate: false, isMultiPart: false).Validated("Alias");
-
+
node = node.Host;
continue;
}
-
+
// Support for the NoLock() virtual method...
if (node is DynamicParser.Node.Method && ((DynamicParser.Node.Method)node).Name.ToUpper() == "NOLOCK")
{
object[] args = ((DynamicParser.Node.Method)node).Arguments;
-
+
if (args != null && args.Length > 0)
throw new ArgumentNullException("arg", "NoLock() doesn't support arguments.");
-
+
nolock = true;
-
+
node = node.Host;
continue;
}
-
+
// Support for table specifications...
if (node is DynamicParser.Node.GetMember)
{
if (owner != null)
throw new ArgumentException(string.Format("Owner '{0}.{1}' is already set when parsing '{2}'.", owner, main, result));
-
+
if (main != null)
owner = ((DynamicParser.Node.GetMember)node).Name;
else
main = ((DynamicParser.Node.GetMember)node).Name;
-
+
node = node.Host;
continue;
}
-
+
// Support for Join Type specifications...
if (node is DynamicParser.Node.Method && (node.Host is DynamicParser.Node.Argument || node.Host is DynamicParser.Node.Invoke))
{
if (type != null) throw new ArgumentException(string.Format("Join type '{0}' is already set when parsing '{1}'.", main, result));
type = ((DynamicParser.Node.Method)node).Name;
-
+
bool avoid = false;
object[] args = ((DynamicParser.Node.Method)node).Arguments;
-
+
if (args != null && args.Length > 0)
{
avoid = args[0] is bool && !((bool)args[0]);
@@ -10090,7 +10072,7 @@ namespace DynamORM
if (!string.IsNullOrEmpty(proposedType))
type = proposedType;
}
-
+
type = type.ToUpper(); // Normalizing, and stepping out the trivial case...
if (type != "JOIN")
{
@@ -10099,13 +10081,13 @@ namespace DynamORM
type = type.Replace("OUTER", " OUTER ")
.Replace(" ", " ")
.Trim(' ');
-
+
// x => x.Left()...
int n = type.IndexOf("JOIN");
-
+
if (n < 0 && !avoid)
type += " JOIN";
-
+
// x => x.InnerJoin() / x => x.JoinLeft() ...
else
{
@@ -10116,17 +10098,17 @@ namespace DynamORM
}
}
}
-
+
node = node.Host;
continue;
}
-
+
// Support for generic sources...
if (node is DynamicParser.Node.Invoke)
{
if (owner != null)
throw new ArgumentException(string.Format("Owner '{0}.{1}' is already set when parsing '{2}'.", owner, main, result));
-
+
if (main != null)
owner = string.Format("{0}", Parse(node, rawstr: true, pars: justAddTables ? null : Parameters));
else
@@ -10136,23 +10118,23 @@ namespace DynamORM
{
tableType = (Type)invoke.Arguments[0];
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(tableType);
-
+
if (mapper == null)
throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", tableType.FullName));
-
+
main = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Name) ?
mapper.Type.Name : mapper.Table.Name;
-
+
owner = (mapper.Table != null) ? mapper.Table.Owner : owner;
}
else
main = string.Format("{0}", Parse(node, rawstr: true, pars: justAddTables ? null : Parameters));
}
-
+
node = node.Host;
continue;
}
-
+
// Just finished the parsing...
if (node is DynamicParser.Node.Argument) break;
throw new ArgumentException(string.Format("Specification #{0} is invalid: {1}", index, result));
@@ -10163,17 +10145,17 @@ namespace DynamORM
// Or it is a not supported expression...
throw new ArgumentException(string.Format("Specification #{0} is invalid: {1}", index, result));
}
-
+
// We annotate the aliases being conservative...
main = main.Validated("Main");
-
+
if (justAddTables)
{
if (!string.IsNullOrEmpty(main))
tableInfo = tableType == null ? new TableInfo(Database, main, alias, owner, nolock) : new TableInfo(Database, tableType, alias, owner, nolock);
else
throw new ArgumentException(string.Format("Specification #{0} is invalid: {1}", index, result));
-
+
Tables.Add(tableInfo);
}
else
@@ -10182,40 +10164,40 @@ namespace DynamORM
tableInfo = string.IsNullOrEmpty(alias) ?
Tables.SingleOrDefault(t => t.Name == main && string.IsNullOrEmpty(t.Alias)) :
Tables.SingleOrDefault(t => t.Alias == alias);
-
+
// We finally add the contents if we can...
StringBuilder sb = new StringBuilder();
if (string.IsNullOrEmpty(type))
type = "JOIN";
-
+
sb.AppendFormat("{0} ", type);
-
+
if (!string.IsNullOrEmpty(tableInfo.Owner))
sb.AppendFormat("{0}.", Database.DecorateName(tableInfo.Owner));
-
+
sb.Append(tableInfo.Name.ContainsAny(StringExtensions.InvalidMemberChars) ? tableInfo.Name : Database.DecorateName(tableInfo.Name));
-
+
if (!string.IsNullOrEmpty(tableInfo.Alias))
sb.AppendFormat(" AS {0}", tableInfo.Alias);
-
+
if (SupportNoLock && tableInfo.NoLock)
sb.AppendFormat(" WITH(NOLOCK)");
-
+
if (!string.IsNullOrEmpty(condition))
sb.AppendFormat(" ON {0}", condition);
-
+
_join = string.IsNullOrEmpty(_join) ? sb.ToString() : string.Format("{0} {1}", _join, sb.ToString()); // No comma in this case
}
}
}
-
+
return this;
}
-
+
#endregion From/Join
-
+
#region Where
-
+
///
/// Adds to the 'Where' clause the contents obtained from parsing the dynamic lambda expression given. The condition
/// is parsed to the appropriate syntax, where the specific customs virtual methods supported by the parser are used
@@ -10230,7 +10212,7 @@ namespace DynamORM
{
return this.InternalWhere(func);
}
-
+
/// Add where condition.
/// Condition column with operator and value.
/// Builder instance.
@@ -10238,7 +10220,7 @@ namespace DynamORM
{
return this.InternalWhere(column);
}
-
+
/// Add where condition.
/// Condition column.
/// Condition operator.
@@ -10248,7 +10230,7 @@ namespace DynamORM
{
return this.InternalWhere(column, op, value);
}
-
+
/// Add where condition.
/// Condition column.
/// Condition value.
@@ -10257,7 +10239,7 @@ namespace DynamORM
{
return this.InternalWhere(column, value);
}
-
+
/// Add where condition.
/// Set conditions as properties and values of an object.
/// If true use schema to determine key columns and ignore those which
@@ -10267,11 +10249,11 @@ namespace DynamORM
{
return this.InternalWhere(conditions, schema);
}
-
+
#endregion Where
-
+
#region Select
-
+
///
/// Adds to the 'Select' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
/// formats are:
@@ -10288,41 +10270,41 @@ namespace DynamORM
{
if (fn == null)
throw new ArgumentNullException("Array of specifications cannot be null.");
-
+
int index = SelectFunc(-1, fn);
if (func != null)
foreach (Func f in func)
index = SelectFunc(index, f);
-
+
return this;
}
-
+
private int SelectFunc(int index, Func f)
{
index++;
if (f == null)
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
-
+
using (DynamicParser parser = DynamicParser.Parse(f))
{
object result = parser.Result;
if (result == null)
throw new ArgumentException(string.Format("Specification #{0} resolves to null.", index));
-
+
string main = null;
string alias = null;
bool all = false;
bool anon = false;
-
+
// If the expression resolves to a string...
if (result is string)
{
string node = (string)result;
Tuple tuple = node.SplitSomethingAndAlias();
main = tuple.Item1.Validated("Table and/or Column");
-
+
main = FixObjectName(main);
-
+
alias = tuple.Item2.Validated("Alias", canbeNull: true);
}
else if (result is DynamicParser.Node)
@@ -10333,7 +10315,7 @@ namespace DynamORM
else if (result.GetType().IsAnonymous())
{
anon = true;
-
+
foreach (KeyValuePair prop in result.ToDictionary())
{
if (prop.Value is string)
@@ -10341,7 +10323,7 @@ namespace DynamORM
string node = (string)prop.Value;
Tuple tuple = node.SplitSomethingAndAlias();
main = FixObjectName(tuple.Item1.Validated("Table and/or Column"));
-
+
////alias = tuple.Item2.Validated("Alias", canbeNull: true);
}
else if (prop.Value is DynamicParser.Node)
@@ -10354,7 +10336,7 @@ namespace DynamORM
// Or it is a not supported expression...
throw new ArgumentException(string.Format("Specification #{0} in anonymous type is invalid: {1}", index, prop.Value));
}
-
+
alias = Database.DecorateName(prop.Key);
ParseSelectAddColumn(main, alias, all);
}
@@ -10364,14 +10346,14 @@ namespace DynamORM
// Or it is a not supported expression...
throw new ArgumentException(string.Format("Specification #{0} is invalid: {1}", index, result));
}
-
+
if (!anon)
ParseSelectAddColumn(main, alias, all);
}
-
+
return index;
}
-
+
/// Add select columns.
/// Columns to add to object.
/// Builder instance.
@@ -10379,10 +10361,10 @@ namespace DynamORM
{
foreach (DynamicColumn col in columns)
Select(x => col.ToSQLSelectColumn(Database));
-
+
return this;
}
-
+
/// Add select columns.
/// Columns to add to object.
/// Column format consist of Column Name , Alias and
@@ -10393,14 +10375,14 @@ namespace DynamORM
DynamicColumn[] cols = new DynamicColumn[columns.Length];
for (int i = 0; i < columns.Length; i++)
cols[i] = DynamicColumn.ParseSelectColumn(columns[i]);
-
+
return SelectColumn(cols);
}
-
+
#endregion Select
-
+
#region GroupBy
-
+
///
/// Adds to the 'Group By' clause the contents obtained from from parsing the dynamic lambda expression given.
///
@@ -10411,48 +10393,48 @@ namespace DynamORM
{
if (fn == null)
throw new ArgumentNullException("Array of specifications cannot be null.");
-
+
int index = GroupByFunc(-1, fn);
-
+
if (func != null)
for (int i = 0; i < func.Length; i++)
{
Func f = func[i];
index = GroupByFunc(index, f);
}
-
+
return this;
}
-
+
private int GroupByFunc(int index, Func f)
{
index++;
if (f == null)
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
-
+
using (DynamicParser parser = DynamicParser.Parse(f))
{
object result = parser.Result;
if (result == null)
throw new ArgumentException(string.Format("Specification #{0} resolves to null.", index));
-
+
string main = null;
-
+
if (result is string)
main = FixObjectName(result as string);
else
main = Parse(result, pars: Parameters);
-
+
main = main.Validated("Group By");
if (_groupby == null)
_groupby = main;
else
_groupby = string.Format("{0}, {1}", _groupby, main);
}
-
+
return index;
}
-
+
/// Add select columns.
/// Columns to group by.
/// Builder instance.
@@ -10463,10 +10445,10 @@ namespace DynamORM
DynamicColumn col = columns[i];
GroupBy(x => col.ToSQLGroupByColumn(Database));
}
-
+
return this;
}
-
+
/// Add select columns.
/// Columns to group by.
/// Column format consist of Column Name and
@@ -10476,11 +10458,11 @@ namespace DynamORM
{
return GroupByColumn(columns.Select(c => DynamicColumn.ParseSelectColumn(c)).ToArray());
}
-
+
#endregion GroupBy
-
+
#region Having
-
+
///
/// Adds to the 'Having' clause the contents obtained from parsing the dynamic lambda expression given. The condition
/// is parsed to the appropriate syntax, Having the specific customs virtual methods supported by the parser are used
@@ -10495,7 +10477,7 @@ namespace DynamORM
{
return this.InternalHaving(func);
}
-
+
/// Add Having condition.
/// Condition column with operator and value.
/// Builder instance.
@@ -10503,7 +10485,7 @@ namespace DynamORM
{
return this.InternalHaving(column);
}
-
+
/// Add Having condition.
/// Condition column.
/// Condition operator.
@@ -10513,7 +10495,7 @@ namespace DynamORM
{
return this.InternalHaving(column, op, value);
}
-
+
/// Add Having condition.
/// Condition column.
/// Condition value.
@@ -10522,7 +10504,7 @@ namespace DynamORM
{
return this.InternalHaving(column, value);
}
-
+
/// Add Having condition.
/// Set conditions as properties and values of an object.
/// If true use schema to determine key columns and ignore those which
@@ -10532,11 +10514,11 @@ namespace DynamORM
{
return this.InternalHaving(conditions, schema);
}
-
+
#endregion Having
-
+
#region OrderBy
-
+
///
/// Adds to the 'Order By' clause the contents obtained from from parsing the dynamic lambda expression given. It
/// accepts a multipart column specification followed by an optional Ascending() or Descending() virtual methods
@@ -10550,44 +10532,44 @@ namespace DynamORM
{
if (fn == null)
throw new ArgumentNullException("Array of specifications cannot be null.");
-
+
int index = OrderByFunc(-1, fn);
-
+
if (func != null)
for (int i = 0; i < func.Length; i++)
{
Func f = func[i];
index = OrderByFunc(index, f);
}
-
+
return this;
}
-
+
private int OrderByFunc(int index, Func f)
{
index++;
if (f == null)
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
-
+
using (DynamicParser parser = DynamicParser.Parse(f))
{
object result = parser.Result;
if (result == null) throw new ArgumentException(string.Format("Specification #{0} resolves to null.", index));
-
+
string main = null;
bool ascending = true;
-
+
if (result is int)
main = result.ToString();
else if (result is string)
{
string[] parts = ((string)result).Split(' ');
main = Database.StripName(parts.First());
-
+
int colNo;
if (!Int32.TryParse(main, out colNo))
main = FixObjectName(main);
-
+
ascending = parts.Length != 2 || parts.Last().ToUpper() == "ASCENDING" || parts.Last().ToUpper() == "ASC";
}
else
@@ -10604,9 +10586,9 @@ namespace DynamORM
throw new ArgumentException(string.Format("{0} must be a parameterless method, but found: {1}.", name, args.Sketch()));
else if ((args == null || args.Length != 1) && node.Host is DynamicParser.Node.Argument)
throw new ArgumentException(string.Format("{0} requires one numeric parameter, but found: {1}.", name, args.Sketch()));
-
+
ascending = (name == "ASCENDING" || name == "ASC") ? true : false;
-
+
if (args != null && args.Length == 1)
{
int col = -1;
@@ -10622,28 +10604,28 @@ namespace DynamORM
else
main = Parse(args[0], pars: Parameters);
}
-
+
result = node.Host;
}
}
-
+
// Just parsing the contents...
if (!(result is DynamicParser.Node.Argument))
main = Parse(result, pars: Parameters);
}
-
+
main = main.Validated("Order By");
main = string.Format("{0} {1}", main, ascending ? "ASC" : "DESC");
-
+
if (_orderby == null)
_orderby = main;
else
_orderby = string.Format("{0}, {1}", _orderby, main);
}
-
+
return index;
}
-
+
/// Add select columns.
/// Columns to order by.
/// Builder instance.
@@ -10654,10 +10636,10 @@ namespace DynamORM
DynamicColumn col = columns[i];
OrderBy(x => col.ToSQLOrderByColumn(Database));
}
-
+
return this;
}
-
+
/// Add select columns.
/// Columns to order by.
/// Column format consist of Column Name and
@@ -10667,11 +10649,11 @@ namespace DynamORM
{
return OrderByColumn(columns.Select(c => DynamicColumn.ParseOrderByColumn(c)).ToArray());
}
-
+
#endregion OrderBy
-
+
#region Top/Limit/Offset/Distinct
-
+
/// Set top if database support it.
/// How many objects select.
/// Builder instance.
@@ -10679,7 +10661,7 @@ namespace DynamORM
{
return Limit(top);
}
-
+
/// Set top if database support it.
/// How many objects select.
/// Builder instance.
@@ -10689,11 +10671,11 @@ namespace DynamORM
(Database.Options & DynamicDatabaseOptions.SupportFirstSkip) != DynamicDatabaseOptions.SupportFirstSkip &&
(Database.Options & DynamicDatabaseOptions.SupportTop) != DynamicDatabaseOptions.SupportTop)
throw new NotSupportedException("Database doesn't support LIMIT clause.");
-
+
_limit = limit;
return this;
}
-
+
/// Set top if database support it.
/// How many objects skip selecting.
/// Builder instance.
@@ -10702,11 +10684,11 @@ namespace DynamORM
if ((Database.Options & DynamicDatabaseOptions.SupportLimitOffset) != DynamicDatabaseOptions.SupportLimitOffset &&
(Database.Options & DynamicDatabaseOptions.SupportFirstSkip) != DynamicDatabaseOptions.SupportFirstSkip)
throw new NotSupportedException("Database doesn't support OFFSET clause.");
-
+
_offset = offset;
return this;
}
-
+
/// Set distinct mode.
/// Distinct mode.
/// Builder instance.
@@ -10715,31 +10697,31 @@ namespace DynamORM
_distinct = distinct;
return this;
}
-
+
#endregion Top/Limit/Offset/Distinct
-
+
#region Helpers
-
+
private void ParseSelectAddColumn(string main, string alias, bool all)
{
// We annotate the aliases being conservative...
main = main.Validated("Main");
-
+
////if (alias != null && !main.ContainsAny(StringExtensions.InvalidMemberChars)) TableAliasList.Add(new KTableAlias(main, alias));
-
+
// If all columns are requested...
if (all)
main += ".*";
-
+
// We finally add the contents...
string str = (alias == null || all) ? main : string.Format("{0} AS {1}", main, alias);
_select = _select == null ? str : string.Format("{0}, {1}", _select, str);
}
-
+
private void ParseSelectNode(object result, ref string column, ref string alias, ref bool all)
{
string main = null;
-
+
DynamicParser.Node node = (DynamicParser.Node)result;
while (true)
{
@@ -10748,59 +10730,59 @@ namespace DynamORM
{
if (alias != null)
throw new ArgumentException(string.Format("Alias '{0}' is already set when parsing '{1}'.", alias, result));
-
+
object[] args = ((DynamicParser.Node.Method)node).Arguments;
-
+
if (args == null)
throw new ArgumentNullException("arg", "AS() is not a parameterless method.");
-
+
if (args.Length != 1)
throw new ArgumentException("AS() requires one and only one parameter: " + args.Sketch());
-
+
// Yes, we decorate columns
alias = Parse(args[0], rawstr: true, decorate: true, isMultiPart: false).Validated("Alias");
-
+
node = node.Host;
continue;
}
-
+
// Support for the ALL() virtual method...
if (node is DynamicParser.Node.Method && ((DynamicParser.Node.Method)node).Name.ToUpper() == "ALL")
{
if (all)
throw new ArgumentException(string.Format("Flag to select all columns is already set when parsing '{0}'.", result));
-
+
object[] args = ((DynamicParser.Node.Method)node).Arguments;
-
+
if (args != null)
throw new ArgumentException("ALL() must be a parameterless virtual method, but found: " + args.Sketch());
-
+
all = true;
-
+
node = node.Host;
continue;
}
-
+
// Support for table and/or column specifications...
if (node is DynamicParser.Node.GetMember)
{
if (main != null)
throw new ArgumentException(string.Format("Main '{0}' is already set when parsing '{1}'.", main, result));
-
+
main = ((DynamicParser.Node.GetMember)node).Name;
-
+
if (node.Host is DynamicParser.Node.GetMember)
{
// If leaf then decorate
main = Database.DecorateName(main);
-
+
// Supporting multipart specifications...
node = node.Host;
-
+
// Get table/alias name
string table = ((DynamicParser.Node.GetMember)node).Name;
bool isAlias = node.Host is DynamicParser.Node.Argument && IsTableAlias(table);
-
+
if (isAlias)
main = string.Format("{0}.{1}", table, main);
else if (node.Host is DynamicParser.Node.GetMember)
@@ -10816,7 +10798,7 @@ namespace DynamORM
else if (node.Host is DynamicParser.Node.Argument)
{
string table = ((DynamicParser.Node.Argument)node.Host).Name;
-
+
if (IsTableAlias(table))
main = string.Format("{0}.{1}", table, Database.DecorateName(main));
else if (!IsTableAlias(main))
@@ -10824,74 +10806,74 @@ namespace DynamORM
}
else if (!(node.Host is DynamicParser.Node.Argument && IsTableAlias(main)))
main = Database.DecorateName(main);
-
+
node = node.Host;
-
+
continue;
}
-
+
// Support for generic sources...
if (node is DynamicParser.Node.Invoke)
{
if (main != null)
throw new ArgumentException(string.Format("Main '{0}' is already set when parsing '{1}'.", main, result));
-
+
main = string.Format("{0}", Parse(node, rawstr: true, pars: Parameters));
-
+
node = node.Host;
continue;
}
-
+
// Just finished the parsing...
if (node is DynamicParser.Node.Argument)
{
if (string.IsNullOrEmpty(main) && IsTableAlias(node.Name))
main = node.Name;
-
+
break;
}
-
+
// All others are assumed to be part of the main element...
if (main != null) throw new ArgumentException(string.Format("Main '{0}' is already set when parsing '{1}'.", main, result));
main = Parse(node, pars: Parameters);
-
+
break;
}
-
+
column = main;
}
-
+
#endregion Helpers
-
+
#region IExtendedDisposable
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
public override void Dispose()
{
base.Dispose();
-
+
_select = _from = _join = _groupby = _orderby = null;
}
-
+
#endregion IExtendedDisposable
}
-
+
/// Update query builder.
internal class DynamicUpdateQueryBuilder : DynamicModifyBuilder, IDynamicUpdateQueryBuilder, DynamicQueryBuilder.IQueryWithWhere
{
private string _columns;
-
+
internal DynamicUpdateQueryBuilder(DynamicDatabase db)
: base(db)
{
}
-
+
public DynamicUpdateQueryBuilder(DynamicDatabase db, string tableName)
: base(db, tableName)
{
}
-
+
/// Generates the text this command will execute against the underlying database.
/// The text to execute against the underlying database.
/// This method must be override by derived classes.
@@ -10904,9 +10886,9 @@ namespace DynamORM
string.IsNullOrEmpty(WhereCondition) ? string.Empty : " WHERE ",
WhereCondition);
}
-
+
#region Update
-
+
/// Add update value or where condition using schema.
/// Update or where column name.
/// Column value.
@@ -10914,18 +10896,18 @@ namespace DynamORM
public virtual IDynamicUpdateQueryBuilder Update(string column, object value)
{
DynamicSchemaColumn? col = GetColumnFromSchema(column);
-
+
if (!col.HasValue && SupportSchema)
throw new InvalidOperationException(string.Format("Column '{0}' not found in schema, can't use universal approach.", column));
-
+
if (col.HasValue && col.Value.IsKey)
Where(column, value);
else
Values(column, value);
-
+
return this;
}
-
+
/// Add update values and where condition columns using schema.
/// Set values or conditions as properties and values of an object.
/// Builder instance.
@@ -10934,58 +10916,58 @@ namespace DynamORM
if (conditions is DynamicColumn)
{
DynamicColumn column = (DynamicColumn)conditions;
-
+
DynamicSchemaColumn? col = column.Schema ?? GetColumnFromSchema(column.ColumnName);
-
+
if (!col.HasValue && SupportSchema)
throw new InvalidOperationException(string.Format("Column '{0}' not found in schema, can't use universal approach.", column));
-
+
if (col.HasValue && col.Value.IsKey)
Where(column);
else
Values(column.ColumnName, column.Value);
-
+
return this;
}
-
+
IDictionary dict = conditions.ToDictionary();
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(conditions.GetType());
-
+
foreach (KeyValuePair con in dict)
{
if (mapper.Ignored.Contains(con.Key))
continue;
-
+
string colName = mapper != null ? mapper.PropertyMap.TryGetValue(con.Key) ?? con.Key : con.Key;
DynamicSchemaColumn? col = GetColumnFromSchema(colName);
-
+
if (!col.HasValue && SupportSchema)
throw new InvalidOperationException(string.Format("Column '{0}' not found in schema, can't use universal approach.", colName));
-
+
if (col.HasValue)
{
colName = col.Value.Name;
-
+
if (col.Value.IsKey)
{
Where(colName, con.Value);
-
+
continue;
}
}
-
+
DynamicPropertyInvoker propMap = mapper.ColumnsMap.TryGetValue(colName.ToLower());
if (propMap == null || propMap.Column == null || !propMap.Column.IsNoUpdate)
Values(colName, con.Value);
}
-
+
return this;
}
-
+
#endregion Update
-
+
#region Values
-
+
///
/// Specifies the columns to update using the dynamic lambda expressions given. Each expression correspond to one
/// column, and can:
@@ -10998,36 +10980,36 @@ namespace DynamORM
{
if (func == null)
throw new ArgumentNullException("Array of specifications cannot be null.");
-
+
int index = -1;
foreach (Func f in func)
{
index++;
if (f == null)
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
-
+
object result = null;
-
+
using (DynamicParser p = DynamicParser.Parse(f))
{
result = p.Result;
-
+
if (result == null)
throw new ArgumentException(string.Format("Specification #{0} resolves to null.", index));
-
+
string main = null;
string value = null;
string str = null;
-
+
// When 'x => x.Table.Column = value' or 'x => x.Column = value'...
if (result is DynamicParser.Node.SetMember)
{
DynamicParser.Node.SetMember node = (DynamicParser.Node.SetMember)result;
-
+
DynamicSchemaColumn? col = GetColumnFromSchema(node.Name);
main = Database.DecorateName(node.Name);
value = Parse(node.Value, ref col, pars: Parameters, nulls: true);
-
+
str = string.Format("{0} = {1}", main, value);
_columns = _columns == null ? str : string.Format("{0}, {1}", _columns, str);
continue;
@@ -11037,7 +11019,7 @@ namespace DynamORM
Values(result);
continue;
}
-
+
// Other specifications are considered invalid...
string err = string.Format("Specification '{0}' is invalid.", result);
str = Parse(result);
@@ -11045,10 +11027,10 @@ namespace DynamORM
throw new ArgumentException(err);
}
}
-
+
return this;
}
-
+
/// Add insert fields.
/// Insert column.
/// Insert value.
@@ -11058,20 +11040,20 @@ namespace DynamORM
if (value is DynamicColumn)
{
DynamicColumn v = (DynamicColumn)value;
-
+
if (string.IsNullOrEmpty(v.ColumnName))
v.ColumnName = column;
-
+
return Values(v);
}
-
+
return Values(new DynamicColumn
{
ColumnName = column,
Value = value,
});
}
-
+
/// Add insert fields.
/// Set insert value as properties and values of an object.
/// Builder instance.
@@ -11081,19 +11063,19 @@ namespace DynamORM
{
DynamicColumn column = (DynamicColumn)o;
DynamicSchemaColumn? col = column.Schema ?? GetColumnFromSchema(column.ColumnName);
-
+
string main = FixObjectName(column.ColumnName, onlyColumn: true);
string value = Parse(column.Value, ref col, pars: Parameters, nulls: true);
-
+
string str = string.Format("{0} = {1}", main, value);
_columns = _columns == null ? str : string.Format("{0}, {1}", _columns, str);
-
+
return this;
}
-
+
IDictionary dict = o.ToDictionary();
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(o.GetType());
-
+
if (mapper != null)
{
foreach (KeyValuePair con in dict)
@@ -11103,14 +11085,14 @@ namespace DynamORM
else
foreach (KeyValuePair con in dict)
Values(con.Key, con.Value);
-
+
return this;
}
-
+
#endregion Values
-
+
#region Where
-
+
///
/// Adds to the 'Where' clause the contents obtained from parsing the dynamic lambda expression given. The condition
/// is parsed to the appropriate syntax, where the specific customs virtual methods supported by the parser are used
@@ -11125,7 +11107,7 @@ namespace DynamORM
{
return this.InternalWhere(func);
}
-
+
/// Add where condition.
/// Condition column with operator and value.
/// Builder instance.
@@ -11133,7 +11115,7 @@ namespace DynamORM
{
return this.InternalWhere(column);
}
-
+
/// Add where condition.
/// Condition column.
/// Condition operator.
@@ -11143,7 +11125,7 @@ namespace DynamORM
{
return this.InternalWhere(column, op, value);
}
-
+
/// Add where condition.
/// Condition column.
/// Condition value.
@@ -11152,7 +11134,7 @@ namespace DynamORM
{
return this.InternalWhere(column, value);
}
-
+
/// Add where condition.
/// Set conditions as properties and values of an object.
/// If true use schema to determine key columns and ignore those which
@@ -11162,27 +11144,27 @@ namespace DynamORM
{
return this.InternalWhere(conditions, schema);
}
-
+
#endregion Where
-
+
#region IExtendedDisposable
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
public override void Dispose()
{
base.Dispose();
-
+
_columns = null;
}
-
+
#endregion IExtendedDisposable
}
}
}
namespace Helpers
- {
+ {
/// Defines methods to support the comparison of collections for equality.
/// The type of collection to compare.
public class CollectionComparer : IEqualityComparer>
@@ -11195,7 +11177,7 @@ namespace DynamORM
{
return Equals(first, second);
}
-
+
/// Returns a hash code for the specified object.
/// The enumerable for which a hash code is to be returned.
/// A hash code for the specified object.
@@ -11203,20 +11185,20 @@ namespace DynamORM
{
return GetHashCode(enumerable);
}
-
+
/// Returns a hash code for the specified object.
/// The enumerable for which a hash code is to be returned.
/// A hash code for the specified object.
public static int GetHashCode(IEnumerable enumerable)
{
int hash = 17;
-
+
foreach (T val in enumerable.OrderBy(x => x))
hash = (hash * 23) + val.GetHashCode();
-
+
return hash;
}
-
+
/// Determines whether the specified objects are equal.
/// The first object of type T to compare.
/// The second object of type T to compare.
@@ -11225,42 +11207,42 @@ namespace DynamORM
{
if ((first == null) != (second == null))
return false;
-
+
if (!object.ReferenceEquals(first, second) && (first != null))
{
if (first.Count() != second.Count())
return false;
-
+
if ((first.Count() != 0) && HaveMismatchedElement(first, second))
return false;
}
-
+
return true;
}
-
+
private static bool HaveMismatchedElement(IEnumerable first, IEnumerable second)
{
int firstCount;
int secondCount;
-
+
Dictionary firstElementCounts = GetElementCounts(first, out firstCount);
Dictionary secondElementCounts = GetElementCounts(second, out secondCount);
-
+
if (firstCount != secondCount)
return true;
-
+
foreach (KeyValuePair kvp in firstElementCounts)
if (kvp.Value != (secondElementCounts.TryGetNullable(kvp.Key) ?? 0))
return true;
-
+
return false;
}
-
+
private static Dictionary GetElementCounts(IEnumerable enumerable, out int nullCount)
{
Dictionary dictionary = new Dictionary();
nullCount = 0;
-
+
foreach (T element in enumerable)
{
if (element == null)
@@ -11271,11 +11253,11 @@ namespace DynamORM
dictionary[element] = ++count;
}
}
-
+
return dictionary;
}
}
-
+
/// Extensions for data reader handling.
public static class DataReaderExtensions
{
@@ -11288,66 +11270,66 @@ namespace DynamORM
{
DataTable schemaTable = r.GetSchemaTable();
DataTable resultTable = new DataTable(name, nameSpace);
-
+
foreach (DataRow col in schemaTable.Rows)
{
dynamic c = col.RowToDynamicUpper();
-
+
DataColumn dataColumn = new DataColumn();
dataColumn.ColumnName = c.COLUMNNAME;
dataColumn.DataType = (Type)c.DATATYPE;
dataColumn.ReadOnly = true;
dataColumn.Unique = c.ISUNIQUE;
-
+
resultTable.Columns.Add(dataColumn);
}
-
+
while (r.Read())
{
DataRow row = resultTable.NewRow();
for (int i = 0; i < resultTable.Columns.Count; i++)
row[i] = r[i];
-
+
resultTable.Rows.Add(row);
}
-
+
return resultTable;
}
}
-
+
/// Framework detection and specific implementations.
public static class FrameworkTools
{
#region Mono or .NET Framework detection
-
+
/// This is pretty simple trick.
private static bool _isMono = Type.GetType("Mono.Runtime") != null;
-
+
/// Gets a value indicating whether application is running under mono runtime.
public static bool IsMono { get { return _isMono; } }
-
+
#endregion Mono or .NET Framework detection
-
+
static FrameworkTools()
{
_frameworkTypeArgumentsGetter = CreateTypeArgumentsGetter();
}
-
+
#region GetGenericTypeArguments
-
+
private static Func> _frameworkTypeArgumentsGetter = null;
-
+
private static Func> CreateTypeArgumentsGetter()
{
// HACK: Creating binders assuming types are correct... this may fail.
if (IsMono)
{
Type binderType = typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly.GetType("Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder");
-
+
if (binderType != null)
{
ParameterExpression param = Expression.Parameter(typeof(InvokeMemberBinder), "o");
-
+
try
{
return Expression.Lambda>>(
@@ -11359,12 +11341,12 @@ namespace DynamORM
catch
{
}
-
+
PropertyInfo prop = binderType.GetProperty("TypeArguments");
-
+
if (!prop.CanRead)
return null;
-
+
return Expression.Lambda>>(
Expression.TypeAs(
Expression.Property(
@@ -11375,16 +11357,16 @@ namespace DynamORM
else
{
Type inter = typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly.GetType("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder");
-
+
if (inter != null)
{
PropertyInfo prop = inter.GetProperty("TypeArguments");
-
+
if (!prop.CanRead)
return null;
-
+
ParameterExpression objParm = Expression.Parameter(typeof(InvokeMemberBinder), "o");
-
+
return Expression.Lambda>>(
Expression.TypeAs(
Expression.Property(
@@ -11392,10 +11374,10 @@ namespace DynamORM
typeof(IList)), objParm).Compile();
}
}
-
+
return null;
}
-
+
/// Extension method allowing to easily extract generic type
/// arguments from assuming that it
/// inherits from
@@ -11412,23 +11394,23 @@ namespace DynamORM
// First try to use delegate if exist
if (_frameworkTypeArgumentsGetter != null)
return _frameworkTypeArgumentsGetter(binder);
-
+
if (_isMono)
{
// HACK: Using Reflection
// In mono this is trivial.
-
+
// First we get field info.
FieldInfo field = binder.GetType().GetField("typeArguments", BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
-
+
// If this was a success get and return it's value
if (field != null)
return field.GetValue(binder) as IList;
else
{
PropertyInfo prop = binder.GetType().GetProperty("TypeArguments");
-
+
// If we have a property, return it's value
if (prop != null)
return prop.GetValue(binder, null) as IList;
@@ -11438,28 +11420,28 @@ namespace DynamORM
{
// HACK: Using Reflection
// In this case, we need more aerobic :D
-
+
// First, get the interface
Type inter = binder.GetType().GetInterface("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder");
-
+
if (inter != null)
{
// Now get property.
PropertyInfo prop = inter.GetProperty("TypeArguments");
-
+
// If we have a property, return it's value
if (prop != null)
return prop.GetValue(binder, null) as IList;
}
}
-
+
// Sadly return null if failed.
return null;
}
-
+
#endregion GetGenericTypeArguments
}
-
+
/// Extends interface.
public interface IExtendedDisposable : IDisposable
{
@@ -11471,7 +11453,7 @@ namespace DynamORM
///
bool IsDisposed { get; }
}
-
+
/// Extends interface.
public interface IFinalizerDisposable : IExtendedDisposable
{
@@ -11480,7 +11462,7 @@ namespace DynamORM
/// If set to true dispose object.
void Dispose(bool disposing);
}
-
+
/// Class containing useful string extensions.
internal static class StringExtensions
{
@@ -11489,20 +11471,20 @@ namespace DynamORM
InvalidMultipartMemberChars = _InvalidMultipartMemberChars.ToCharArray();
InvalidMemberChars = _InvalidMemberChars.ToCharArray();
}
-
+
private static readonly string _InvalidMultipartMemberChars = " +-*/^%[]{}()!\"\\&=?¿";
private static readonly string _InvalidMemberChars = "." + _InvalidMultipartMemberChars;
-
+
///
/// Gets an array with some invalid characters that cannot be used with multipart names for class members.
///
public static char[] InvalidMultipartMemberChars { get; private set; }
-
+
///
/// Gets an array with some invalid characters that cannot be used with names for class members.
///
public static char[] InvalidMemberChars { get; private set; }
-
+
///
/// Provides with an alternate and generic way to obtain an alternate string representation for this instance,
/// applying the following rules:
@@ -11524,34 +11506,34 @@ namespace DynamORM
{
if (obj == null) return nullString;
if (obj is string) return (string)obj;
-
+
Type type = obj.GetType();
if (type.IsEnum) return obj.ToString();
-
+
// If the ToString() method has been overriden (by the type itself, or by its parents), let's use it...
MethodInfo method = type.GetMethod("ToString", Type.EmptyTypes);
if (method.DeclaringType != typeof(object)) return obj.ToString();
-
+
// For alll other cases...
StringBuilder sb = new StringBuilder();
bool first = true;
-
+
// Dictionaries...
if (obj is IDictionary)
{
if (brackets == null || brackets.Length < 2)
brackets = "[]".ToCharArray();
-
+
sb.AppendFormat("{0}", brackets[0]); first = true; foreach (DictionaryEntry kvp in (IDictionary)obj)
{
if (!first) sb.Append(", "); else first = false;
sb.AppendFormat("'{0}'='{1}'", kvp.Key.Sketch(), kvp.Value.Sketch());
}
-
+
sb.AppendFormat("{0}", brackets[1]);
return sb.ToString();
}
-
+
// IEnumerables...
IEnumerator ator = null;
if (obj is IEnumerable)
@@ -11562,7 +11544,7 @@ namespace DynamORM
if (method != null)
ator = (IEnumerator)method.Invoke(obj, null);
}
-
+
if (ator != null)
{
if (brackets == null || brackets.Length < 2) brackets = "[]".ToCharArray();
@@ -11571,27 +11553,27 @@ namespace DynamORM
if (!first) sb.Append(", "); else first = false;
sb.AppendFormat("{0}", ator.Current.Sketch());
}
-
+
sb.AppendFormat("{0}", brackets[1]);
-
+
if (ator is IDisposable)
((IDisposable)ator).Dispose();
-
+
return sb.ToString();
}
-
+
// As a last resort, using the public properties (or fields if needed, or type name)...
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
PropertyInfo[] props = type.GetProperties(flags);
FieldInfo[] infos = type.GetFields(flags);
-
+
if (props.Length == 0 && infos.Length == 0) sb.Append(type.FullName); // Fallback if needed
else
{
if (brackets == null || brackets.Length < 2) brackets = "{}".ToCharArray();
sb.AppendFormat("{0}", brackets[0]);
first = true;
-
+
if (props.Length != 0)
{
foreach (PropertyInfo prop in props)
@@ -11611,14 +11593,14 @@ namespace DynamORM
}
}
}
-
+
sb.AppendFormat("{0}", brackets[1]);
}
-
+
// And returning...
return sb.ToString();
}
-
+
///
/// Returns true if the target string contains any of the characters given.
///
@@ -11629,12 +11611,12 @@ namespace DynamORM
{
if (source == null) throw new ArgumentNullException("source", "Source string cannot be null.");
if (items == null) throw new ArgumentNullException("items", "Array of characters to test cannot be null.");
-
+
if (items.Length == 0) return false; // No characters to validate
int ix = source.IndexOfAny(items);
return ix >= 0 ? true : false;
}
-
+
///
/// Returns a new validated string using the rules given.
///
@@ -11662,14 +11644,14 @@ namespace DynamORM
{
// Assuring a valid descriptor...
if (string.IsNullOrWhiteSpace(desc)) desc = "Source";
-
+
// Validating if null sources are accepted...
if (source == null)
{
if (!canbeNull) throw new ArgumentNullException(desc, string.Format("{0} cannot be null.", desc));
return null;
}
-
+
// Trimming if needed...
if (trim && !(trimStart || trimEnd)) source = source.Trim();
else
@@ -11677,47 +11659,47 @@ namespace DynamORM
if (trimStart) source = source.TrimStart(' ');
if (trimEnd) source = source.TrimEnd(' ');
}
-
+
// Adjusting lenght...
if (minLen > 0)
{
if (padLeft != '\0') source = source.PadLeft(minLen, padLeft);
if (padRight != '\0') source = source.PadRight(minLen, padRight);
}
-
+
if (maxLen > 0)
{
if (padLeft != '\0') source = source.PadLeft(maxLen, padLeft);
if (padRight != '\0') source = source.PadRight(maxLen, padRight);
}
-
+
// Validating emptyness and lenghts...
if (source.Length == 0)
{
if (!canbeEmpty) throw new ArgumentException(string.Format("{0} cannot be empty.", desc));
return string.Empty;
}
-
+
if (minLen >= 0 && source.Length < minLen) throw new ArgumentException(string.Format("Lenght of {0} '{1}' is lower than '{2}'.", desc, source, minLen));
if (maxLen >= 0 && source.Length > maxLen) throw new ArgumentException(string.Format("Lenght of {0} '{1}' is bigger than '{2}'.", desc, source, maxLen));
-
+
// Checking invalid chars...
if (invalidChars != null)
{
int n = source.IndexOfAny(invalidChars);
if (n >= 0) throw new ArgumentException(string.Format("Invalid character '{0}' found in {1} '{2}'.", source[n], desc, source));
}
-
+
// Checking valid chars...
if (validChars != null)
{
int n = validChars.ToString().IndexOfAny(source.ToCharArray());
if (n >= 0) throw new ArgumentException(string.Format("Invalid character '{0}' found in {1} '{2}'.", validChars.ToString()[n], desc, source));
}
-
+
return source;
}
-
+
///
/// Splits the given string with the 'something AS alias' format, returning a tuple containing its 'something' and 'alias' parts.
/// If no alias is detected, then its component in the tuple returned is null and all the contents from the source
@@ -11728,11 +11710,11 @@ namespace DynamORM
public static Tuple SplitSomethingAndAlias(this string source)
{
source = source.Validated("[Something AS Alias]");
-
+
string something = null;
string alias = null;
int n = source.LastIndexOf(" AS ", StringComparison.OrdinalIgnoreCase);
-
+
if (n < 0)
something = source;
else
@@ -11740,10 +11722,10 @@ namespace DynamORM
something = source.Substring(0, n);
alias = source.Substring(n + 4);
}
-
+
return new Tuple(something, alias);
}
-
+
/// Allows to replace parameters inside of string.
/// String containing parameters in format [$ParameterName] .
/// Function that should return value that will be placed in string in place of placed parameter.
@@ -11755,29 +11737,29 @@ namespace DynamORM
int startPos = 0, endPos = 0;
prefix.Validated();
sufix.Validated();
-
+
startPos = stringToFill.IndexOf(prefix, startPos);
while (startPos >= 0)
{
endPos = stringToFill.IndexOf(sufix, startPos + prefix.Length);
int nextStartPos = stringToFill.IndexOf(prefix, startPos + prefix.Length);
-
+
if (endPos > startPos + prefix.Length + 1 && (nextStartPos > endPos || nextStartPos == -1))
{
string paramName = stringToFill.Substring(startPos + prefix.Length, endPos - (startPos + prefix.Length));
-
+
stringToFill = stringToFill
.Remove(startPos, (endPos - startPos) + sufix.Length)
.Insert(startPos, getValue(paramName));
}
-
+
startPos = stringToFill.IndexOf(prefix, startPos + prefix.Length);
}
-
+
return stringToFill;
}
}
-
+
/// Class contains unclassified extensions.
internal static class UnclassifiedExtensions
{
@@ -11799,7 +11781,7 @@ namespace DynamORM
return obj != null && obj != DBNull.Value ?
func(obj) : elseValue;
}
-
+
/// Easy way to use conditional value.
/// Includes .
/// Input object type to check.
@@ -11819,8 +11801,8 @@ namespace DynamORM
return obj != null && obj != DBNull.Value ?
func(obj) : elseFunc != null ? elseFunc() : default(R);
}
-
-#if !NET6_0_OR_GREATER
+
+ #if !NET6_0_OR_GREATER
/// Simple distinct by selector extension.
/// The enumerator of elements distinct by specified selector.
/// Source collection.
@@ -11834,18 +11816,18 @@ namespace DynamORM
if (seenKeys.Add(keySelector(element)))
yield return element;
}
-#endif
+ #endif
}
namespace Dynamics
- {
+ {
///
/// Class able to parse dynamic lambda expressions. Allows to create dynamic logic.
///
public class DynamicParser : IExtendedDisposable
{
#region Node
-
+
///
/// Generic bindable operation where some of its operands is a dynamic argument, or a dynamic member or
/// a method of that argument.
@@ -11854,9 +11836,9 @@ namespace DynamORM
public class Node : IDynamicMetaObjectProvider, IFinalizerDisposable, ISerializable
{
private DynamicParser _parser = null;
-
+
#region MetaNode
-
+
///
/// Represents the dynamic binding and a binding logic of
/// an object participating in the dynamic binding.
@@ -11873,20 +11855,20 @@ namespace DynamORM
: base(parameter, rest, value)
{
}
-
+
// Func was cool but caused memory leaks
private DynamicMetaObject GetBinder(Node node)
{
Node o = (Node)this.Value;
node.Parser = o.Parser;
o.Parser.Last = node;
-
+
ParameterExpression p = Expression.Variable(typeof(Node), "ret");
BlockExpression exp = Expression.Block(new ParameterExpression[] { p }, Expression.Assign(p, Expression.Constant(node)));
-
+
return new MetaNode(exp, this.Restrictions, node);
}
-
+
///
/// Performs the binding of the dynamic get member operation.
///
@@ -11898,7 +11880,7 @@ namespace DynamORM
{
return GetBinder(new GetMember((Node)this.Value, binder.Name));
}
-
+
///
/// Performs the binding of the dynamic set member operation.
///
@@ -11911,7 +11893,7 @@ namespace DynamORM
{
return GetBinder(new SetMember((Node)this.Value, binder.Name, value.Value));
}
-
+
///
/// Performs the binding of the dynamic get index operation.
///
@@ -11924,7 +11906,7 @@ namespace DynamORM
{
return GetBinder(new GetIndex((Node)this.Value, MetaList2List(indexes)));
}
-
+
///
/// Performs the binding of the dynamic set index operation.
///
@@ -11938,7 +11920,7 @@ namespace DynamORM
{
return GetBinder(new SetIndex((Node)this.Value, MetaList2List(indexes), value.Value));
}
-
+
///
/// Performs the binding of the dynamic invoke operation.
///
@@ -11951,7 +11933,7 @@ namespace DynamORM
{
return GetBinder(new Invoke((Node)this.Value, MetaList2List(args)));
}
-
+
///
/// Performs the binding of the dynamic invoke member operation.
///
@@ -11964,7 +11946,7 @@ namespace DynamORM
{
return GetBinder(new Method((Node)this.Value, binder.Name, MetaList2List(args)));
}
-
+
///
/// Performs the binding of the dynamic binary operation.
///
@@ -11977,7 +11959,7 @@ namespace DynamORM
{
return GetBinder(new Binary((Node)this.Value, binder.Operation, arg.Value));
}
-
+
///
/// Performs the binding of the dynamic unary operation.
///
@@ -11990,20 +11972,20 @@ namespace DynamORM
Node o = (Node)this.Value;
Unary node = new Unary(o, binder.Operation) { Parser = o.Parser };
o.Parser.Last = node;
-
+
// If operation is 'IsTrue' or 'IsFalse', we will return false to keep the engine working...
object ret = node;
if (binder.Operation == ExpressionType.IsTrue) ret = (object)false;
if (binder.Operation == ExpressionType.IsFalse) ret = (object)false;
-
+
ParameterExpression p = Expression.Variable(ret.GetType(), "ret"); // the type is now obtained from "ret"
BlockExpression exp = Expression.Block(
new ParameterExpression[] { p },
Expression.Assign(p, Expression.Constant(ret))); // the expression is now obtained from "ret"
-
+
return new MetaNode(exp, this.Restrictions, node);
}
-
+
///
/// Performs the binding of the dynamic conversion operation.
///
@@ -12016,11 +11998,11 @@ namespace DynamORM
Node o = (Node)this.Value;
Convert node = new Convert(o, binder.ReturnType) { Parser = o.Parser };
o.Parser.Last = node;
-
+
// Reducing the object to return if this is an assignment node...
object ret = o;
bool done = false;
-
+
while (!done)
{
if (ret is SetMember)
@@ -12030,7 +12012,7 @@ namespace DynamORM
else
done = true;
}
-
+
// Creating an instance...
if (binder.ReturnType == typeof(string)) ret = ret.ToString();
else
@@ -12048,31 +12030,31 @@ namespace DynamORM
ret = new object();
}
}
-
+
ParameterExpression p = Expression.Variable(binder.ReturnType, "ret");
BlockExpression exp = Expression.Block(
new ParameterExpression[] { p },
Expression.Assign(p, Expression.Constant(ret, binder.ReturnType))); // specifying binder.ReturnType
-
+
return new MetaNode(exp, this.Restrictions, node);
}
-
+
private static object[] MetaList2List(DynamicMetaObject[] metaObjects)
{
if (metaObjects == null) return null;
-
+
object[] list = new object[metaObjects.Length];
for (int i = 0; i < metaObjects.Length; i++)
list[i] = metaObjects[i].Value;
-
+
return list;
}
}
-
+
#endregion MetaNode
-
+
#region Argument
-
+
///
/// Describe a dynamic argument used in a dynamic lambda expression.
///
@@ -12087,7 +12069,7 @@ namespace DynamORM
: base(name)
{
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12097,7 +12079,7 @@ namespace DynamORM
: base(info, context)
{
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
@@ -12107,11 +12089,11 @@ namespace DynamORM
return Name;
}
}
-
+
#endregion Argument
-
+
#region GetMember
-
+
///
/// Describe a 'get member' operation, as in 'x => x.Member'.
///
@@ -12127,7 +12109,7 @@ namespace DynamORM
: base(host, name)
{
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12137,7 +12119,7 @@ namespace DynamORM
: base(info, context)
{
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
@@ -12147,11 +12129,11 @@ namespace DynamORM
return string.Format("{0}.{1}", Host.Sketch(), Name.Sketch());
}
}
-
+
#endregion GetMember
-
+
#region SetMember
-
+
///
/// Describe a 'set member' operation, as in 'x => x.Member = y'.
///
@@ -12163,7 +12145,7 @@ namespace DynamORM
/// assigned to this instance, or if this instance is disposed.
///
public object Value { get; private set; }
-
+
///
/// Initializes a new instance of the class.
///
@@ -12175,7 +12157,7 @@ namespace DynamORM
{
Value = value;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12187,7 +12169,7 @@ namespace DynamORM
string type = info.GetString("MemberType");
Value = type == "NULL" ? null : info.GetValue("MemberValue", Type.GetType(type));
}
-
+
///
/// Gets the object data.
///
@@ -12198,10 +12180,10 @@ namespace DynamORM
info.AddValue("MemberType", Value == null ? "NULL" : Value.GetType().AssemblyQualifiedName);
if (Value != null)
info.AddValue("MemberValue", Value);
-
+
base.GetObjectData(info, context);
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
@@ -12210,7 +12192,7 @@ namespace DynamORM
return "{DynamicParser::Node::SetMember::Disposed}";
return string.Format("({0}.{1} = {2})", Host.Sketch(), Name.Sketch(), Value.Sketch());
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// If set to true dispose object.
@@ -12227,10 +12209,10 @@ namespace DynamORM
{
if (node.IsNodeAncestor(this))
node.Host = null;
-
+
node.Dispose(disposing);
}
-
+
Value = null;
}
}
@@ -12238,15 +12220,15 @@ namespace DynamORM
{
}
}
-
+
base.Dispose(disposing);
}
}
-
+
#endregion SetMember
-
+
#region GetIndex
-
+
///
/// Describe a 'get indexed' operation, as in 'x => x.Member[...]'.
///
@@ -12255,7 +12237,7 @@ namespace DynamORM
{
/// Gets the indexes.
public object[] Indexes { get; internal set; }
-
+
///
/// Initializes a new instance of the class.
///
@@ -12270,10 +12252,10 @@ namespace DynamORM
throw new ArgumentNullException("indexes", "Indexes array cannot be null.");
if (indexes.Length == 0)
throw new ArgumentException("Indexes array cannot be empty.");
-
+
Indexes = indexes;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12283,7 +12265,7 @@ namespace DynamORM
: base(info, context)
{
int count = (int)info.GetValue("IndexCount", typeof(int));
-
+
if (count != 0)
{
Indexes = new object[count]; for (int i = 0; i < count; i++)
@@ -12294,7 +12276,7 @@ namespace DynamORM
}
}
}
-
+
///
/// Gets the object data.
///
@@ -12308,20 +12290,20 @@ namespace DynamORM
info.AddValue("IndexType" + i, Indexes[i] == null ? "NULL" : Indexes[i].GetType().AssemblyQualifiedName);
if (Indexes[i] != null) info.AddValue("IndexValue" + i, Indexes[i]);
}
-
+
base.GetObjectData(info, context);
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
{
if (IsDisposed)
return "{DynamicParser::Node::GetIndex::Disposed}";
-
+
return string.Format("{0}{1}", Host.Sketch(), Indexes == null ? "[empty]" : Indexes.Sketch());
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// If set to true dispose object.
@@ -12340,29 +12322,29 @@ namespace DynamORM
{
if (node.IsNodeAncestor(this))
node.Host = null;
-
+
node.Dispose(disposing);
}
}
-
+
Array.Clear(Indexes, 0, Indexes.Length);
}
}
catch
{
}
-
+
Indexes = null;
}
-
+
base.Dispose(disposing);
}
}
-
+
#endregion GetIndex
-
+
#region SetIndex
-
+
///
/// Describe a 'set indexed' operation, as in 'x => x.Member[...] = Value'.
///
@@ -12374,7 +12356,7 @@ namespace DynamORM
/// assigned to this instance, or if this instance is disposed.
///
public object Value { get; private set; }
-
+
///
/// Initializes a new instance of the class.
///
@@ -12386,7 +12368,7 @@ namespace DynamORM
{
Value = value;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12398,7 +12380,7 @@ namespace DynamORM
string type = info.GetString("MemberType");
Value = type == "NULL" ? null : info.GetValue("MemberValue", Type.GetType(type));
}
-
+
///
/// Gets the object data.
///
@@ -12408,20 +12390,20 @@ namespace DynamORM
{
info.AddValue("MemberType", Value == null ? "NULL" : Value.GetType().AssemblyQualifiedName);
if (Value != null) info.AddValue("MemberValue", Value);
-
+
base.GetObjectData(info, context);
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
{
if (IsDisposed)
return "{DynamicParser::Node::SetIndex::Disposed}";
-
+
return string.Format("({0}{1} = {2})", Host.Sketch(), Indexes == null ? "[empty]" : Indexes.Sketch(), Value.Sketch());
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// If set to true dispose object.
@@ -12438,10 +12420,10 @@ namespace DynamORM
{
if (node.IsNodeAncestor(this))
node.Host = null;
-
+
node.Dispose(disposing);
}
-
+
Value = null;
}
}
@@ -12449,15 +12431,15 @@ namespace DynamORM
{
}
}
-
+
base.Dispose(disposing);
}
}
-
+
#endregion SetIndex
-
+
#region Invoke
-
+
///
/// Describe a method invocation operation, as in 'x => x.Method(...)".
///
@@ -12466,7 +12448,7 @@ namespace DynamORM
{
/// Gets the arguments.
public object[] Arguments { get; internal set; }
-
+
///
/// Initializes a new instance of the class.
///
@@ -12477,7 +12459,7 @@ namespace DynamORM
{
Arguments = arguments == null || arguments.Length == 0 ? null : arguments;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12487,7 +12469,7 @@ namespace DynamORM
: base(info, context)
{
int count = (int)info.GetValue("ArgumentCount", typeof(int));
-
+
if (count != 0)
{
Arguments = new object[count]; for (int i = 0; i < count; i++)
@@ -12498,7 +12480,7 @@ namespace DynamORM
}
}
}
-
+
///
/// Gets the object data.
///
@@ -12512,10 +12494,10 @@ namespace DynamORM
info.AddValue("ArgumentType" + i, Arguments[i] == null ? "NULL" : Arguments[i].GetType().AssemblyQualifiedName);
if (Arguments[i] != null) info.AddValue("ArgumentValue" + i, Arguments[i]);
}
-
+
base.GetObjectData(info, context);
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// If set to true dispose object.
@@ -12534,39 +12516,39 @@ namespace DynamORM
{
if (node.IsNodeAncestor(this))
node.Host = null;
-
+
node.Dispose(disposing);
}
}
-
+
Array.Clear(Arguments, 0, Arguments.Length);
}
}
catch
{
}
-
+
Arguments = null;
}
-
+
base.Dispose(disposing);
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
{
if (IsDisposed)
return "{DynamicParser::Node::Invoke::Disposed}";
-
+
return string.Format("{0}{1}", Host.Sketch(), Arguments == null ? "()" : Arguments.Sketch(brackets: "()".ToCharArray()));
}
}
-
+
#endregion Invoke
-
+
#region Method
-
+
///
/// Describe a method invocation operation, as in 'x => x.Method(...)".
///
@@ -12575,7 +12557,7 @@ namespace DynamORM
{
/// Gets the arguments.
public object[] Arguments { get; internal set; }
-
+
///
/// Initializes a new instance of the class.
///
@@ -12587,7 +12569,7 @@ namespace DynamORM
{
Arguments = arguments == null || arguments.Length == 0 ? null : arguments;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12597,7 +12579,7 @@ namespace DynamORM
: base(info, context)
{
int count = (int)info.GetValue("ArgumentCount", typeof(int));
-
+
if (count != 0)
{
Arguments = new object[count]; for (int i = 0; i < count; i++)
@@ -12608,7 +12590,7 @@ namespace DynamORM
}
}
}
-
+
///
/// Gets the object data.
///
@@ -12622,20 +12604,20 @@ namespace DynamORM
info.AddValue("ArgumentType" + i, Arguments[i] == null ? "NULL" : Arguments[i].GetType().AssemblyQualifiedName);
if (Arguments[i] != null) info.AddValue("ArgumentValue" + i, Arguments[i]);
}
-
+
base.GetObjectData(info, context);
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
{
if (IsDisposed)
return "{DynamicParser::Node::Method::Disposed}";
-
+
return string.Format("{0}.{1}{2}", Host.Sketch(), Name.Sketch(), Arguments == null ? "()" : Arguments.Sketch(brackets: "()".ToCharArray()));
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// If set to true dispose object.
@@ -12654,29 +12636,29 @@ namespace DynamORM
{
if (node.IsNodeAncestor(this))
node.Host = null;
-
+
node.Dispose(disposing);
}
}
-
+
Array.Clear(Arguments, 0, Arguments.Length);
}
}
catch
{
}
-
+
Arguments = null;
}
-
+
base.Dispose(disposing);
}
}
-
+
#endregion Method
-
+
#region Binary
-
+
///
/// Represents a binary operation between a dynamic element and an arbitrary object, including null ones, as in
/// 'x => (x && null)'. The left operand must be an instance of , whereas the right one
@@ -12687,13 +12669,13 @@ namespace DynamORM
{
/// Gets the operation.
public ExpressionType Operation { get; private set; }
-
+
/// Gets host of the .
public Node Left { get { return Host; } }
-
+
/// Gets the right side value.
public object Right { get; private set; }
-
+
///
/// Initializes a new instance of the class.
///
@@ -12706,7 +12688,7 @@ namespace DynamORM
Operation = operation;
Right = right;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12716,11 +12698,11 @@ namespace DynamORM
: base(info, context)
{
Operation = (ExpressionType)info.GetValue("Operation", typeof(ExpressionType));
-
+
string type = info.GetString("RightType");
Right = type == "NULL" ? null : (Node)info.GetValue("RightItem", Type.GetType(type));
}
-
+
///
/// Gets the object data.
///
@@ -12729,31 +12711,31 @@ namespace DynamORM
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Operation", Operation);
-
+
info.AddValue("RightType", Right == null ? "NULL" : Right.GetType().AssemblyQualifiedName);
if (Right != null)
info.AddValue("RightItem", Right);
-
+
base.GetObjectData(info, context);
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
{
if (IsDisposed)
return "{DynamicParser::Node::Binary::Disposed}";
-
+
return string.Format("({0} {1} {2})", Host.Sketch(), Operation, Right.Sketch());
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// If set to true dispose object.
public override void Dispose(bool disposing)
{
base.Dispose(disposing);
-
+
if (disposing)
{
if (Left != null)
@@ -12761,32 +12743,32 @@ namespace DynamORM
if (Left is Node)
{
Node n = (Node)Left;
-
+
if (!n.IsDisposed)
n.Dispose(disposing);
}
}
-
+
if (Right != null)
{
if (Right is Node)
{
Node n = (Node)Right;
-
+
if (!n.IsDisposed)
n.Dispose(disposing);
}
-
+
Right = null;
}
}
}
}
-
+
#endregion Binary
-
+
#region Unary
-
+
///
/// Represents an unary operation, as in 'x => !x'. The target must be a instance. There
/// is no distinction between pre- and post- version of the same operation.
@@ -12796,10 +12778,10 @@ namespace DynamORM
{
/// Gets the operation.
public ExpressionType Operation { get; private set; }
-
+
/// Gets host of the .
public Node Target { get; private set; }
-
+
///
/// Initializes a new instance of the class.
///
@@ -12811,7 +12793,7 @@ namespace DynamORM
Operation = operation;
Target = target;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12822,7 +12804,7 @@ namespace DynamORM
{
Operation = (ExpressionType)info.GetValue("Operation", typeof(ExpressionType));
}
-
+
///
/// Gets the object data.
///
@@ -12831,20 +12813,20 @@ namespace DynamORM
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Operation", Operation);
-
+
base.GetObjectData(info, context);
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
{
if (IsDisposed)
return "{DynamicParser::Node::Binary::Disposed}";
-
+
return string.Format("({0} {1})", Operation, Host.Sketch());
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// If set to true dispose object.
@@ -12861,10 +12843,10 @@ namespace DynamORM
{
if (node.IsNodeAncestor(this))
node.Host = null;
-
+
node.Dispose(disposing);
}
-
+
Target = null;
}
}
@@ -12872,15 +12854,15 @@ namespace DynamORM
{
}
}
-
+
base.Dispose(disposing);
}
}
-
+
#endregion Unary
-
+
#region Convert
-
+
///
/// Represents a conversion operation, as in 'x => (string)x'.
///
@@ -12889,10 +12871,10 @@ namespace DynamORM
{
/// Gets the new type to which value will be converted.
public Type NewType { get; private set; }
-
+
/// Gets host of the .
public Node Target { get { return Host; } }
-
+
///
/// Initializes a new instance of the class.
///
@@ -12903,7 +12885,7 @@ namespace DynamORM
{
NewType = newType;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12914,7 +12896,7 @@ namespace DynamORM
{
NewType = (Type)info.GetValue("NewType", typeof(Type));
}
-
+
///
/// Gets the object data.
///
@@ -12923,21 +12905,21 @@ namespace DynamORM
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("NewType", NewType);
-
+
base.GetObjectData(info, context);
}
}
-
+
#endregion Convert
-
+
///
/// Gets the name of the member. It might be null if this instance is disposed.
///
public string Name { get; internal set; }
-
+
/// Gets host of the .
public Node Host { get; internal set; }
-
+
/// Gets reference to the parser.
public DynamicParser Parser
{
@@ -12949,7 +12931,7 @@ namespace DynamORM
_parser._allNodes.Add(this);
}
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12957,7 +12939,7 @@ namespace DynamORM
{
IsDisposed = false;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12967,10 +12949,10 @@ namespace DynamORM
{
if (host == null)
throw new ArgumentNullException("host", "Host cannot be null.");
-
+
Host = host;
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12980,7 +12962,7 @@ namespace DynamORM
{
Name = name.Validated("Name");
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -12992,7 +12974,7 @@ namespace DynamORM
{
Name = name.Validated("Name");
}
-
+
///
/// Initializes a new instance of the class.
///
@@ -13001,11 +12983,11 @@ namespace DynamORM
protected Node(SerializationInfo info, StreamingContext context)
{
Name = info.GetString("MemberName");
-
+
string type = info.GetString("HostType");
Host = type == "NULL" ? null : (Node)info.GetValue("HostItem", Type.GetType(type));
}
-
+
/// Returns whether the given node is an ancestor of this instance.
/// The node to test.
/// True if the given node is an ancestor of this instance.
@@ -13014,31 +12996,31 @@ namespace DynamORM
if (node != null)
{
Node parent = Host;
-
+
while (parent != null)
{
if (object.ReferenceEquals(parent, node))
return true;
-
+
parent = parent.Host;
}
}
-
+
return false;
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
{
if (IsDisposed)
return "{DynamicParser::Node::Disposed}";
-
+
return "{DynamicParser::Node::Empty}";
}
-
+
#region Implementation of IDynamicMetaObjectProvider
-
+
/// Returns the responsible
/// for binding operations performed on this object.
/// The expression tree representation of the runtime value.
@@ -13048,26 +13030,26 @@ namespace DynamORM
{
if (IsDisposed)
throw new ObjectDisposedException("DynamicParser.Node");
-
+
return new MetaNode(
parameter,
BindingRestrictions.GetInstanceRestriction(parameter, this),
this);
}
-
+
#endregion Implementation of IDynamicMetaObjectProvider
-
+
#region Implementation of IFinalizerDisposable
-
+
/// Finalizes an instance of the class.
~Node()
{
Dispose(false);
}
-
+
/// Gets a value indicating whether this instance is disposed.
public bool IsDisposed { get; private set; }
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
public virtual void Dispose()
@@ -13075,7 +13057,7 @@ namespace DynamORM
Dispose(true);
GC.SuppressFinalize(this);
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// If set to true dispose object.
@@ -13084,20 +13066,20 @@ namespace DynamORM
if (disposing)
{
IsDisposed = true;
-
+
if (Host != null && !Host.IsDisposed)
Host.Dispose();
-
+
Host = null;
-
+
Parser = null;
}
}
-
+
#endregion Implementation of IFinalizerDisposable
-
+
#region Implementation of ISerializable
-
+
///
/// Populates a with the data needed to serialize the target object.
///
@@ -13107,30 +13089,30 @@ namespace DynamORM
{
if (!string.IsNullOrEmpty(Name))
info.AddValue("MemberName", Name);
-
+
info.AddValue("HostType", Host == null ? "NULL" : Host.GetType().AssemblyQualifiedName);
if (Host != null)
info.AddValue("HostItem", Host);
}
-
+
#endregion Implementation of ISerializable
}
-
+
#endregion Node
-
+
#region Data
-
+
private List _arguments = new List();
private List _allNodes = new List();
private object _uncertainResult;
-
+
#endregion Data
-
+
#region Properties
-
+
/// Gets the last node (root of the tree).
public Node Last { get; internal set; }
-
+
///
/// Gets an enumeration containing the dynamic arguments used in the dynamic lambda expression parsed.
///
@@ -13141,15 +13123,15 @@ namespace DynamORM
List list = new List();
if (!IsDisposed && _arguments != null)
list.AddRange(_arguments);
-
+
foreach (Node.Argument arg in list)
yield return arg;
-
+
list.Clear();
list = null;
}
}
-
+
///
/// Gets the number of dynamic arguments used in the dynamic lambda expression parsed.
///
@@ -13157,7 +13139,7 @@ namespace DynamORM
{
get { return _arguments == null ? 0 : _arguments.Count; }
}
-
+
///
/// Gets the result of the parsing of the dynamic lambda expression. This result can be either an arbitrary object,
/// including null, if the expression resolves to it, or an instance of the class that
@@ -13167,9 +13149,9 @@ namespace DynamORM
{
get { return _uncertainResult ?? Last; }
}
-
+
#endregion Properties
-
+
private DynamicParser(Delegate f)
{
// I know this can be almost a one liner
@@ -13186,7 +13168,7 @@ namespace DynamORM
else
throw new ArgumentException(string.Format("Argument '{0}' must be dynamic.", p.Name));
}
-
+
try
{
_uncertainResult = f.DynamicInvoke(_arguments.ToArray());
@@ -13197,7 +13179,7 @@ namespace DynamORM
else throw e;
}
}
-
+
///
/// Parses the dynamic lambda expression given in the form of a delegate, and returns a new instance of the
/// class that holds the dynamic arguments used in the dynamic lambda expression, and
@@ -13209,19 +13191,19 @@ namespace DynamORM
{
return new DynamicParser(f);
}
-
+
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString()
{
if (IsDisposed)
return "{DynamicParser::Disposed}";
-
+
StringBuilder sb = new StringBuilder();
-
+
sb.Append("(");
bool first = true;
-
+
if (_arguments != null)
{
foreach (Node.Argument arg in _arguments)
@@ -13230,62 +13212,62 @@ namespace DynamORM
sb.Append(arg);
}
}
-
+
sb.Append(")");
-
+
sb.AppendFormat(" => {0}", Result.Sketch());
-
+
return sb.ToString();
}
-
+
#region Implementation of IExtendedDisposable
-
+
/// Gets a value indicating whether this instance is disposed.
public bool IsDisposed { get; private set; }
-
+
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
public void Dispose()
{
IsDisposed = true;
-
+
if (_uncertainResult != null)
{
if (_uncertainResult is Node)
((Node)_uncertainResult).Dispose();
-
+
_uncertainResult = null;
}
-
+
if (Last != null)
{
if (!Last.IsDisposed)
Last.Dispose();
-
+
Last = null;
}
-
+
if (_arguments != null)
{
_arguments.ForEach(x => { if (!x.IsDisposed) x.Dispose(); });
-
+
_arguments.Clear();
_arguments = null;
}
-
+
if (_allNodes != null)
{
_allNodes.ForEach(x => { if (!x.IsDisposed) x.Dispose(); });
-
+
_allNodes.Clear();
_allNodes = null;
}
}
-
+
#endregion Implementation of IExtendedDisposable
}
-
+
/// Class that allows to use interfaces as dynamic objects.
/// Type of class to proxy.
/// This is temporary solution. Which allows to use builders as a dynamic type.
@@ -13295,7 +13277,7 @@ namespace DynamORM
private Type _type;
private Dictionary _properties;
private Dictionary _methods;
-
+
///
/// Initializes a new instance of the class.
///
@@ -13305,18 +13287,18 @@ namespace DynamORM
{
if (proxiedObject == null)
throw new ArgumentNullException("proxiedObject");
-
+
_proxy = proxiedObject;
_type = typeof(T);
-
+
DynamicTypeMap mapper = Mapper.DynamicMapperCache.GetMapper();
-
+
_properties = mapper
.ColumnsMap
.ToDictionary(
k => k.Value.Name,
v => v.Value);
-
+
_methods = GetAllMembers(_type)
.Where(x => x is MethodInfo)
.Cast()
@@ -13331,7 +13313,7 @@ namespace DynamORM
Type type = v.ReturnType == typeof(void) ?
Expression.GetActionType(v.GetParameters().Select(t => t.ParameterType).ToArray()) :
Expression.GetDelegateType(v.GetParameters().Select(t => t.ParameterType).Concat(new[] { v.ReturnType }).ToArray());
-
+
return Delegate.CreateDelegate(type, _proxy, v.Name);
}
catch (ArgumentException)
@@ -13340,7 +13322,7 @@ namespace DynamORM
}
});
}
-
+
/// Provides implementation for type conversion operations.
/// Classes derived from the
/// class can override this method to specify dynamic behavior for
@@ -13365,17 +13347,17 @@ namespace DynamORM
result = _proxy;
return true;
}
-
+
if (_proxy != null &&
binder.Type.IsAssignableFrom(_proxy.GetType()))
{
result = _proxy;
return true;
}
-
+
return base.TryConvert(binder, out result);
}
-
+
/// Provides the implementation for operations that get member
/// values. Classes derived from the
/// class can override this method to specify dynamic behavior for
@@ -13400,9 +13382,9 @@ namespace DynamORM
try
{
DynamicPropertyInvoker prop = _properties.TryGetValue(binder.Name);
-
+
result = prop.NullOr(p => p.Get.NullOr(g => g(_proxy), null), null);
-
+
return prop != null && prop.Get != null;
}
catch (Exception ex)
@@ -13410,7 +13392,7 @@ namespace DynamORM
throw new InvalidOperationException(string.Format("Cannot get member {0}", binder.Name), ex);
}
}
-
+
/// Provides the implementation for operations that set member
/// values. Classes derived from the
/// class can override this method to specify dynamic behavior for operations
@@ -13435,13 +13417,13 @@ namespace DynamORM
try
{
DynamicPropertyInvoker prop = _properties.TryGetValue(binder.Name);
-
+
if (prop != null && prop.Setter != null)
{
prop.Set(_proxy, value);
return true;
}
-
+
return false;
}
catch (Exception ex)
@@ -13449,7 +13431,7 @@ namespace DynamORM
throw new InvalidOperationException(string.Format("Cannot set member {0} to '{1}'", binder.Name, value), ex);
}
}
-
+
/// Provides the implementation for operations that invoke a member.
/// Classes derived from the
/// class can override this method to specify dynamic behavior for
@@ -13475,58 +13457,58 @@ namespace DynamORM
{
return TryInvokeMethod(binder.Name, out result, args) || base.TryInvokeMember(binder, args, out result);
}
-
+
private bool TryInvokeMethod(string name, out object result, object[] args)
{
result = null;
-
+
MethodInfo mi = _methods.Keys
.Where(m => m.Name == name)
.FirstOrDefault(m =>
CompareTypes(m.GetParameters().ToArray(),
args.Select(a => a.GetType()).ToArray()));
-
+
Delegate d = _methods.TryGetValue(mi);
-
+
if (d != null)
{
result = d.DynamicInvoke(CompleteArguments(mi.GetParameters().ToArray(), args));
-
+
if (d.Method.ReturnType == _type && result is T)
result = new DynamicProxy((T)result);
-
+
return true;
}
else if (mi != null)
{
result = mi.Invoke(_proxy, CompleteArguments(mi.GetParameters().ToArray(), args));
-
+
if (mi.ReturnType == _type && result is T)
result = new DynamicProxy((T)result);
-
+
return true;
}
-
+
return false;
}
-
+
private bool CompareTypes(ParameterInfo[] parameters, Type[] types)
{
if (parameters.Length < types.Length || parameters.Count(p => !p.IsOptional) > types.Length)
return false;
-
+
for (int i = 0; i < types.Length; i++)
if (types[i] != parameters[i].ParameterType && !parameters[i].ParameterType.IsAssignableFrom(types[i]))
return false;
-
+
return true;
}
-
+
private object[] CompleteArguments(ParameterInfo[] parameters, object[] arguments)
{
return arguments.Concat(parameters.Skip(arguments.Length).Select(p => p.DefaultValue)).ToArray();
}
-
+
private IEnumerable GetAllMembers(Type type)
{
if (type.IsInterface)
@@ -13534,47 +13516,47 @@ namespace DynamORM
List members = new List();
List considered = new List();
Queue queue = new Queue();
-
+
considered.Add(type);
queue.Enqueue(type);
-
+
while (queue.Count > 0)
{
Type subType = queue.Dequeue();
foreach (Type subInterface in subType.GetInterfaces())
{
if (considered.Contains(subInterface)) continue;
-
+
considered.Add(subInterface);
queue.Enqueue(subInterface);
}
-
+
MemberInfo[] typeProperties = subType.GetMembers(
BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.Instance);
-
+
IEnumerable newPropertyInfos = typeProperties
.Where(x => !members.Contains(x));
-
+
members.InsertRange(0, newPropertyInfos);
}
-
+
return members;
}
-
+
return type.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance);
}
-
+
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
public void Dispose()
{
object res;
TryInvokeMethod("Dispose", out res, new object[] { });
-
+
_properties.Clear();
-
+
_methods = null;
_properties = null;
_type = null;
@@ -13585,57 +13567,57 @@ namespace DynamORM
}
namespace Mapper
- {
+ {
/// Allows to add table name to class.
[AttributeUsage(AttributeTargets.Property)]
public class ColumnAttribute : Attribute
{
/// Gets or sets name.
public string Name { get; set; }
-
+
/// Gets or sets column type.
/// Used when overriding schema.
public DbType? Type { get; set; }
-
+
/// Gets or sets a value indicating whether column is a key.
public bool IsKey { get; set; }
-
+
/// Gets or sets a value indicating whether column allows null or not.
/// Information only.
public bool AllowNull { get; set; }
-
+
/// Gets or sets a value indicating whether column should have unique value.
/// Used when overriding schema.
public bool? IsUnique { get; set; }
-
+
/// Gets or sets column size.
/// Used when overriding schema.
public int? Size { get; set; }
-
+
/// Gets or sets column precision.
/// Used when overriding schema.
public byte? Precision { get; set; }
-
+
/// Gets or sets column scale.
/// Used when overriding schema.
public byte? Scale { get; set; }
-
+
/// Gets or sets a value indicating whether this column is no allowed to be inserted.
/// This is only a suggestion to automated mapping.
public bool IsNoInsert { get; set; }
-
+
/// Gets or sets a value indicating whether this column is no allowed to be updated.
/// This is only a suggestion to automated mapping.
public bool IsNoUpdate { get; set; }
-
+
#region Constructors
-
+
/// Initializes a new instance of the class.
public ColumnAttribute()
{
AllowNull = true;
}
-
+
/// Initializes a new instance of the class.
/// Name of column.
public ColumnAttribute(string name)
@@ -13643,7 +13625,7 @@ namespace DynamORM
{
Name = name;
}
-
+
/// Initializes a new instance of the class.
/// Set column as a key column.
public ColumnAttribute(bool isKey)
@@ -13651,7 +13633,7 @@ namespace DynamORM
{
IsKey = isKey;
}
-
+
/// Initializes a new instance of the class.
/// Name of column.
/// Set column as a key column.
@@ -13660,7 +13642,7 @@ namespace DynamORM
{
IsKey = isKey;
}
-
+
/// Initializes a new instance of the class.
/// Set column as a key column.
/// Set column type.
@@ -13669,7 +13651,7 @@ namespace DynamORM
{
Type = type;
}
-
+
/// Initializes a new instance of the class.
/// Name of column.
/// Set column as a key column.
@@ -13679,7 +13661,7 @@ namespace DynamORM
{
Type = type;
}
-
+
/// Initializes a new instance of the class.
/// Name of column.
/// Set column as a key column.
@@ -13690,7 +13672,7 @@ namespace DynamORM
{
Size = size;
}
-
+
/// Initializes a new instance of the class.
/// Name of column.
/// Set column as a key column.
@@ -13703,7 +13685,7 @@ namespace DynamORM
Precision = precision;
Scale = scale;
}
-
+
/// Initializes a new instance of the class.
/// Name of column.
/// Set column as a key column.
@@ -13716,7 +13698,7 @@ namespace DynamORM
{
Size = size;
}
-
+
/// Initializes a new instance of the class.
/// Name of column.
/// Set column as a key column.
@@ -13730,10 +13712,10 @@ namespace DynamORM
{
IsUnique = isUnique;
}
-
+
#endregion Constructors
}
-
+
/// Type cast helper.
public static class DynamicCast
{
@@ -13744,7 +13726,7 @@ namespace DynamORM
{
return type.IsValueType ? TypeDefaults.GetOrAdd(type, t => Activator.CreateInstance(t)) : null;
}
-
+
/// Casts the object to this type.
/// The type to which cast value.
/// The value to cast.
@@ -13753,23 +13735,23 @@ namespace DynamORM
{
return GetConverter(type, val)(val);
}
-
+
private static readonly ConcurrentDictionary TypeDefaults = new ConcurrentDictionary();
private static readonly ConcurrentDictionary> TypeAsCasts = new ConcurrentDictionary>();
private static readonly ConcurrentDictionary> TypeConvert = new ConcurrentDictionary>();
private static readonly ParameterExpression ConvParameter = Expression.Parameter(typeof(object), "val");
-
+
[MethodImpl(MethodImplOptions.Synchronized)]
private static Func GetConverter(Type targetType, object val)
{
Func fn;
-
+
if (!targetType.IsValueType && !val.GetType().IsValueType)
{
if (!TypeAsCasts.TryGetValue(targetType, out fn))
{
UnaryExpression instanceCast = Expression.TypeAs(ConvParameter, targetType);
-
+
fn = Expression.Lambda>(Expression.TypeAs(instanceCast, typeof(object)), ConvParameter).Compile();
TypeAsCasts.AddOrUpdate(targetType, fn, (t, f) => fn);
}
@@ -13780,51 +13762,51 @@ namespace DynamORM
var key = new PairOfTypes(fromType, targetType);
if (TypeConvert.TryGetValue(key, out fn))
return fn;
-
+
fn = (Func)Expression.Lambda(Expression.Convert(Expression.Convert(Expression.Convert(ConvParameter, fromType), targetType), typeof(object)), ConvParameter).Compile();
TypeConvert.AddOrUpdate(key, fn, (t, f) => fn);
}
-
+
return fn;
}
-
+
private class PairOfTypes
{
private readonly Type _first;
private readonly Type _second;
-
+
public PairOfTypes(Type first, Type second)
{
this._first = first;
this._second = second;
}
-
+
public override int GetHashCode()
{
return (31 * _first.GetHashCode()) + _second.GetHashCode();
}
-
+
public override bool Equals(object obj)
{
if (obj == this)
return true;
-
+
var other = obj as PairOfTypes;
if (other == null)
return false;
-
+
return _first.Equals(other._first)
&& _second.Equals(other._second);
}
}
}
-
+
/// Class with mapper cache.
public static class DynamicMapperCache
{
private static readonly object SyncLock = new object();
private static Dictionary _cache = new Dictionary();
-
+
/// Get type mapper.
/// Type of mapper.
/// Type mapper.
@@ -13832,7 +13814,7 @@ namespace DynamORM
{
return GetMapper(typeof(T));
}
-
+
/// Get type mapper.
/// Type of mapper.
/// Type mapper.
@@ -13842,24 +13824,24 @@ namespace DynamORM
return null;
/*if (type.IsAnonymous())
return null;*/
-
+
DynamicTypeMap mapper = null;
-
+
lock (SyncLock)
{
if (!_cache.TryGetValue(type, out mapper))
{
mapper = new DynamicTypeMap(type);
-
+
if (mapper != null)
_cache.Add(type, mapper);
}
}
-
+
return mapper;
}
}
-
+
/// Exception thrown when mapper fails to set or get a property.
///
public class DynamicMapperException : Exception
@@ -13868,20 +13850,20 @@ namespace DynamORM
public DynamicMapperException()
{
}
-
+
/// Initializes a new instance of the class.
/// The message that describes the error.
public DynamicMapperException(string message) : base(message)
{
}
-
+
/// Initializes a new instance of the class.
/// The error message that explains the reason for the exception.
/// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.
public DynamicMapperException(string message, Exception innerException) : base(message, innerException)
{
}
-
+
/// Initializes a new instance of the class.
/// The that holds the serialized object data about the exception being thrown.
/// The that contains contextual information about the source or destination.
@@ -13889,52 +13871,52 @@ namespace DynamORM
{
}
}
-
+
/// Dynamic property invoker.
public class DynamicPropertyInvoker
{
internal class ParameterSpec
{
public string Name { get; set; }
-
+
public DbType Type { get; set; }
-
+
public int Ordinal { get; set; }
}
-
+
/// Gets the array type of property if main type is a form of collection.
public Type ArrayType { get; private set; }
-
+
/// Gets a value indicating whether this property is in fact a generic list.
public bool IsGnericEnumerable { get; private set; }
-
+
/// Gets the type of property.
public Type Type { get; private set; }
-
+
/// Gets value getter.
public Func Get { get; private set; }
-
+
/// Gets value setter.
public Action Setter { get; private set; }
-
+
/// Gets the property information.
public PropertyInfo PropertyInfo { get; private set; }
-
+
/// Gets name of property.
public string Name { get; private set; }
-
+
/// Gets type column description.
public ColumnAttribute Column { get; private set; }
-
+
/// Gets type list of property requirements.
public List Requirements { get; private set; }
-
+
/// Gets a value indicating whether this is ignored in some cases.
public bool Ignore { get; private set; }
-
+
/// Gets a value indicating whether this instance hold data contract type.
public bool IsDataContract { get; private set; }
-
+
/// Initializes a new instance of the class.
/// Property info to be invoked in the future.
/// Column attribute if exist.
@@ -13943,45 +13925,45 @@ namespace DynamORM
PropertyInfo = property;
Name = property.Name;
Type = property.PropertyType;
-
+
object[] ignore = property.GetCustomAttributes(typeof(IgnoreAttribute), false);
Requirements = property.GetCustomAttributes(typeof(RequiredAttribute), false).Cast().ToList();
-
+
Ignore = ignore != null && ignore.Length > 0;
-
+
IsGnericEnumerable = Type.IsGenericEnumerable();
-
+
ArrayType = Type.IsArray ? Type.GetElementType() :
IsGnericEnumerable ? Type.GetGenericArguments().First() :
Type;
-
+
IsDataContract = ArrayType.GetCustomAttributes(false).Any(x => x.GetType().Name == "DataContractAttribute");
-
+
if (ArrayType.IsArray)
throw new InvalidOperationException("Jagged arrays are not supported");
-
+
if (ArrayType.IsGenericEnumerable())
throw new InvalidOperationException("Enumerables of enumerables are not supported");
-
+
Column = attr;
-
+
if (attr != null && attr.AllowNull && Type.IsNullableType())
attr.AllowNull = false;
-
+
if (property.CanRead)
Get = CreateGetter(property);
-
+
if (property.CanWrite)
Setter = CreateSetter(property);
}
-
+
private Func CreateGetter(PropertyInfo property)
{
if (!property.CanRead)
return null;
-
+
ParameterExpression objParm = Expression.Parameter(typeof(object), "o");
-
+
return Expression.Lambda>(
Expression.Convert(
Expression.Property(
@@ -13989,15 +13971,15 @@ namespace DynamORM
property.Name),
typeof(object)), objParm).Compile();
}
-
+
private Action CreateSetter(PropertyInfo property)
{
if (!property.CanWrite)
return null;
-
+
ParameterExpression objParm = Expression.Parameter(typeof(object), "o");
ParameterExpression valueParm = Expression.Parameter(typeof(object), "value");
-
+
return Expression.Lambda>(
Expression.Assign(
Expression.Property(
@@ -14006,14 +13988,14 @@ namespace DynamORM
Expression.Convert(valueParm, property.PropertyType)),
objParm, valueParm).Compile();
}
-
+
/// Sets the specified value to destination object.
/// The destination object.
/// The value.
public void Set(object dest, object val, bool byProperty = false)
{
object value = null;
-
+
try
{
if (!Type.IsAssignableFrom(val.GetType()))
@@ -14025,9 +14007,9 @@ namespace DynamORM
if (val is IEnumerable)
{
var lst = (val as IEnumerable).Select(x => GetElementVal(ArrayType, x, byProperty)).ToList();
-
+
value = Array.CreateInstance(ArrayType, lst.Count);
-
+
int i = 0;
foreach (var e in lst)
((Array)value).SetValue(e, i++);
@@ -14046,7 +14028,7 @@ namespace DynamORM
}
else
value = val;
-
+
Setter(dest, value);
}
catch (Exception ex)
@@ -14057,12 +14039,12 @@ namespace DynamORM
ex);
}
}
-
+
private object GetElementVal(System.Type etype, object val, bool byProperty)
{
bool nullable = etype.IsGenericType && etype.GetGenericTypeDefinition() == typeof(Nullable<>);
Type type = Nullable.GetUnderlyingType(etype) ?? etype;
-
+
if (val == null && type.IsValueType)
{
if (nullable)
@@ -14083,7 +14065,7 @@ namespace DynamORM
{
if (nullable)
return null;
-
+
throw;
}
else if (Type == typeof(string) && val.GetType() == typeof(Guid))
@@ -14103,7 +14085,7 @@ namespace DynamORM
{
if (byProperty)
return val.MapByProperty(type);
-
+
return val.Map(type);
}
else
@@ -14115,108 +14097,108 @@ namespace DynamORM
{
if (nullable)
return null;
-
+
throw;
}
}
-
+
#region Type command cache
-
+
internal ParameterSpec InsertCommandParameter { get; set; }
-
+
internal ParameterSpec UpdateCommandParameter { get; set; }
-
+
internal ParameterSpec DeleteCommandParameter { get; set; }
-
+
#endregion Type command cache
}
-
+
/// Represents type columnMap.
public class DynamicTypeMap
{
/// Gets mapper destination type creator.
public Type Type { get; private set; }
-
+
/// Gets type table description.
public TableAttribute Table { get; private set; }
-
+
/// Gets object creator.
public Func Creator { get; private set; }
-
+
/// Gets map of columns to properties.
/// Key: Column name (lower), Value: .
public Dictionary ColumnsMap { get; private set; }
-
+
/// Gets map of properties to column.
/// Key: Property name, Value: Column name.
public Dictionary PropertyMap { get; private set; }
-
+
/// Gets list of ignored properties.
public List Ignored { get; private set; }
-
+
/// Initializes a new instance of the class.
/// Type to which columnMap objects.
public DynamicTypeMap(Type type)
{
Type = type;
-
+
object[] attr = type.GetCustomAttributes(typeof(TableAttribute), false);
-
+
if (attr != null && attr.Length > 0)
Table = (TableAttribute)attr[0];
-
+
Creator = CreateCreator();
CreateColumnAndPropertyMap();
}
-
+
private void CreateColumnAndPropertyMap()
{
Dictionary columnMap = new Dictionary();
Dictionary propertyMap = new Dictionary();
List ignored = new List();
-
+
foreach (PropertyInfo pi in GetAllMembers(Type).Where(x => x is PropertyInfo).Cast())
{
// Skip indexers
if (pi.GetIndexParameters().Any())
continue;
-
+
ColumnAttribute attr = null;
-
+
object[] attrs = pi.GetCustomAttributes(typeof(ColumnAttribute), true);
-
+
if (attrs != null && attrs.Length > 0)
attr = (ColumnAttribute)attrs[0];
-
+
string col = attr == null || string.IsNullOrEmpty(attr.Name) ? pi.Name : attr.Name;
-
+
DynamicPropertyInvoker val = new DynamicPropertyInvoker(pi, attr);
columnMap.Add(col.ToLower(), val);
-
+
propertyMap.Add(pi.Name, col);
-
+
if (val.Ignore)
ignored.Add(pi.Name);
}
-
+
ColumnsMap = columnMap;
PropertyMap = propertyMap;
-
+
Ignored = ignored; ////columnMap.Where(i => i.Value.Ignore).Select(i => i.Value.Name).ToList();
}
-
+
private Func