This commit is contained in:
@@ -44,9 +44,10 @@ namespace DynamORM.Builders
|
||||
/// <para>- Resolve to a string, in this case a '=' must appear in the string.</para>
|
||||
/// <para>- Resolve to a expression with the form: 'x => x.Column = Value'.</para>
|
||||
/// </summary>
|
||||
/// <param name="fn">The specifications.</param>
|
||||
/// <param name="func">The specifications.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
IDynamicInsertQueryBuilder Insert(params Func<dynamic, object>[] func);
|
||||
IDynamicInsertQueryBuilder Values(Func<dynamic, object> fn, params Func<dynamic, object>[] func);
|
||||
|
||||
/// <summary>Add insert fields.</summary>
|
||||
/// <param name="column">Insert column.</param>
|
||||
@@ -56,9 +57,7 @@ namespace DynamORM.Builders
|
||||
|
||||
/// <summary>Add insert fields.</summary>
|
||||
/// <param name="o">Set insert value as properties and values of an object.</param>
|
||||
/// <param name="schema">If <c>true</c> use schema to determine key columns and ignore those which
|
||||
/// aren't keys.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicInsertQueryBuilder Insert(object o, bool schema = false);
|
||||
IDynamicInsertQueryBuilder Insert(object o);
|
||||
}
|
||||
}
|
||||
@@ -63,9 +63,10 @@ namespace DynamORM.Builders
|
||||
/// <para>- Generic expression: 'x => x( expression ).As( x.Alias )', where the alias part is mandatory. In this
|
||||
/// case the alias is not annotated.</para>
|
||||
/// </summary>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
IDynamicSelectQueryBuilder From(params Func<dynamic, object>[] func);
|
||||
IDynamicSelectQueryBuilder From(Func<dynamic, object> fn, params Func<dynamic, object>[] func);
|
||||
|
||||
/// <summary>
|
||||
/// Adds to the 'Join' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
|
||||
@@ -139,21 +140,22 @@ namespace DynamORM.Builders
|
||||
/// <para>- Generic expression: 'x => x( expression ).As( x.Alias )', where the alias part is mandatory. In this case
|
||||
/// the alias is not annotated.</para>
|
||||
/// </summary>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
IDynamicSelectQueryBuilder Select(params Func<dynamic, object>[] func);
|
||||
IDynamicSelectQueryBuilder Select(Func<dynamic, object> fn, params Func<dynamic, object>[] func);
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to add to object.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicSelectQueryBuilder Select(params DynamicColumn[] columns);
|
||||
IDynamicSelectQueryBuilder SelectColumn(params DynamicColumn[] columns);
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to add to object.</param>
|
||||
/// <remarks>Column format consist of <c>Column Name</c>, <c>Alias</c> and
|
||||
/// <c>Aggregate function</c> in this order separated by '<c>:</c>'.</remarks>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicSelectQueryBuilder Select(params string[] columns);
|
||||
IDynamicSelectQueryBuilder SelectColumn(params string[] columns);
|
||||
|
||||
#endregion Select
|
||||
|
||||
@@ -162,21 +164,22 @@ namespace DynamORM.Builders
|
||||
/// <summary>
|
||||
/// Adds to the 'Group By' clause the contents obtained from from parsing the dynamic lambda expression given.
|
||||
/// </summary>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
IDynamicSelectQueryBuilder GroupBy(params Func<dynamic, object>[] func);
|
||||
IDynamicSelectQueryBuilder GroupBy(Func<dynamic, object> fn, params Func<dynamic, object>[] func);
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to group by.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicSelectQueryBuilder GroupBy(params DynamicColumn[] columns);
|
||||
IDynamicSelectQueryBuilder GroupByColumn(params DynamicColumn[] columns);
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to group by.</param>
|
||||
/// <remarks>Column format consist of <c>Column Name</c> and
|
||||
/// <c>Alias</c> in this order separated by '<c>:</c>'.</remarks>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicSelectQueryBuilder GroupBy(params string[] columns);
|
||||
IDynamicSelectQueryBuilder GroupByColumn(params string[] columns);
|
||||
|
||||
#endregion GroupBy
|
||||
|
||||
@@ -188,21 +191,22 @@ namespace DynamORM.Builders
|
||||
/// to specify the direction. If no virtual method is used, the default is ascending order. You can also use the
|
||||
/// shorter versions <code>Asc()</code> and <code>Desc()</code>.
|
||||
/// </summary>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
IDynamicSelectQueryBuilder OrderBy(params Func<dynamic, object>[] func);
|
||||
IDynamicSelectQueryBuilder OrderBy(Func<dynamic, object> fn, params Func<dynamic, object>[] func);
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to order by.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicSelectQueryBuilder OrderBy(params DynamicColumn[] columns);
|
||||
IDynamicSelectQueryBuilder OrderByColumn(params DynamicColumn[] columns);
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to order by.</param>
|
||||
/// <remarks>Column format consist of <c>Column Name</c> and
|
||||
/// <c>Alias</c> in this order separated by '<c>:</c>'.</remarks>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicSelectQueryBuilder OrderBy(params string[] columns);
|
||||
IDynamicSelectQueryBuilder OrderByColumn(params string[] columns);
|
||||
|
||||
#endregion OrderBy
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace DynamORM.Builders
|
||||
/// </summary>
|
||||
/// <param name="func">The specifications.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
IDynamicUpdateQueryBuilder Values(params Func<dynamic, object>[] func);
|
||||
IDynamicUpdateQueryBuilder Set(params Func<dynamic, object>[] func);
|
||||
|
||||
/// <summary>Add insert fields.</summary>
|
||||
/// <param name="column">Insert column.</param>
|
||||
|
||||
@@ -80,62 +80,67 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <para>- Resolve to a string, in this case a '=' must appear in the string.</para>
|
||||
/// <para>- Resolve to a expression with the form: 'x => x.Column = Value'.</para>
|
||||
/// </summary>
|
||||
/// <param name="fn">The specifications.</param>
|
||||
/// <param name="func">The specifications.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicInsertQueryBuilder Insert(params Func<dynamic, object>[] func)
|
||||
public virtual IDynamicInsertQueryBuilder Values(Func<dynamic, object> fn, params Func<dynamic, object>[] func)
|
||||
{
|
||||
if (func == null)
|
||||
if (fn == null)
|
||||
throw new ArgumentNullException("Array of specifications cannot be null.");
|
||||
|
||||
int index = -1;
|
||||
int index = InsertFunc(-1, fn);
|
||||
|
||||
foreach (var f in func)
|
||||
{
|
||||
index++;
|
||||
|
||||
if (f == null)
|
||||
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
|
||||
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var 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)
|
||||
{
|
||||
var node = (DynamicParser.Node.SetMember)result;
|
||||
|
||||
DynamicSchemaColumn? col = GetColumnFromSchema(node.Name);
|
||||
main = Database.DecorateName(node.Name);
|
||||
value = Parse(node.Value, pars: Parameters, nulls: true, columnSchema: col);
|
||||
|
||||
_columns = _columns == null ? main : string.Format("{0}, {1}", _columns, main);
|
||||
_values = _values == null ? value : string.Format("{0}, {1}", _values, value);
|
||||
continue;
|
||||
}
|
||||
else if (!(result is DynamicParser.Node) && !result.GetType().IsValueType)
|
||||
{
|
||||
Insert(result);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Other specifications are considered invalid...
|
||||
var err = string.Format("Specification '{0}' is invalid.", result);
|
||||
str = Parse(result);
|
||||
if (str.Contains("=")) err += " May have you used a '==' instead of a '=' operator?";
|
||||
throw new ArgumentException(err);
|
||||
}
|
||||
}
|
||||
if (func != null)
|
||||
foreach (var f in func)
|
||||
index = InsertFunc(index, f);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private int InsertFunc(int index, Func<dynamic, object> f)
|
||||
{
|
||||
index++;
|
||||
|
||||
if (f == null)
|
||||
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
|
||||
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var 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)
|
||||
{
|
||||
var node = (DynamicParser.Node.SetMember)result;
|
||||
|
||||
DynamicSchemaColumn? col = GetColumnFromSchema(node.Name);
|
||||
main = Database.DecorateName(node.Name);
|
||||
value = Parse(node.Value, pars: Parameters, nulls: true, columnSchema: col);
|
||||
|
||||
_columns = _columns == null ? main : string.Format("{0}, {1}", _columns, main);
|
||||
_values = _values == null ? value : string.Format("{0}, {1}", _values, value);
|
||||
return index;
|
||||
}
|
||||
else if (!(result is DynamicParser.Node) && !result.GetType().IsValueType)
|
||||
{
|
||||
Insert(result);
|
||||
return index;
|
||||
}
|
||||
|
||||
// Other specifications are considered invalid...
|
||||
var err = string.Format("Specification '{0}' is invalid.", result);
|
||||
str = Parse(result);
|
||||
if (str.Contains("=")) err += " May have you used a '==' instead of a '=' operator?";
|
||||
throw new ArgumentException(err);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Add insert fields.</summary>
|
||||
/// <param name="column">Insert column.</param>
|
||||
/// <param name="value">Insert value.</param>
|
||||
@@ -161,10 +166,8 @@ namespace DynamORM.Builders.Implementation
|
||||
|
||||
/// <summary>Add insert fields.</summary>
|
||||
/// <param name="o">Set insert value as properties and values of an object.</param>
|
||||
/// <param name="schema">If <c>true</c> use schema to determine key columns and ignore those which
|
||||
/// aren't keys.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
public virtual IDynamicInsertQueryBuilder Insert(object o, bool schema = false)
|
||||
public virtual IDynamicInsertQueryBuilder Insert(object o)
|
||||
{
|
||||
if (o is DynamicColumn)
|
||||
{
|
||||
|
||||
@@ -251,176 +251,184 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <para>- Generic expression: 'x => x( expression ).As( x.Alias )', where the alias part is mandatory. In this
|
||||
/// case the alias is not annotated.</para>
|
||||
/// </summary>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder From(params Func<dynamic, object>[] func)
|
||||
public virtual IDynamicSelectQueryBuilder From(Func<dynamic, object> fn, params Func<dynamic, object>[] func)
|
||||
{
|
||||
if (func == null)
|
||||
throw new ArgumentNullException("Array of functions cannot be null.");
|
||||
if (fn == null)
|
||||
throw new ArgumentNullException("Array of functions cannot be or contain null.");
|
||||
|
||||
int index = -1;
|
||||
int index = FromFunc(-1, fn);
|
||||
foreach (var f in func)
|
||||
{
|
||||
index++;
|
||||
ITableInfo tableInfo = null;
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var result = parser.Result;
|
||||
|
||||
// If the expression result is string.
|
||||
if (result is string)
|
||||
{
|
||||
var node = (string)result;
|
||||
var tuple = node.SplitSomethingAndAlias();
|
||||
var parts = tuple.Item1.Split('.');
|
||||
tableInfo = new TableInfo(Database,
|
||||
Database.StripName(parts.Last()).Validated("Table"),
|
||||
tuple.Item2.Validated("Alias", canbeNull: true),
|
||||
parts.Length == 2 ? Database.StripName(parts.First()).Validated("Owner", canbeNull: true) : null);
|
||||
}
|
||||
else if (result is Type)
|
||||
{
|
||||
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));
|
||||
|
||||
var 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
|
||||
var node = (DynamicParser.Node)result;
|
||||
|
||||
string owner = null;
|
||||
string main = null;
|
||||
string alias = null;
|
||||
Type type = null;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// 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).Validated("Alias");
|
||||
|
||||
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<dynamic, object>).Cast<Func<dynamic, object>>().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
|
||||
{
|
||||
var invoke = (DynamicParser.Node.Invoke)node;
|
||||
if (invoke.Arguments.Length == 1 && invoke.Arguments[0] is Type)
|
||||
{
|
||||
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));
|
||||
|
||||
var 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) : new TableInfo(Database, type, alias, owner);
|
||||
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);
|
||||
|
||||
_from = string.IsNullOrEmpty(_from) ? sb.ToString() : string.Format("{0}, {1}", _from, sb.ToString());
|
||||
}
|
||||
}
|
||||
index = FromFunc(index, f);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private int FromFunc(int index, Func<dynamic, object> f)
|
||||
{
|
||||
if (f == null)
|
||||
throw new ArgumentNullException("Array of functions cannot be or contain null.");
|
||||
|
||||
index++;
|
||||
ITableInfo tableInfo = null;
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var result = parser.Result;
|
||||
|
||||
// If the expression result is string.
|
||||
if (result is string)
|
||||
{
|
||||
var node = (string)result;
|
||||
var tuple = node.SplitSomethingAndAlias();
|
||||
var parts = tuple.Item1.Split('.');
|
||||
tableInfo = new TableInfo(Database,
|
||||
Database.StripName(parts.Last()).Validated("Table"),
|
||||
tuple.Item2.Validated("Alias", canbeNull: true),
|
||||
parts.Length == 2 ? Database.StripName(parts.First()).Validated("Owner", canbeNull: true) : null);
|
||||
}
|
||||
else if (result is Type)
|
||||
{
|
||||
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));
|
||||
|
||||
var 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
|
||||
var node = (DynamicParser.Node)result;
|
||||
|
||||
string owner = null;
|
||||
string main = null;
|
||||
string alias = null;
|
||||
Type type = null;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// 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).Validated("Alias");
|
||||
|
||||
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<dynamic, object>).Cast<Func<dynamic, object>>().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
|
||||
{
|
||||
var invoke = (DynamicParser.Node.Invoke)node;
|
||||
if (invoke.Arguments.Length == 1 && invoke.Arguments[0] is Type)
|
||||
{
|
||||
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));
|
||||
|
||||
var 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) : new TableInfo(Database, type, alias, owner);
|
||||
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);
|
||||
|
||||
_from = string.IsNullOrEmpty(_from) ? sb.ToString() : string.Format("{0}, {1}", _from, sb.ToString());
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds to the 'Join' clause the contents obtained by parsing the dynamic lambda expressions given. The supported
|
||||
/// formats are:
|
||||
@@ -780,94 +788,100 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <para>- Generic expression: 'x => x( expression ).As( x.Alias )', where the alias part is mandatory. In this case
|
||||
/// the alias is not annotated.</para>
|
||||
/// </summary>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder Select(params Func<dynamic, object>[] func)
|
||||
public virtual IDynamicSelectQueryBuilder Select(Func<dynamic, object> fn, params Func<dynamic, object>[] func)
|
||||
{
|
||||
if (func == null)
|
||||
if (fn == null)
|
||||
throw new ArgumentNullException("Array of specifications cannot be null.");
|
||||
|
||||
int index = -1;
|
||||
foreach (var f in func)
|
||||
{
|
||||
index++;
|
||||
if (f == null)
|
||||
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
|
||||
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var 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)
|
||||
{
|
||||
var node = (string)result;
|
||||
var 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)
|
||||
{
|
||||
// Or if it resolves to a dynamic node...
|
||||
ParseSelectNode(result, ref main, ref alias, ref all);
|
||||
}
|
||||
else if (result.GetType().IsAnonymous())
|
||||
{
|
||||
anon = true;
|
||||
|
||||
foreach (var prop in result.ToDictionary())
|
||||
{
|
||||
if (prop.Value is string)
|
||||
{
|
||||
var node = (string)prop.Value;
|
||||
var 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)
|
||||
{
|
||||
// Or if it resolves to a dynamic node...
|
||||
ParseSelectNode(prop.Value, ref main, ref alias, ref all);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
int index = SelectFunc(-1, fn);
|
||||
if (func != null)
|
||||
foreach (var f in func)
|
||||
index = SelectFunc(index, f);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private int SelectFunc(int index, Func<dynamic, object> f)
|
||||
{
|
||||
index++;
|
||||
if (f == null)
|
||||
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
|
||||
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var 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)
|
||||
{
|
||||
var node = (string)result;
|
||||
var 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)
|
||||
{
|
||||
// Or if it resolves to a dynamic node...
|
||||
ParseSelectNode(result, ref main, ref alias, ref all);
|
||||
}
|
||||
else if (result.GetType().IsAnonymous())
|
||||
{
|
||||
anon = true;
|
||||
|
||||
foreach (var prop in result.ToDictionary())
|
||||
{
|
||||
if (prop.Value is string)
|
||||
{
|
||||
var node = (string)prop.Value;
|
||||
var 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)
|
||||
{
|
||||
// Or if it resolves to a dynamic node...
|
||||
ParseSelectNode(prop.Value, ref main, ref alias, ref all);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to add to object.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder Select(params DynamicColumn[] columns)
|
||||
public virtual IDynamicSelectQueryBuilder SelectColumn(params DynamicColumn[] columns)
|
||||
{
|
||||
foreach (var col in columns)
|
||||
Select(x => col.ToSQLSelectColumn(Database));
|
||||
@@ -880,9 +894,9 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <remarks>Column format consist of <c>Column Name</c>, <c>Alias</c> and
|
||||
/// <c>Aggregate function</c> in this order separated by '<c>:</c>'.</remarks>
|
||||
/// <returns>Builder instance.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder Select(params string[] columns)
|
||||
public virtual IDynamicSelectQueryBuilder SelectColumn(params string[] columns)
|
||||
{
|
||||
return Select(columns.Select(c => DynamicColumn.ParseSelectColumn(c)).ToArray());
|
||||
return SelectColumn(columns.Select(c => DynamicColumn.ParseSelectColumn(c)).ToArray());
|
||||
}
|
||||
|
||||
#endregion Select
|
||||
@@ -892,48 +906,54 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <summary>
|
||||
/// Adds to the 'Group By' clause the contents obtained from from parsing the dynamic lambda expression given.
|
||||
/// </summary>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder GroupBy(params Func<dynamic, object>[] func)
|
||||
public virtual IDynamicSelectQueryBuilder GroupBy(Func<dynamic, object> fn, params Func<dynamic, object>[] func)
|
||||
{
|
||||
if (func == null)
|
||||
if (fn == null)
|
||||
throw new ArgumentNullException("Array of specifications cannot be null.");
|
||||
|
||||
int index = -1;
|
||||
int index = GroupByFunc(-1, fn);
|
||||
|
||||
foreach (var f in func)
|
||||
{
|
||||
index++;
|
||||
if (f == null)
|
||||
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var 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);
|
||||
}
|
||||
}
|
||||
if (func != null)
|
||||
foreach (var f in func)
|
||||
index = GroupByFunc(index, f);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private int GroupByFunc(int index, Func<dynamic, object> f)
|
||||
{
|
||||
index++;
|
||||
if (f == null)
|
||||
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var 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;
|
||||
}
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to group by.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder GroupBy(params DynamicColumn[] columns)
|
||||
public virtual IDynamicSelectQueryBuilder GroupByColumn(params DynamicColumn[] columns)
|
||||
{
|
||||
foreach (var col in columns)
|
||||
GroupBy(x => col.ToSQLGroupByColumn(Database));
|
||||
@@ -946,9 +966,9 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <remarks>Column format consist of <c>Column Name</c> and
|
||||
/// <c>Alias</c> in this order separated by '<c>:</c>'.</remarks>
|
||||
/// <returns>Builder instance.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder GroupBy(params string[] columns)
|
||||
public virtual IDynamicSelectQueryBuilder GroupByColumn(params string[] columns)
|
||||
{
|
||||
return GroupBy(columns.Select(c => DynamicColumn.ParseSelectColumn(c)).ToArray());
|
||||
return GroupByColumn(columns.Select(c => DynamicColumn.ParseSelectColumn(c)).ToArray());
|
||||
}
|
||||
|
||||
#endregion GroupBy
|
||||
@@ -961,101 +981,107 @@ namespace DynamORM.Builders.Implementation
|
||||
/// to specify the direction. If no virtual method is used, the default is ascending order. You can also use the
|
||||
/// shorter versions <code>Asc()</code> and <code>Desc()</code>.
|
||||
/// </summary>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder OrderBy(params Func<dynamic, object>[] func)
|
||||
public virtual IDynamicSelectQueryBuilder OrderBy(Func<dynamic, object> fn, params Func<dynamic, object>[] func)
|
||||
{
|
||||
if (func == null)
|
||||
if (fn == null)
|
||||
throw new ArgumentNullException("Array of specifications cannot be null.");
|
||||
|
||||
int index = -1;
|
||||
int index = OrderByFunc(-1, fn);
|
||||
|
||||
foreach (var f in func)
|
||||
{
|
||||
index++;
|
||||
if (f == null)
|
||||
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
|
||||
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var 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)
|
||||
{
|
||||
var 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
|
||||
{
|
||||
// Intercepting trailing 'Ascending' or 'Descending' virtual methods...
|
||||
if (result is DynamicParser.Node.Method)
|
||||
{
|
||||
var node = (DynamicParser.Node.Method)result;
|
||||
var name = node.Name.ToUpper();
|
||||
if (name == "ASCENDING" || name == "ASC" || name == "DESCENDING" || name == "DESC")
|
||||
{
|
||||
object[] args = node.Arguments;
|
||||
if (args != null && !(node.Host is DynamicParser.Node.Argument))
|
||||
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;
|
||||
if (args[0] is int)
|
||||
main = args[0].ToString();
|
||||
else if (args[0] is string)
|
||||
{
|
||||
if (Int32.TryParse(args[0].ToString(), out col))
|
||||
main = col.ToString();
|
||||
else
|
||||
main = FixObjectName(args[0].ToString());
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (func != null)
|
||||
foreach (var f in func)
|
||||
index = OrderByFunc(index, f);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private int OrderByFunc(int index, Func<dynamic, object> f)
|
||||
{
|
||||
index++;
|
||||
if (f == null)
|
||||
throw new ArgumentNullException(string.Format("Specification #{0} cannot be null.", index));
|
||||
|
||||
using (var parser = DynamicParser.Parse(f))
|
||||
{
|
||||
var 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)
|
||||
{
|
||||
var 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
|
||||
{
|
||||
// Intercepting trailing 'Ascending' or 'Descending' virtual methods...
|
||||
if (result is DynamicParser.Node.Method)
|
||||
{
|
||||
var node = (DynamicParser.Node.Method)result;
|
||||
var name = node.Name.ToUpper();
|
||||
if (name == "ASCENDING" || name == "ASC" || name == "DESCENDING" || name == "DESC")
|
||||
{
|
||||
object[] args = node.Arguments;
|
||||
if (args != null && !(node.Host is DynamicParser.Node.Argument))
|
||||
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;
|
||||
if (args[0] is int)
|
||||
main = args[0].ToString();
|
||||
else if (args[0] is string)
|
||||
{
|
||||
if (Int32.TryParse(args[0].ToString(), out col))
|
||||
main = col.ToString();
|
||||
else
|
||||
main = FixObjectName(args[0].ToString());
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>Add select columns.</summary>
|
||||
/// <param name="columns">Columns to order by.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder OrderBy(params DynamicColumn[] columns)
|
||||
public virtual IDynamicSelectQueryBuilder OrderByColumn(params DynamicColumn[] columns)
|
||||
{
|
||||
foreach (var col in columns)
|
||||
OrderBy(x => col.ToSQLOrderByColumn(Database));
|
||||
@@ -1068,9 +1094,9 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <remarks>Column format consist of <c>Column Name</c> and
|
||||
/// <c>Alias</c> in this order separated by '<c>:</c>'.</remarks>
|
||||
/// <returns>Builder instance.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder OrderBy(params string[] columns)
|
||||
public virtual IDynamicSelectQueryBuilder OrderByColumn(params string[] columns)
|
||||
{
|
||||
return OrderBy(columns.Select(c => DynamicColumn.ParseOrderByColumn(c)).ToArray());
|
||||
return OrderByColumn(columns.Select(c => DynamicColumn.ParseOrderByColumn(c)).ToArray());
|
||||
}
|
||||
|
||||
#endregion OrderBy
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace DynamORM.Builders.Implementation
|
||||
/// </summary>
|
||||
/// <param name="func">The specifications.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicUpdateQueryBuilder Values(params Func<dynamic, object>[] func)
|
||||
public virtual IDynamicUpdateQueryBuilder Set(params Func<dynamic, object>[] func)
|
||||
{
|
||||
if (func == null)
|
||||
throw new ArgumentNullException("Array of specifications cannot be null.");
|
||||
|
||||
@@ -94,9 +94,13 @@ namespace DynamORM
|
||||
/// <summary>Gets schema columns cache.</summary>
|
||||
internal Dictionary<string, Dictionary<string, DynamicSchemaColumn>> Schema { get; private set; }
|
||||
|
||||
#if !DYNAMORM_OMMIT_OLDSYNTAX
|
||||
|
||||
/// <summary>Gets tables cache for this database instance.</summary>
|
||||
internal Dictionary<string, DynamicTable> TablesCache { get; private set; }
|
||||
|
||||
#endif
|
||||
|
||||
#endregion Internal fields and properties
|
||||
|
||||
#region Properties and Constructors
|
||||
@@ -160,13 +164,17 @@ namespace DynamORM
|
||||
TransactionPool = new Dictionary<IDbConnection, Stack<IDbTransaction>>();
|
||||
CommandsPool = new Dictionary<IDbConnection, List<IDbCommand>>();
|
||||
Schema = new Dictionary<string, Dictionary<string, DynamicSchemaColumn>>();
|
||||
#if !DYNAMORM_OMMIT_OLDSYNTAX
|
||||
TablesCache = new Dictionary<string, DynamicTable>();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion Properties and Constructors
|
||||
|
||||
#region Table
|
||||
|
||||
#if !DYNAMORM_OMMIT_OLDSYNTAX
|
||||
|
||||
/// <summary>Gets dynamic table which is a simple ORM using dynamic objects.</summary>
|
||||
/// <param name="action">The action with instance of <see cref="DynamicTable"/> as parameter.</param>
|
||||
/// <param name="table">Table name.</param>
|
||||
@@ -236,6 +244,8 @@ namespace DynamORM
|
||||
TablesCache.Remove(item.Key);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endregion Table
|
||||
|
||||
#region From/Insert/Update/Delete
|
||||
@@ -248,11 +258,11 @@ namespace DynamORM
|
||||
/// <para>- Generic expression: <code>x => x( expression ).As( x.Alias )</code>, where the alias part is mandatory. In this
|
||||
/// case the alias is not annotated.</para>
|
||||
/// </summary>
|
||||
/// <param name="func">The specification.</param>
|
||||
/// <param name="fn">The specification.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder From(params Func<dynamic, object>[] func)
|
||||
public virtual IDynamicSelectQueryBuilder From(Func<dynamic, object> fn)
|
||||
{
|
||||
return new DynamicSelectQueryBuilder(this).From(func);
|
||||
return new DynamicSelectQueryBuilder(this).From(fn);
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>FROM</code> clause using <see cref="Type"/>.</summary>
|
||||
@@ -263,6 +273,14 @@ namespace DynamORM
|
||||
return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)));
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>FROM</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <param name="t">Type which can be represented in database.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicSelectQueryBuilder From(Type t)
|
||||
{
|
||||
return new DynamicSelectQueryBuilder(this).From(x => x(t));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds to the <code>INSERT INTO</code> clause the contents obtained by parsing the dynamic lambda expressions given. The supported
|
||||
/// formats are:
|
||||
@@ -287,6 +305,14 @@ namespace DynamORM
|
||||
return new DynamicInsertQueryBuilder(this).Table(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>INSERT INTO</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <param name="t">Type which can be represented in database.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicInsertQueryBuilder Insert(Type t)
|
||||
{
|
||||
return new DynamicInsertQueryBuilder(this).Table(t);
|
||||
}
|
||||
|
||||
/// <summary>Bulk insert objects into database.</summary>
|
||||
/// <typeparam name="T">Type of objects to insert.</typeparam>
|
||||
/// <param name="e">Enumerable containing instances of objects to insert.</param>
|
||||
@@ -413,6 +439,14 @@ namespace DynamORM
|
||||
return new DynamicUpdateQueryBuilder(this).Table(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>UPDATE</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <param name="t">Type which can be represented in database.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicUpdateQueryBuilder Update(Type t)
|
||||
{
|
||||
return new DynamicUpdateQueryBuilder(this).Table(t);
|
||||
}
|
||||
|
||||
/// <summary>Bulk update objects in database.</summary>
|
||||
/// <typeparam name="T">Type of objects to update.</typeparam>
|
||||
/// <param name="e">Enumerable containing instances of objects to update.</param>
|
||||
@@ -1231,10 +1265,12 @@ namespace DynamORM
|
||||
/// releasing, or resetting unmanaged resources.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
#if !DYNAMORM_OMMIT_OLDSYNTAX
|
||||
var tables = TablesCache.Values.ToList();
|
||||
TablesCache.Clear();
|
||||
|
||||
tables.ForEach(t => t.Dispose());
|
||||
#endif
|
||||
|
||||
foreach (var con in TransactionPool)
|
||||
{
|
||||
|
||||
@@ -601,6 +601,8 @@ namespace DynamORM
|
||||
|
||||
#region Generic Execution
|
||||
|
||||
#if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE
|
||||
|
||||
/// <summary>Execute scalar and return string if possible.</summary>
|
||||
/// <typeparam name="T">Type to parse to.</typeparam>
|
||||
/// <param name="command"><see cref="System.Data.IDbCommand"/> which will be executed.</param>
|
||||
@@ -725,6 +727,8 @@ namespace DynamORM
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endregion Generic Execution
|
||||
|
||||
/// <summary>Dump command into text writer.</summary>
|
||||
@@ -841,22 +845,49 @@ namespace DynamORM
|
||||
/// <summary>Creates sub query that can be used inside of from/join/expressions.</summary>
|
||||
/// <typeparam name="T">Class implementing <see cref="IDynamicQueryBuilder"/> interface.</typeparam>
|
||||
/// <param name="b">The builder that will be parent of new sub query.</param>
|
||||
/// <returns>Instance of sub query.</returns>
|
||||
public static IDynamicSelectQueryBuilder SubQuery<T>(this T b) where T : IDynamicQueryBuilder
|
||||
{
|
||||
return new DynamicSelectQueryBuilder(b.Database, b as DynamicQueryBuilder);
|
||||
}
|
||||
|
||||
/// <summary>Creates sub query that can be used inside of from/join/expressions.</summary>
|
||||
/// <typeparam name="T">Class implementing <see cref="IDynamicQueryBuilder"/> interface.</typeparam>
|
||||
/// <param name="b">The builder that will be parent of new sub query.</param>
|
||||
/// <param name="fn">The specification for sub query.</param>
|
||||
/// <param name="func">The specification for sub query.</param>
|
||||
/// <returns>Instance of sub query.</returns>
|
||||
public static IDynamicSelectQueryBuilder SubQuery<T>(this T b, params Func<dynamic, object>[] func) where T : IDynamicQueryBuilder
|
||||
public static IDynamicSelectQueryBuilder SubQuery<T>(this T b, Func<dynamic, object> fn, params Func<dynamic, object>[] func) where T : IDynamicQueryBuilder
|
||||
{
|
||||
return func == null || func.Length == 0 ? new DynamicSelectQueryBuilder(b.Database, b as DynamicQueryBuilder) : new DynamicSelectQueryBuilder(b.Database, b as DynamicQueryBuilder).From(func);
|
||||
return new DynamicSelectQueryBuilder(b.Database, b as DynamicQueryBuilder).From(fn, func);
|
||||
}
|
||||
|
||||
/// <summary>Creates sub query that can be used inside of from/join/expressions.</summary>
|
||||
/// <typeparam name="T">Class implementing <see cref="IDynamicQueryBuilder"/> interface.</typeparam>
|
||||
/// <param name="b">The builder that will be parent of new sub query.</param>
|
||||
/// <param name="subquery">First argument is parent query, second one is a sub query.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public static T SubQuery<T>(this T b, Action<T, IDynamicSelectQueryBuilder> subquery) where T : IDynamicQueryBuilder
|
||||
{
|
||||
var sub = b.SubQuery();
|
||||
|
||||
subquery(b, sub);
|
||||
|
||||
(b as DynamicQueryBuilder).ParseCommand(sub as DynamicQueryBuilder, b.Parameters);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>Creates sub query that can be used inside of from/join/expressions.</summary>
|
||||
/// <typeparam name="T">Class implementing <see cref="IDynamicQueryBuilder"/> interface.</typeparam>
|
||||
/// <param name="b">The builder that will be parent of new sub query.</param>
|
||||
/// <param name="subquery">First argument is parent query, second one is a sub query.</param>
|
||||
/// <param name="fn">The specification for sub query.</param>
|
||||
/// <param name="func">The specification for sub query.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public static T SubQuery<T>(this T b, Action<T, IDynamicSelectQueryBuilder> subquery, params Func<dynamic, object>[] func) where T : IDynamicQueryBuilder
|
||||
public static T SubQuery<T>(this T b, Action<T, IDynamicSelectQueryBuilder> subquery, Func<dynamic, object> fn, params Func<dynamic, object>[] func) where T : IDynamicQueryBuilder
|
||||
{
|
||||
var sub = b.SubQuery(func);
|
||||
var sub = b.SubQuery(fn, func);
|
||||
|
||||
subquery(b, sub);
|
||||
|
||||
@@ -1244,6 +1275,8 @@ namespace DynamORM
|
||||
|
||||
#region TryParse extensions
|
||||
|
||||
#if !DYNAMORM_OMMIT_TRYPARSE
|
||||
|
||||
/// <summary>Generic try parse.</summary>
|
||||
/// <typeparam name="T">Type to parse to.</typeparam>
|
||||
/// <param name="value">Value to parse.</param>
|
||||
@@ -1288,6 +1321,8 @@ namespace DynamORM
|
||||
/// <returns>Returns <c>true</c> if conversion was successful.</returns>
|
||||
public delegate bool TryParseHandler<T>(string value, out T result);
|
||||
|
||||
#endif
|
||||
|
||||
#endregion TryParse extensions
|
||||
|
||||
#region Coalesce - besicaly not an extensions
|
||||
|
||||
@@ -41,6 +41,8 @@ using DynamORM.Mapper;
|
||||
|
||||
namespace DynamORM
|
||||
{
|
||||
#if !DYNAMORM_OMMIT_OLDSYNTAX
|
||||
|
||||
/// <summary>Dynamic table is a simple ORM using dynamic objects.</summary>
|
||||
/// <example>
|
||||
/// <para>Assume that we have a table representing Users class.</para>
|
||||
@@ -836,25 +838,25 @@ namespace DynamORM
|
||||
{
|
||||
case "order":
|
||||
if (args[i] is string)
|
||||
builder.OrderBy(((string)args[i]).Split(','));
|
||||
builder.OrderByColumn(((string)args[i]).Split(','));
|
||||
else if (args[i] is string[])
|
||||
builder.OrderBy(args[i] as string);
|
||||
builder.OrderByColumn(args[i] as string);
|
||||
else if (args[i] is DynamicColumn[])
|
||||
builder.OrderBy((DynamicColumn[])args[i]);
|
||||
builder.OrderByColumn((DynamicColumn[])args[i]);
|
||||
else if (args[i] is DynamicColumn)
|
||||
builder.OrderBy((DynamicColumn)args[i]);
|
||||
builder.OrderByColumn((DynamicColumn)args[i]);
|
||||
else goto default;
|
||||
break;
|
||||
|
||||
case "group":
|
||||
if (args[i] is string)
|
||||
builder.GroupBy(((string)args[i]).Split(','));
|
||||
builder.GroupByColumn(((string)args[i]).Split(','));
|
||||
else if (args[i] is string[])
|
||||
builder.GroupBy(args[i] as string);
|
||||
builder.GroupByColumn(args[i] as string);
|
||||
else if (args[i] is DynamicColumn[])
|
||||
builder.GroupBy((DynamicColumn[])args[i]);
|
||||
builder.GroupByColumn((DynamicColumn[])args[i]);
|
||||
else if (args[i] is DynamicColumn)
|
||||
builder.GroupBy((DynamicColumn)args[i]);
|
||||
builder.GroupByColumn((DynamicColumn)args[i]);
|
||||
else goto default;
|
||||
break;
|
||||
|
||||
@@ -864,7 +866,7 @@ namespace DynamORM
|
||||
op.ToUpper() : null;
|
||||
|
||||
if (args[i] is string || args[i] is string[])
|
||||
builder.Select((args[i] as String).NullOr(s => s.Split(','), args[i] as String[])
|
||||
builder.SelectColumn((args[i] as String).NullOr(s => s.Split(','), args[i] as String[])
|
||||
.Select(c =>
|
||||
{
|
||||
var col = DynamicColumn.ParseSelectColumn(c);
|
||||
@@ -874,7 +876,7 @@ namespace DynamORM
|
||||
return col;
|
||||
}).ToArray());
|
||||
else if (args[i] is DynamicColumn || args[i] is DynamicColumn[])
|
||||
builder.Select((args[i] as DynamicColumn).NullOr(c => new DynamicColumn[] { c }, args[i] as DynamicColumn[])
|
||||
builder.SelectColumn((args[i] as DynamicColumn).NullOr(c => new DynamicColumn[] { c }, args[i] as DynamicColumn[])
|
||||
.Select(c =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(c.Aggregate))
|
||||
@@ -1042,4 +1044,6 @@ namespace DynamORM
|
||||
|
||||
#endregion ICloneable Members
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -26,6 +26,11 @@
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* See: http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* Supported preprocessor flags:
|
||||
* * DYNAMORM_OMMIT_OLDSYNTAX - Remove dynamic table functionality
|
||||
* * DYNAMORM_OMMIT_GENERICEXECUTION - Remove generic execution functionality
|
||||
* * DYNAMORM_OMMIT_TRYPARSE - Remove TryParse helpers (also applies DYNAMORM_OMMIT_GENERICEXECUTION)
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
Reference in New Issue
Block a user