Add positional typed multi-table SQL contexts

This commit is contained in:
root
2026-02-27 09:12:17 +01:00
parent c0fb2e5232
commit 8210fbfdb5
5 changed files with 865 additions and 28 deletions

View File

@@ -7303,6 +7303,66 @@ namespace DynamORM
/// <summary>Add typed SQL DSL order by expressions.</summary> /// <summary>Add typed SQL DSL order by expressions.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql(Func<TypedTableContext<T>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedSqlOrderExpression>[] selectors); IDynamicTypedSelectQueryBuilder<T> OrderBySql(Func<TypedTableContext<T>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedSqlOrderExpression>[] selectors);
/// <summary>Add typed SQL DSL select items using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable>[] selectors);
/// <summary>Add typed SQL DSL select items using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable>[] selectors);
/// <summary>Add typed SQL DSL select items using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable>[] selectors);
/// <summary>Add typed SQL DSL select items using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable>[] selectors);
/// <summary>Add typed SQL DSL where predicate using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL where predicate using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL where predicate using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL where predicate using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL having predicate using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL having predicate using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL having predicate using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL having predicate using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL group-by expression using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression>[] selectors);
/// <summary>Add typed SQL DSL group-by expression using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression>[] selectors);
/// <summary>Add typed SQL DSL group-by expression using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression>[] selectors);
/// <summary>Add typed SQL DSL group-by expression using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression>[] selectors);
/// <summary>Add typed SQL DSL order-by expression using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression>[] selectors);
/// <summary>Add typed SQL DSL order-by expression using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression>[] selectors);
/// <summary>Add typed SQL DSL order-by expression using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression>[] selectors);
/// <summary>Add typed SQL DSL order-by expression using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression>[] selectors);
} }
/// <summary>Typed update query builder for mapped entities.</summary> /// <summary>Typed update query builder for mapped entities.</summary>
/// <typeparam name="T">Mapped entity type.</typeparam> /// <typeparam name="T">Mapped entity type.</typeparam>
@@ -10869,6 +10929,11 @@ namespace DynamORM
/// <typeparam name="T">Mapped entity type.</typeparam> /// <typeparam name="T">Mapped entity type.</typeparam>
internal class DynamicTypedSelectQueryBuilder<T> : DynamicSelectQueryBuilder, IDynamicTypedSelectQueryBuilder<T> internal class DynamicTypedSelectQueryBuilder<T> : DynamicSelectQueryBuilder, IDynamicTypedSelectQueryBuilder<T>
{ {
private sealed class TypedJoinInfo
{
public Type ModelType { get; set; }
public string Alias { get; set; }
}
private sealed class TypedSqlRenderContext : ITypedSqlRenderContext private sealed class TypedSqlRenderContext : ITypedSqlRenderContext
{ {
private readonly DynamicTypedSelectQueryBuilder<T> _builder; private readonly DynamicTypedSelectQueryBuilder<T> _builder;
@@ -10916,6 +10981,7 @@ namespace DynamORM
} }
} }
private readonly DynamicTypeMap _mapper; private readonly DynamicTypeMap _mapper;
private readonly List<TypedJoinInfo> _typedJoins = new List<TypedJoinInfo>();
public DynamicTypedSelectQueryBuilder(DynamicDatabase db) public DynamicTypedSelectQueryBuilder(DynamicDatabase db)
: base(db) : base(db)
@@ -10977,6 +11043,7 @@ namespace DynamORM
if (!string.IsNullOrEmpty(condition)) if (!string.IsNullOrEmpty(condition))
joinExpr += string.Format(" ON {0}", condition); joinExpr += string.Format(" ON {0}", condition);
RegisterTypedJoin(typeof(TRight), rightAlias);
AppendJoinClause(joinExpr); AppendJoinClause(joinExpr);
return this; return this;
} }
@@ -11019,6 +11086,7 @@ namespace DynamORM
else if (!string.IsNullOrEmpty(spec.OnRawCondition)) else if (!string.IsNullOrEmpty(spec.OnRawCondition))
joinExpr += string.Format(" ON {0}", spec.OnRawCondition); joinExpr += string.Format(" ON {0}", spec.OnRawCondition);
RegisterTypedJoin(typeof(TRight), rightAlias);
AppendJoinClause(joinExpr); AppendJoinClause(joinExpr);
return this; return this;
} }
@@ -11076,6 +11144,54 @@ namespace DynamORM
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable> item in selectors)
AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable> item in selectors)
AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable> item in selectors)
AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable> item in selectors)
AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> GroupBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors) public IDynamicTypedSelectQueryBuilder<T> GroupBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors)
{ {
if (selector == null) if (selector == null)
@@ -11105,6 +11221,54 @@ namespace DynamORM
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression> item in selectors)
AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression> item in selectors)
AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression> item in selectors)
AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression> item in selectors)
AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> OrderBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors) public IDynamicTypedSelectQueryBuilder<T> OrderBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors)
{ {
if (selector == null) if (selector == null)
@@ -11134,6 +11298,54 @@ namespace DynamORM
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression> item in selectors)
AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression> item in selectors)
AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression> item in selectors)
AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression> item in selectors)
AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
return this;
}
public new IDynamicTypedSelectQueryBuilder<T> Top(int? top) public new IDynamicTypedSelectQueryBuilder<T> Top(int? top)
{ {
base.Top(top); base.Top(top);
@@ -11173,27 +11385,83 @@ namespace DynamORM
if (predicate == null) if (predicate == null)
throw new ArgumentNullException("predicate"); throw new ArgumentNullException("predicate");
string condition = RenderSqlPredicate(predicate); AppendSqlCondition(RenderSqlPredicate(predicate), false);
if (string.IsNullOrEmpty(WhereCondition))
WhereCondition = condition;
else
WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition);
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0))), false);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1))), false);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2))), false);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3))), false);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> HavingSql(Func<TypedTableContext<T>, TypedSqlPredicate> predicate) public IDynamicTypedSelectQueryBuilder<T> HavingSql(Func<TypedTableContext<T>, TypedSqlPredicate> predicate)
{ {
if (predicate == null) if (predicate == null)
throw new ArgumentNullException("predicate"); throw new ArgumentNullException("predicate");
string condition = RenderSqlPredicate(predicate); AppendSqlCondition(RenderSqlPredicate(predicate), true);
if (string.IsNullOrEmpty(HavingCondition))
HavingCondition = condition;
else
HavingCondition = string.Format("{0} AND {1}", HavingCondition, condition);
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0))), true);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1))), true);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2))), true);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3))), true);
return this;
}
public new IDynamicTypedSelectQueryBuilder<T> Having(DynamicColumn column) public new IDynamicTypedSelectQueryBuilder<T> Having(DynamicColumn column)
{ {
base.Having(column); base.Having(column);
@@ -11237,8 +11505,14 @@ namespace DynamORM
if (selector == null) if (selector == null)
throw new ArgumentNullException("selector"); throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext()));
}
private void AddSelectSqlSelector(TypedSqlSelectable item)
{
if (item == null)
throw new ArgumentNullException("item");
TypedSqlRenderContext context = new TypedSqlRenderContext(this); TypedSqlRenderContext context = new TypedSqlRenderContext(this);
TypedSqlSelectable item = selector(new TypedTableContext<T>(GetRootAliasOrTableName()));
string rendered = item.Render(context); string rendered = item.Render(context);
_select = string.IsNullOrEmpty(_select) ? rendered : string.Format("{0}, {1}", _select, rendered); _select = string.IsNullOrEmpty(_select) ? rendered : string.Format("{0}, {1}", _select, rendered);
} }
@@ -11265,8 +11539,14 @@ namespace DynamORM
if (selector == null) if (selector == null)
throw new ArgumentNullException("selector"); throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext()));
}
private void AddGroupBySqlSelector(TypedSqlExpression item)
{
if (item == null)
throw new ArgumentNullException("item");
TypedSqlRenderContext context = new TypedSqlRenderContext(this); TypedSqlRenderContext context = new TypedSqlRenderContext(this);
TypedSqlExpression item = selector(new TypedTableContext<T>(GetRootAliasOrTableName()));
string rendered = item.Render(context); string rendered = item.Render(context);
_groupby = string.IsNullOrEmpty(_groupby) ? rendered : string.Format("{0}, {1}", _groupby, rendered); _groupby = string.IsNullOrEmpty(_groupby) ? rendered : string.Format("{0}, {1}", _groupby, rendered);
} }
@@ -11289,15 +11569,25 @@ namespace DynamORM
if (selector == null) if (selector == null)
throw new ArgumentNullException("selector"); throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext()));
}
private void AddOrderBySqlSelector(TypedSqlOrderExpression item)
{
TypedSqlRenderContext context = new TypedSqlRenderContext(this); TypedSqlRenderContext context = new TypedSqlRenderContext(this);
TypedSqlOrderExpression item = selector(new TypedTableContext<T>(GetRootAliasOrTableName()));
string rendered = item.Render(context); string rendered = item.Render(context);
_orderby = string.IsNullOrEmpty(_orderby) ? rendered : string.Format("{0}, {1}", _orderby, rendered); _orderby = string.IsNullOrEmpty(_orderby) ? rendered : string.Format("{0}, {1}", _orderby, rendered);
} }
private string RenderSqlPredicate(Func<TypedTableContext<T>, TypedSqlPredicate> predicate) private string RenderSqlPredicate(Func<TypedTableContext<T>, TypedSqlPredicate> predicate)
{ {
return RenderSqlPredicate(predicate(GetRootContext()));
}
private string RenderSqlPredicate(TypedSqlPredicate predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
TypedSqlRenderContext context = new TypedSqlRenderContext(this); TypedSqlRenderContext context = new TypedSqlRenderContext(this);
return predicate(new TypedTableContext<T>(GetRootAliasOrTableName())).Render(context); return predicate.Render(context);
} }
private string ParseTypedCondition(Expression expression) private string ParseTypedCondition(Expression expression)
{ {
@@ -11461,6 +11751,46 @@ namespace DynamORM
return string.IsNullOrEmpty(table.Alias) ? table.Name : table.Alias; return string.IsNullOrEmpty(table.Alias) ? table.Name : table.Alias;
} }
private TypedTableContext<T> GetRootContext()
{
return new TypedTableContext<T>(GetRootAliasOrTableName());
}
private TypedTableContext<TJoin> GetJoinedContext<TJoin>(int index)
{
if (index < 0 || index >= _typedJoins.Count)
throw new InvalidOperationException(string.Format("Typed join context at position {0} is not available.", index + 1));
TypedJoinInfo join = _typedJoins[index];
if (join.ModelType != typeof(TJoin))
throw new InvalidOperationException(string.Format("Typed join context at position {0} is {1}, not {2}.", index + 1, join.ModelType.FullName, typeof(TJoin).FullName));
return new TypedTableContext<TJoin>(join.Alias);
}
private void RegisterTypedJoin(Type modelType, string alias)
{
_typedJoins.Add(new TypedJoinInfo
{
ModelType = modelType,
Alias = alias
});
}
private void AppendSqlCondition(string condition, bool having)
{
if (having)
{
if (string.IsNullOrEmpty(HavingCondition))
HavingCondition = condition;
else
HavingCondition = string.Format("{0} AND {1}", HavingCondition, condition);
}
else
{
if (string.IsNullOrEmpty(WhereCondition))
WhereCondition = condition;
else
WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition);
}
}
private static bool IsMemberFromTypedParameter(Expression expression) private static bool IsMemberFromTypedParameter(Expression expression)
{ {
var member = expression as MemberExpression; var member = expression as MemberExpression;

View File

@@ -0,0 +1,36 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*/
using DynamORM.Mapper;
namespace DynamORM.Tests.Helpers
{
[Table(Name = "UserRoles", Owner = "dbo")]
public class TypedJoinUserRole
{
[Column("Role_Id", true)]
public long RoleId { get; set; }
[Column("User_Id")]
public long UserId { get; set; }
[Column("Role_Name")]
public string RoleName { get; set; }
}
[Table(Name = "UserRegions", Owner = "dbo")]
public class TypedJoinUserRegion
{
[Column("Region_Id", true)]
public long RegionId { get; set; }
[Column("User_Id")]
public long UserId { get; set; }
[Column("Region_Code")]
public string RegionCode { get; set; }
}
}

View File

@@ -386,5 +386,117 @@ namespace DynamORM.Tests.TypedSql
"UPDATE \"sample_users\" SET \"code\" = (SELECT x.\"user_code\" FROM \"sample_users\" AS x WHERE (x.\"id_user\" = [$0])), \"first\" = LOWER([$1]) WHERE (\"id\" = [$2])", "UPDATE \"sample_users\" SET \"code\" = (SELECT x.\"user_code\" FROM \"sample_users\" AS x WHERE (x.\"id_user\" = [$0])), \"first\" = LOWER([$1]) WHERE (\"id\" = [$2])",
NormalizeSql(cmd.CommandText())); NormalizeSql(cmd.CommandText()));
} }
[Test]
public void TestSelectSqlSupportsPositionalJoinedContexts()
{
var cmd = Database.FromTyped<TypedJoinUser>("u")
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
.SelectSql<TypedJoinUserClient>(
(u, c) => u.Col(x => x.IdUser).As("user_id"),
(u, c) => c.Col(x => x.Users).As("client_users"));
Assert.AreEqual(
"SELECT u.\"Id_User\" AS \"user_id\", c.\"Users\" AS \"client_users\" FROM \"dbo\".\"Users\" AS u LEFT JOIN \"dbo\".\"UserClients\" AS c ON (u.\"Id_User\" = c.\"User_Id\")",
NormalizeSql(cmd.CommandText()));
}
[Test]
public void TestWhereGroupHavingAndOrderBySupportPositionalJoinedContexts()
{
var cmd = Database.FromTyped<TypedJoinUser>("u")
.Join<TypedJoinUserClient>(j => j.Inner().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
.SelectSql<TypedJoinUserClient>(
(u, c) => u.Col(x => x.IdUser),
(u, c) => Sql.Count(c.Col(x => x.UserId)).As("cnt"))
.WhereSql<TypedJoinUserClient>((u, c) => u.Col(x => x.Active).Eq(1).And(c.Col(x => x.Deleted).Eq(0)))
.GroupBySql<TypedJoinUserClient>(
(u, c) => u.Col(x => x.IdUser),
(u, c) => c.Col(x => x.Users))
.HavingSql<TypedJoinUserClient>((u, c) => Sql.Count(c.Col(x => x.UserId)).Gt(0))
.OrderBySql<TypedJoinUserClient>(
(u, c) => c.Col(x => x.Users).Asc(),
(u, c) => Sql.Count(c.Col(x => x.UserId)).Desc());
Assert.AreEqual(
"SELECT u.\"Id_User\", COUNT(c.\"User_Id\") AS \"cnt\" FROM \"dbo\".\"Users\" AS u INNER JOIN \"dbo\".\"UserClients\" AS c ON (u.\"Id_User\" = c.\"User_Id\") WHERE ((u.\"Active\" = [$0]) AND (c.\"Deleted\" = [$1])) GROUP BY u.\"Id_User\", c.\"Users\" HAVING (COUNT(c.\"User_Id\") > [$2]) ORDER BY c.\"Users\" ASC, COUNT(c.\"User_Id\") DESC",
NormalizeSql(cmd.CommandText()));
}
[Test]
public void TestPositionalJoinedContextsSupportThreeJoins()
{
var cmd = Database.FromTyped<TypedJoinUser>("u")
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
.Join<TypedJoinUserRole>(j => j.Left().As("r").OnSql((u, r) => u.Col(x => x.IdUser).Eq(r.Col(x => x.UserId))))
.Join<TypedJoinUserRegion>(j => j.Left().As("g").OnSql((u, g) => u.Col(x => x.IdUser).Eq(g.Col(x => x.UserId))))
.SelectSql<TypedJoinUserClient, TypedJoinUserRole, TypedJoinUserRegion>(
(u, c, r, g) => u.Col(x => x.IdUser),
(u, c, r, g) => c.Col(x => x.Users).As("client_users"),
(u, c, r, g) => r.Col(x => x.RoleName).As("role_name"),
(u, c, r, g) => g.Col(x => x.RegionCode).As("region_code"))
.WhereSql<TypedJoinUserClient, TypedJoinUserRole, TypedJoinUserRegion>(
(u, c, r, g) => c.Col(x => x.Deleted).Eq(0).And(r.Col(x => x.RoleId).Gt(0)).And(g.Col(x => x.RegionId).Gt(0)))
.OrderBySql<TypedJoinUserClient, TypedJoinUserRole, TypedJoinUserRegion>(
(u, c, r, g) => r.Col(x => x.RoleName).Asc(),
(u, c, r, g) => g.Col(x => x.RegionCode).Desc());
Assert.AreEqual(
"SELECT u.\"Id_User\", c.\"Users\" AS \"client_users\", r.\"Role_Name\" AS \"role_name\", g.\"Region_Code\" AS \"region_code\" FROM \"dbo\".\"Users\" AS u LEFT JOIN \"dbo\".\"UserClients\" AS c ON (u.\"Id_User\" = c.\"User_Id\") LEFT JOIN \"dbo\".\"UserRoles\" AS r ON (u.\"Id_User\" = r.\"User_Id\") LEFT JOIN \"dbo\".\"UserRegions\" AS g ON (u.\"Id_User\" = g.\"User_Id\") WHERE (((c.\"Deleted\" = [$0]) AND (r.\"Role_Id\" > [$1])) AND (g.\"Region_Id\" > [$2])) ORDER BY r.\"Role_Name\" ASC, g.\"Region_Code\" DESC",
NormalizeSql(cmd.CommandText()));
}
[Test]
public void TestPositionalJoinedContextsSupportFourJoinedTables()
{
var cmd = Database.FromTyped<TypedFluentUser>("u")
.Join<TypedFluentUser>(j => j.Left().As("b").OnSql((u, b) => u.Col(x => x.Id).Eq(b.Col(x => x.Id))))
.Join<TypedFluentUser>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.Id).Eq(c.Col(x => x.Id))))
.Join<TypedFluentUser>(j => j.Left().As("d").OnSql((u, d) => u.Col(x => x.Id).Eq(d.Col(x => x.Id))))
.Join<TypedFluentUser>(j => j.Left().As("e").OnSql((u, e) => u.Col(x => x.Id).Eq(e.Col(x => x.Id))))
.SelectSql<TypedFluentUser, TypedFluentUser, TypedFluentUser, TypedFluentUser>(
(u, b, c, d, e) => u.Col(x => x.Id).As("root_id"),
(u, b, c, d, e) => b.Col(x => x.Code).As("b_code"),
(u, b, c, d, e) => c.Col(x => x.Code).As("c_code"),
(u, b, c, d, e) => d.Col(x => x.Code).As("d_code"),
(u, b, c, d, e) => e.Col(x => x.Code).As("e_code"))
.WhereSql<TypedFluentUser, TypedFluentUser, TypedFluentUser, TypedFluentUser>(
(u, b, c, d, e) => b.Col(x => x.Code).IsNotNull()
.And(c.Col(x => x.Code).IsNotNull())
.And(d.Col(x => x.Code).IsNotNull())
.And(e.Col(x => x.Code).IsNotNull()));
Assert.AreEqual(
"SELECT u.\"id_user\" AS \"root_id\", b.\"user_code\" AS \"b_code\", c.\"user_code\" AS \"c_code\", d.\"user_code\" AS \"d_code\", e.\"user_code\" AS \"e_code\" FROM \"sample_users\" AS u LEFT JOIN \"sample_users\" AS b ON (u.\"id_user\" = b.\"id_user\") LEFT JOIN \"sample_users\" AS c ON (u.\"id_user\" = c.\"id_user\") LEFT JOIN \"sample_users\" AS d ON (u.\"id_user\" = d.\"id_user\") LEFT JOIN \"sample_users\" AS e ON (u.\"id_user\" = e.\"id_user\") WHERE ((((b.\"user_code\" IS NOT NULL) AND (c.\"user_code\" IS NOT NULL)) AND (d.\"user_code\" IS NOT NULL)) AND (e.\"user_code\" IS NOT NULL))",
NormalizeSql(cmd.CommandText()));
}
[Test]
public void TestPositionalJoinedContextsValidateRequestedType()
{
var builder = Database.FromTyped<TypedJoinUser>("u")
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))));
var ex = Assert.Throws<System.InvalidOperationException>(() =>
builder.SelectSql<TypedJoinUserRole>((u, r) => r.Col(x => x.RoleId).As("role_id")));
Assert.AreEqual(
"Typed join context at position 1 is DynamORM.Tests.Helpers.TypedJoinUserClient, not DynamORM.Tests.Helpers.TypedJoinUserRole.",
ex.Message);
}
[Test]
public void TestPositionalJoinedContextsValidateRequestedPosition()
{
var builder = Database.FromTyped<TypedJoinUser>("u")
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))));
var ex = Assert.Throws<System.InvalidOperationException>(() =>
builder.SelectSql<TypedJoinUserClient, TypedJoinUserRole>((u, c, r) => r.Col(x => x.RoleId).As("role_id")));
Assert.AreEqual(
"Typed join context at position 2 is not available.",
ex.Message);
}
} }
} }

View File

@@ -105,5 +105,65 @@ namespace DynamORM.Builders
/// <summary>Add typed SQL DSL order by expressions.</summary> /// <summary>Add typed SQL DSL order by expressions.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql(Func<TypedTableContext<T>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedSqlOrderExpression>[] selectors); IDynamicTypedSelectQueryBuilder<T> OrderBySql(Func<TypedTableContext<T>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedSqlOrderExpression>[] selectors);
/// <summary>Add typed SQL DSL select items using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable>[] selectors);
/// <summary>Add typed SQL DSL select items using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable>[] selectors);
/// <summary>Add typed SQL DSL select items using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable>[] selectors);
/// <summary>Add typed SQL DSL select items using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable>[] selectors);
/// <summary>Add typed SQL DSL where predicate using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL where predicate using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL where predicate using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL where predicate using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL having predicate using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL having predicate using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL having predicate using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL having predicate using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate);
/// <summary>Add typed SQL DSL group-by expression using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression>[] selectors);
/// <summary>Add typed SQL DSL group-by expression using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression>[] selectors);
/// <summary>Add typed SQL DSL group-by expression using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression>[] selectors);
/// <summary>Add typed SQL DSL group-by expression using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression>[] selectors);
/// <summary>Add typed SQL DSL order-by expression using root and first joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression>[] selectors);
/// <summary>Add typed SQL DSL order-by expression using root and first two joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression>[] selectors);
/// <summary>Add typed SQL DSL order-by expression using root and first three joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression>[] selectors);
/// <summary>Add typed SQL DSL order-by expression using root and first four joined table contexts.</summary>
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression>[] selectors);
} }
} }

View File

@@ -42,6 +42,12 @@ namespace DynamORM.Builders.Implementation
/// <typeparam name="T">Mapped entity type.</typeparam> /// <typeparam name="T">Mapped entity type.</typeparam>
internal class DynamicTypedSelectQueryBuilder<T> : DynamicSelectQueryBuilder, IDynamicTypedSelectQueryBuilder<T> internal class DynamicTypedSelectQueryBuilder<T> : DynamicSelectQueryBuilder, IDynamicTypedSelectQueryBuilder<T>
{ {
private sealed class TypedJoinInfo
{
public Type ModelType { get; set; }
public string Alias { get; set; }
}
private sealed class TypedSqlRenderContext : ITypedSqlRenderContext private sealed class TypedSqlRenderContext : ITypedSqlRenderContext
{ {
private readonly DynamicTypedSelectQueryBuilder<T> _builder; private readonly DynamicTypedSelectQueryBuilder<T> _builder;
@@ -94,6 +100,7 @@ namespace DynamORM.Builders.Implementation
} }
private readonly DynamicTypeMap _mapper; private readonly DynamicTypeMap _mapper;
private readonly List<TypedJoinInfo> _typedJoins = new List<TypedJoinInfo>();
public DynamicTypedSelectQueryBuilder(DynamicDatabase db) public DynamicTypedSelectQueryBuilder(DynamicDatabase db)
: base(db) : base(db)
@@ -158,6 +165,7 @@ namespace DynamORM.Builders.Implementation
if (!string.IsNullOrEmpty(condition)) if (!string.IsNullOrEmpty(condition))
joinExpr += string.Format(" ON {0}", condition); joinExpr += string.Format(" ON {0}", condition);
RegisterTypedJoin(typeof(TRight), rightAlias);
AppendJoinClause(joinExpr); AppendJoinClause(joinExpr);
return this; return this;
} }
@@ -201,6 +209,7 @@ namespace DynamORM.Builders.Implementation
else if (!string.IsNullOrEmpty(spec.OnRawCondition)) else if (!string.IsNullOrEmpty(spec.OnRawCondition))
joinExpr += string.Format(" ON {0}", spec.OnRawCondition); joinExpr += string.Format(" ON {0}", spec.OnRawCondition);
RegisterTypedJoin(typeof(TRight), rightAlias);
AppendJoinClause(joinExpr); AppendJoinClause(joinExpr);
return this; return this;
} }
@@ -267,6 +276,58 @@ namespace DynamORM.Builders.Implementation
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable> item in selectors)
AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable> item in selectors)
AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable> item in selectors)
AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable> item in selectors)
AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> GroupBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors) public IDynamicTypedSelectQueryBuilder<T> GroupBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors)
{ {
if (selector == null) if (selector == null)
@@ -299,6 +360,58 @@ namespace DynamORM.Builders.Implementation
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression> item in selectors)
AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression> item in selectors)
AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression> item in selectors)
AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression> item in selectors)
AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> OrderBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors) public IDynamicTypedSelectQueryBuilder<T> OrderBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors)
{ {
if (selector == null) if (selector == null)
@@ -331,6 +444,58 @@ namespace DynamORM.Builders.Implementation
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression> item in selectors)
AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression> item in selectors)
AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression> item in selectors)
AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2)));
return this;
}
public IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression>[] selectors)
{
if (selector == null)
throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
if (selectors != null)
foreach (Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression> item in selectors)
AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3)));
return this;
}
public new IDynamicTypedSelectQueryBuilder<T> Top(int? top) public new IDynamicTypedSelectQueryBuilder<T> Top(int? top)
{ {
base.Top(top); base.Top(top);
@@ -375,29 +540,93 @@ namespace DynamORM.Builders.Implementation
if (predicate == null) if (predicate == null)
throw new ArgumentNullException("predicate"); throw new ArgumentNullException("predicate");
string condition = RenderSqlPredicate(predicate); AppendSqlCondition(RenderSqlPredicate(predicate), false);
if (string.IsNullOrEmpty(WhereCondition))
WhereCondition = condition;
else
WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition);
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0))), false);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1))), false);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2))), false);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3))), false);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> HavingSql(Func<TypedTableContext<T>, TypedSqlPredicate> predicate) public IDynamicTypedSelectQueryBuilder<T> HavingSql(Func<TypedTableContext<T>, TypedSqlPredicate> predicate)
{ {
if (predicate == null) if (predicate == null)
throw new ArgumentNullException("predicate"); throw new ArgumentNullException("predicate");
string condition = RenderSqlPredicate(predicate); AppendSqlCondition(RenderSqlPredicate(predicate), true);
if (string.IsNullOrEmpty(HavingCondition))
HavingCondition = condition;
else
HavingCondition = string.Format("{0} AND {1}", HavingCondition, condition);
return this; return this;
} }
public IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0))), true);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1))), true);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2))), true);
return this;
}
public IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext<TJoin1>(0), GetJoinedContext<TJoin2>(1), GetJoinedContext<TJoin3>(2), GetJoinedContext<TJoin4>(3))), true);
return this;
}
public new IDynamicTypedSelectQueryBuilder<T> Having(DynamicColumn column) public new IDynamicTypedSelectQueryBuilder<T> Having(DynamicColumn column)
{ {
base.Having(column); base.Having(column);
@@ -446,8 +675,15 @@ namespace DynamORM.Builders.Implementation
if (selector == null) if (selector == null)
throw new ArgumentNullException("selector"); throw new ArgumentNullException("selector");
AddSelectSqlSelector(selector(GetRootContext()));
}
private void AddSelectSqlSelector(TypedSqlSelectable item)
{
if (item == null)
throw new ArgumentNullException("item");
TypedSqlRenderContext context = new TypedSqlRenderContext(this); TypedSqlRenderContext context = new TypedSqlRenderContext(this);
TypedSqlSelectable item = selector(new TypedTableContext<T>(GetRootAliasOrTableName()));
string rendered = item.Render(context); string rendered = item.Render(context);
_select = string.IsNullOrEmpty(_select) ? rendered : string.Format("{0}, {1}", _select, rendered); _select = string.IsNullOrEmpty(_select) ? rendered : string.Format("{0}, {1}", _select, rendered);
} }
@@ -476,8 +712,15 @@ namespace DynamORM.Builders.Implementation
if (selector == null) if (selector == null)
throw new ArgumentNullException("selector"); throw new ArgumentNullException("selector");
AddGroupBySqlSelector(selector(GetRootContext()));
}
private void AddGroupBySqlSelector(TypedSqlExpression item)
{
if (item == null)
throw new ArgumentNullException("item");
TypedSqlRenderContext context = new TypedSqlRenderContext(this); TypedSqlRenderContext context = new TypedSqlRenderContext(this);
TypedSqlExpression item = selector(new TypedTableContext<T>(GetRootAliasOrTableName()));
string rendered = item.Render(context); string rendered = item.Render(context);
_groupby = string.IsNullOrEmpty(_groupby) ? rendered : string.Format("{0}, {1}", _groupby, rendered); _groupby = string.IsNullOrEmpty(_groupby) ? rendered : string.Format("{0}, {1}", _groupby, rendered);
} }
@@ -503,16 +746,28 @@ namespace DynamORM.Builders.Implementation
if (selector == null) if (selector == null)
throw new ArgumentNullException("selector"); throw new ArgumentNullException("selector");
AddOrderBySqlSelector(selector(GetRootContext()));
}
private void AddOrderBySqlSelector(TypedSqlOrderExpression item)
{
TypedSqlRenderContext context = new TypedSqlRenderContext(this); TypedSqlRenderContext context = new TypedSqlRenderContext(this);
TypedSqlOrderExpression item = selector(new TypedTableContext<T>(GetRootAliasOrTableName()));
string rendered = item.Render(context); string rendered = item.Render(context);
_orderby = string.IsNullOrEmpty(_orderby) ? rendered : string.Format("{0}, {1}", _orderby, rendered); _orderby = string.IsNullOrEmpty(_orderby) ? rendered : string.Format("{0}, {1}", _orderby, rendered);
} }
private string RenderSqlPredicate(Func<TypedTableContext<T>, TypedSqlPredicate> predicate) private string RenderSqlPredicate(Func<TypedTableContext<T>, TypedSqlPredicate> predicate)
{ {
return RenderSqlPredicate(predicate(GetRootContext()));
}
private string RenderSqlPredicate(TypedSqlPredicate predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
TypedSqlRenderContext context = new TypedSqlRenderContext(this); TypedSqlRenderContext context = new TypedSqlRenderContext(this);
return predicate(new TypedTableContext<T>(GetRootAliasOrTableName())).Render(context); return predicate.Render(context);
} }
private string ParseTypedCondition(Expression expression) private string ParseTypedCondition(Expression expression)
@@ -690,6 +945,50 @@ namespace DynamORM.Builders.Implementation
return string.IsNullOrEmpty(table.Alias) ? table.Name : table.Alias; return string.IsNullOrEmpty(table.Alias) ? table.Name : table.Alias;
} }
private TypedTableContext<T> GetRootContext()
{
return new TypedTableContext<T>(GetRootAliasOrTableName());
}
private TypedTableContext<TJoin> GetJoinedContext<TJoin>(int index)
{
if (index < 0 || index >= _typedJoins.Count)
throw new InvalidOperationException(string.Format("Typed join context at position {0} is not available.", index + 1));
TypedJoinInfo join = _typedJoins[index];
if (join.ModelType != typeof(TJoin))
throw new InvalidOperationException(string.Format("Typed join context at position {0} is {1}, not {2}.", index + 1, join.ModelType.FullName, typeof(TJoin).FullName));
return new TypedTableContext<TJoin>(join.Alias);
}
private void RegisterTypedJoin(Type modelType, string alias)
{
_typedJoins.Add(new TypedJoinInfo
{
ModelType = modelType,
Alias = alias
});
}
private void AppendSqlCondition(string condition, bool having)
{
if (having)
{
if (string.IsNullOrEmpty(HavingCondition))
HavingCondition = condition;
else
HavingCondition = string.Format("{0} AND {1}", HavingCondition, condition);
}
else
{
if (string.IsNullOrEmpty(WhereCondition))
WhereCondition = condition;
else
WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition);
}
}
private static bool IsMemberFromTypedParameter(Expression expression) private static bool IsMemberFromTypedParameter(Expression expression)
{ {
var member = expression as MemberExpression; var member = expression as MemberExpression;