diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs index e9ebcd5..7fb9fe2 100644 --- a/AmalgamationTool/DynamORM.Amalgamation.cs +++ b/AmalgamationTool/DynamORM.Amalgamation.cs @@ -2,31 +2,6 @@ * DynamORM - Dynamic Object-Relational Mapping library. * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) * All rights reserved. - * - * Some of methods in this code file is based on Kerosene ORM solution - * for parsing dynamic lambda expressions by Moisés Barba Cebeira - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. */ using DynamORM.Builders.Extensions; @@ -35,6 +10,7 @@ using DynamORM.Builders; using DynamORM.Helpers.Dynamics; using DynamORM.Helpers; using DynamORM.Mapper; +using DynamORM.TypedSql; using DynamORM.Validation; using System.Collections.Concurrent; using System.Collections.Generic; @@ -1976,6 +1952,43 @@ namespace DynamORM } } /// Adds to the FROM clause using . + /// Type which can be represented in database. + /// Table alias. + /// use no lock. + /// This instance to permit chaining. + public virtual IDynamicTypedSelectQueryBuilder FromTyped(string alias = null, bool noLock = false) + { + // TODO: Make it more readable and maitainable + DynamicTypedSelectQueryBuilder builder = new DynamicTypedSelectQueryBuilder(this); + + if (noLock) + { + if (string.IsNullOrEmpty(alias)) + builder.From(x => x(typeof(T)).NoLock()); + else + builder.From(x => x(typeof(T)).As(alias).NoLock()); + } + else + { + if (string.IsNullOrEmpty(alias)) + builder.From(x => x(typeof(T))); + else + builder.From(x => x(typeof(T)).As(alias)); + } + return builder; + } + /// Adds to the FROM clause using a typed scope builder with evolving join arity. + /// Type which can be represented in database. + /// Table alias. + /// use no lock. + /// Scope builder instance. + public virtual IDynamicTypedSelectScopeQueryBuilder FromTypedScope(string alias = null, bool noLock = false) + { + DynamicTypedSelectQueryBuilder builder = (DynamicTypedSelectQueryBuilder)FromTyped(alias, noLock); + string resolvedAlias = string.IsNullOrEmpty(alias) ? builder.Tables[0].Alias ?? builder.Tables[0].Name : alias; + return new DynamicTypedSelectScopeQueryBuilder(builder, resolvedAlias); + } + /// Adds to the FROM clause using . /// Type which can be represented in database. /// This instance to permit chaining. public virtual IDynamicSelectQueryBuilder From(Type t) @@ -2005,6 +2018,13 @@ namespace DynamORM return new DynamicInsertQueryBuilder(this).Table(typeof(T)); } /// Adds to the INSERT INTO clause using . + /// Type which can be represented in database. + /// This instance to permit chaining. + public virtual IDynamicTypedInsertQueryBuilder InsertTyped() + { + return new DynamicTypedInsertQueryBuilder(this, true); + } + /// Adds to the INSERT INTO clause using . /// Type which can be represented in database. /// This instance to permit chaining. public virtual IDynamicInsertQueryBuilder Insert(Type t) @@ -2105,6 +2125,13 @@ namespace DynamORM return new DynamicUpdateQueryBuilder(this).Table(typeof(T)); } /// Adds to the UPDATE clause using . + /// Type which can be represented in database. + /// This instance to permit chaining. + public virtual IDynamicTypedUpdateQueryBuilder UpdateTyped() + { + return new DynamicTypedUpdateQueryBuilder(this, true); + } + /// Adds to the UPDATE clause using . /// Type which can be represented in database. /// This instance to permit chaining. public virtual IDynamicUpdateQueryBuilder Update(Type t) @@ -2314,6 +2341,13 @@ namespace DynamORM return new DynamicDeleteQueryBuilder(this).Table(typeof(T)); } /// Adds to the DELETE FROM clause using . + /// Type which can be represented in database. + /// This instance to permit chaining. + public virtual IDynamicTypedDeleteQueryBuilder DeleteTyped() + { + return new DynamicTypedDeleteQueryBuilder(this, true); + } + /// Adds to the DELETE FROM clause using . /// Type which can be represented in database. /// This instance to permit chaining. public virtual IDynamicDeleteQueryBuilder Delete(Type t) @@ -6794,6 +6828,18 @@ namespace DynamORM } namespace Builders { + /// Typed join kind used by typed fluent builder APIs. + public enum DynamicJoinType + { + Inner = 0, + Join, + Left, + Right, + Full, + LeftOuter, + RightOuter, + FullOuter + } /// Dynamic delete query builder interface. /// This interface it publicly available. Implementation should be hidden. public interface IDynamicDeleteQueryBuilder : IDynamicQueryBuilder @@ -7161,6 +7207,347 @@ namespace DynamORM #endregion Top/Limit/Offset/Distinct } + /// Typed delete query builder for mapped entities. + /// Mapped entity type. + public interface IDynamicTypedDeleteQueryBuilder : IDynamicDeleteQueryBuilder + { + /// Add typed where predicate using mapped properties. + /// Predicate to parse. + /// Builder instance. + IDynamicTypedDeleteQueryBuilder Where(Expression> predicate); + + /// Add typed SQL DSL where predicate. + IDynamicTypedDeleteQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate); + } + /// Typed insert query builder for mapped entities. + /// Mapped entity type. + public interface IDynamicTypedInsertQueryBuilder : IDynamicInsertQueryBuilder + { + /// Add typed insert assignment using mapped property selector. + /// Property type. + /// Property selector. + /// Value to insert. + /// Builder instance. + IDynamicTypedInsertQueryBuilder Insert(Expression> selector, object value); + + /// Add values from mapped object. + /// Mapped object value. + /// Builder instance. + IDynamicTypedInsertQueryBuilder Insert(T value); + + /// Add typed SQL DSL insert assignment. + IDynamicTypedInsertQueryBuilder InsertSql(Expression> selector, Func, TypedSqlExpression> valueFactory); + + /// Add typed SQL DSL insert assignments from object projection. + IDynamicTypedInsertQueryBuilder InsertSql(Func, object> values); + } + /// Typed select query builder for mapped entities. + /// Mapped entity type. + public interface IDynamicTypedSelectQueryBuilder : IDynamicSelectQueryBuilder + { + /// Add typed join to mapped table. + /// Joined mapped entity type. + /// Join ON predicate. + /// Optional alias for joined table. + /// Join type. + /// Adds NOLOCK hint to joined source when supported by provider options. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Join(Expression> on, string alias = null, DynamicJoinType joinType = DynamicJoinType.Inner, bool noLock = false); + + /// Add typed join with custom join type text (for example: CROSS APPLY). + /// Joined mapped entity type. + /// Optional join ON predicate. + /// Optional alias for joined table. + /// Join type text. + /// Adds NOLOCK hint to joined source when supported by provider options. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Join(Expression> on, string alias, string joinType, bool noLock = false); + + /// Add typed join using join-spec builder syntax (As(), join kind and On()). + /// Joined mapped entity type. + /// Join specification builder callback. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Join(Func, TypedJoinBuilder> specification); + + /// Add typed where predicate using mapped properties. + /// Predicate to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Where(Expression> predicate); + + /// Add typed having predicate using mapped properties. + /// Predicate to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Having(Expression> predicate); + + /// Add typed selected columns using mapped properties. + /// Projection type. + /// Selector to parse. + /// Additional selectors to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Select(Expression> selector, params Expression>[] selectors); + + /// Add typed group by columns using mapped properties. + /// Projection type. + /// Selector to parse. + /// Additional selectors to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder GroupBy(Expression> selector, params Expression>[] selectors); + + /// Add typed order by columns using mapped properties. Supports Asc()/Desc(). + /// Projection type. + /// Selector to parse. + /// Additional selectors to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder OrderBy(Expression> selector, params Expression>[] selectors); + + /// Add typed SQL DSL select items. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedSqlSelectable> selector, params Func, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL where predicate. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL group by expressions. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedSqlExpression> selector, params Func, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL order by expressions. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedSqlOrderExpression> selector, params Func, TypedSqlOrderExpression>[] selectors); + + /// Add typed SQL DSL select items using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL select items using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL select items using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL select items using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL where predicate using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL where predicate using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL where predicate using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL where predicate using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL group-by expression using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL group-by expression using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL group-by expression using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL group-by expression using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL order-by expression using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedSqlOrderExpression>[] selectors); + + /// Add typed SQL DSL order-by expression using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + + /// Add typed SQL DSL order-by expression using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + + /// Add typed SQL DSL order-by expression using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedSqlSelectable> selector, params Func, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedSqlExpression> selector, params Func, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedSqlOrderExpression> selector, params Func, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + /// Typed update query builder for mapped entities. + /// Mapped entity type. + public interface IDynamicTypedUpdateQueryBuilder : IDynamicUpdateQueryBuilder + { + /// Add typed where predicate using mapped properties. + /// Predicate to parse. + /// Builder instance. + IDynamicTypedUpdateQueryBuilder Where(Expression> predicate); + + /// Add typed assignment using mapped property selector. + /// Property type. + /// Property selector. + /// Assigned value. + /// Builder instance. + IDynamicTypedUpdateQueryBuilder Set(Expression> selector, object value); + + /// Add update values from mapped object. + /// Mapped object value. + /// Builder instance. + IDynamicTypedUpdateQueryBuilder Values(T value); + + /// Add typed SQL DSL where predicate. + IDynamicTypedUpdateQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL assignment. + IDynamicTypedUpdateQueryBuilder SetSql(Expression> selector, Func, TypedSqlExpression> valueFactory); + + /// Add typed SQL DSL assignments from object projection. + IDynamicTypedUpdateQueryBuilder SetSql(Func, object> values); + } /// Dynamic update query builder interface. /// This interface it publicly available. Implementation should be hidden. public interface IDynamicUpdateQueryBuilder : IDynamicQueryBuilder @@ -7290,6 +7677,590 @@ namespace DynamORM /// Gets table schema. Dictionary Schema { get; } } + /// Marker extensions for typed fluent builder expressions. + public static class TypedFluentExtensions + { + /// Marks select projection alias in typed expressions. + public static T As(this T source, string alias) + { + return source; + } + /// Marks ascending order in typed order expressions. + public static T Asc(this T source) + { + return source; + } + /// Marks descending order in typed order expressions. + public static T Desc(this T source) + { + return source; + } + } + /// Typed join specification builder used by typed fluent select queries. + /// Left side mapped type. + /// Right side mapped type. + public class TypedJoinBuilder + { + internal TypedJoinBuilder() + { + JoinType = DynamicJoinType.Join; + } + /// Gets join alias. + public string Alias { get; private set; } + + /// Gets join type. + public DynamicJoinType JoinType { get; private set; } + + /// Gets custom join type text. + public string CustomJoinType { get; private set; } + + /// Gets a value indicating whether joined source should use NOLOCK. + public bool UseNoLock { get; private set; } + + /// Gets ON predicate. + public Expression> OnPredicate { get; private set; } + + /// Gets raw ON condition. + public string OnRawCondition { get; private set; } + + /// Gets typed SQL DSL ON specification. + public Func, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + + /// Sets join alias. + public TypedJoinBuilder As(string alias) + { + Alias = alias; + return this; + } + /// Sets INNER JOIN. + public TypedJoinBuilder Inner() + { + JoinType = DynamicJoinType.Inner; + CustomJoinType = null; + return this; + } + /// Sets plain JOIN. + public TypedJoinBuilder Join() + { + JoinType = DynamicJoinType.Join; + CustomJoinType = null; + return this; + } + /// Sets LEFT JOIN. + public TypedJoinBuilder Left() + { + JoinType = DynamicJoinType.Left; + CustomJoinType = null; + return this; + } + /// Sets RIGHT JOIN. + public TypedJoinBuilder Right() + { + JoinType = DynamicJoinType.Right; + CustomJoinType = null; + return this; + } + /// Sets FULL JOIN. + public TypedJoinBuilder Full() + { + JoinType = DynamicJoinType.Full; + CustomJoinType = null; + return this; + } + /// Sets LEFT OUTER JOIN. + public TypedJoinBuilder LeftOuter() + { + JoinType = DynamicJoinType.LeftOuter; + CustomJoinType = null; + return this; + } + /// Sets RIGHT OUTER JOIN. + public TypedJoinBuilder RightOuter() + { + JoinType = DynamicJoinType.RightOuter; + CustomJoinType = null; + return this; + } + /// Sets FULL OUTER JOIN. + public TypedJoinBuilder FullOuter() + { + JoinType = DynamicJoinType.FullOuter; + CustomJoinType = null; + return this; + } + /// Sets custom join type text (for example: CROSS APPLY). + public TypedJoinBuilder Type(string joinType) + { + if (string.IsNullOrEmpty(joinType)) + throw new ArgumentNullException("joinType"); + + CustomJoinType = joinType.Trim(); + return this; + } + /// Marks joined source with NOLOCK hint. + public TypedJoinBuilder NoLock(bool use = true) + { + UseNoLock = use; + return this; + } + /// Sets ON predicate. + public TypedJoinBuilder On(Expression> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + OnPredicate = predicate; + OnRawCondition = null; + OnSqlPredicate = null; + return this; + } + /// Sets raw ON clause (without the ON keyword). + public TypedJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + + OnRawCondition = condition.Trim(); + OnPredicate = null; + OnSqlPredicate = null; + return this; + } + /// Sets typed SQL DSL ON predicate. + public TypedJoinBuilder OnSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + OnSqlPredicate = predicate; + OnPredicate = null; + OnRawCondition = null; + return this; + } + } + /// Compatibility and convenience extensions for typed joins. + public static class TypedJoinExtensions + { + /// + /// Legacy compatibility helper. Prefer . + /// + public static IDynamicTypedSelectQueryBuilder JoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + string alias, + Expression> on, + string joinType = "INNER JOIN") + { + if (builder == null) throw new ArgumentNullException("builder"); + if (on == null) throw new ArgumentNullException("on"); + + DynamicJoinType jt = DynamicJoinType.Inner; + string normalized = (joinType ?? string.Empty).Trim().ToUpperInvariant(); + + if (normalized == "JOIN") + jt = DynamicJoinType.Join; + else if (normalized == "LEFT OUTER JOIN" || normalized == "LEFT OUTER") + jt = DynamicJoinType.LeftOuter; + else if (normalized == "RIGHT OUTER JOIN" || normalized == "RIGHT OUTER") + jt = DynamicJoinType.RightOuter; + else if (normalized == "FULL OUTER JOIN" || normalized == "FULL OUTER") + jt = DynamicJoinType.FullOuter; + else if (normalized == "LEFT JOIN" || normalized == "LEFT") + jt = DynamicJoinType.Left; + else if (normalized == "RIGHT JOIN" || normalized == "RIGHT") + jt = DynamicJoinType.Right; + else if (normalized == "FULL JOIN" || normalized == "FULL") + jt = DynamicJoinType.Full; + else if (normalized != "INNER JOIN" && normalized != "INNER" && normalized != "JOIN") + return builder.Join(on, alias, joinType); + + return builder.Join(on, alias, jt); + } + /// Convenience typed INNER JOIN extension. + public static IDynamicTypedSelectQueryBuilder InnerJoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + Expression> on, + string alias = null) + { + return builder.Join(on, alias, DynamicJoinType.Inner); + } + /// Convenience typed LEFT JOIN extension. + public static IDynamicTypedSelectQueryBuilder LeftJoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + Expression> on, + string alias = null) + { + return builder.Join(on, alias, DynamicJoinType.Left); + } + /// Convenience typed RIGHT JOIN extension. + public static IDynamicTypedSelectQueryBuilder RightJoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + Expression> on, + string alias = null) + { + return builder.Join(on, alias, DynamicJoinType.Right); + } + /// Convenience typed FULL JOIN extension. + public static IDynamicTypedSelectQueryBuilder FullJoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + Expression> on, + string alias = null) + { + return builder.Join(on, alias, DynamicJoinType.Full); + } + } + public abstract class TypedScopeJoinBuilderBase + where TSelf : TypedScopeJoinBuilderBase + { + public string Alias { get; private set; } + public DynamicJoinType JoinType { get; private set; } + public string CustomJoinType { get; private set; } + public bool UseNoLock { get; private set; } + + protected TypedScopeJoinBuilderBase() + { + JoinType = DynamicJoinType.Join; + } + public TSelf As(string alias) { Alias = alias; return (TSelf)this; } + public TSelf Inner() { JoinType = DynamicJoinType.Inner; CustomJoinType = null; return (TSelf)this; } + public TSelf Join() { JoinType = DynamicJoinType.Join; CustomJoinType = null; return (TSelf)this; } + public TSelf Left() { JoinType = DynamicJoinType.Left; CustomJoinType = null; return (TSelf)this; } + public TSelf Right() { JoinType = DynamicJoinType.Right; CustomJoinType = null; return (TSelf)this; } + public TSelf Full() { JoinType = DynamicJoinType.Full; CustomJoinType = null; return (TSelf)this; } + public TSelf LeftOuter() { JoinType = DynamicJoinType.LeftOuter; CustomJoinType = null; return (TSelf)this; } + public TSelf RightOuter() { JoinType = DynamicJoinType.RightOuter; CustomJoinType = null; return (TSelf)this; } + public TSelf FullOuter() { JoinType = DynamicJoinType.FullOuter; CustomJoinType = null; return (TSelf)this; } + public TSelf Type(string joinType) { if (string.IsNullOrEmpty(joinType)) throw new ArgumentNullException("joinType"); CustomJoinType = joinType.Trim(); return (TSelf)this; } + public TSelf NoLock(bool use = true) { UseNoLock = use; return (TSelf)this; } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } namespace Extensions { internal static class DynamicHavingQueryExtensions @@ -7876,8 +8847,8 @@ namespace DynamORM /// Implementation of dynamic insert query builder. internal class DynamicInsertQueryBuilder : DynamicModifyBuilder, IDynamicInsertQueryBuilder { - private string _columns; - private string _values; + protected string _columns; + protected string _values; /// /// Initializes a new instance of the class. @@ -8985,11 +9956,11 @@ namespace DynamORM private int? _offset = null; private bool _distinct = false; - private string _select; + protected string _select; private string _from; - private string _join; - private string _groupby; - private string _orderby; + protected string _join; + protected string _groupby; + protected string _orderby; #region IQueryWithHaving @@ -10304,10 +11275,2579 @@ namespace DynamORM } #endregion IExtendedDisposable } + /// Typed wrapper over with property-to-column translation. + /// Mapped entity type. + internal class DynamicTypedDeleteQueryBuilder : DynamicDeleteQueryBuilder, IDynamicTypedDeleteQueryBuilder + { + internal DynamicTypedDeleteQueryBuilder(DynamicDatabase db) + : this(db, false) + { + } + internal DynamicTypedDeleteQueryBuilder(DynamicDatabase db, bool mapType) + : base(db) + { + if (mapType) + this.Table(typeof(T)); + else + this.Table(typeof(T).Name); + } + public IDynamicTypedDeleteQueryBuilder Where(Expression> predicate) + { + TypedModifyHelper.ApplyWhere((c, o, v) => base.Where(c, o, v), predicate); + return this; + } + public IDynamicTypedDeleteQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate) + { + string condition = TypedModifyHelper.RenderPredicate(predicate, null, RenderValue, Database.DecorateName, RenderSubQuery); + if (string.IsNullOrEmpty(WhereCondition)) + WhereCondition = condition; + else + WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition); + + return this; + } + public new IDynamicTypedDeleteQueryBuilder Where(Func func) + { + base.Where(func); + return this; + } + public new IDynamicTypedDeleteQueryBuilder Where(DynamicColumn column) + { + base.Where(column); + return this; + } + public new IDynamicTypedDeleteQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value) + { + base.Where(column, op, value); + return this; + } + public new IDynamicTypedDeleteQueryBuilder Where(string column, object value) + { + base.Where(column, value); + return this; + } + public new IDynamicTypedDeleteQueryBuilder Where(object conditions, bool schema = false) + { + base.Where(conditions, schema); + return this; + } + private string RenderValue(object value) + { + if (value == null) + return "NULL"; + + DynamicSchemaColumn? columnSchema = null; + return ParseConstant(value, Parameters, columnSchema); + } + private string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query) + { + foreach (KeyValuePair item in query.Parameters) + if (!Parameters.ContainsKey(item.Key)) + Parameters.Add(item.Key, item.Value); + + return query.CommandText(); + } + } + /// Typed wrapper over with property-to-column translation. + /// Mapped entity type. + internal class DynamicTypedInsertQueryBuilder : DynamicInsertQueryBuilder, IDynamicTypedInsertQueryBuilder + { + internal DynamicTypedInsertQueryBuilder(DynamicDatabase db) + : this(db, false) + { + } + internal DynamicTypedInsertQueryBuilder(DynamicDatabase db, bool mapType) + : base(db) + { + if (mapType) + this.Table(typeof(T)); + else + this.Table(typeof(T).Name); + } + public IDynamicTypedInsertQueryBuilder Insert(Expression> selector, object value) + { + base.Insert(TypedModifyHelper.GetMappedColumn(selector), value); + return this; + } + public IDynamicTypedInsertQueryBuilder Insert(T value) + { + base.Insert(value); + return this; + } + public IDynamicTypedInsertQueryBuilder InsertSql(Expression> selector, Func, TypedSqlExpression> valueFactory) + { + string column = FixObjectName(TypedModifyHelper.GetMappedColumn(selector), onlyColumn: true); + string value = TypedModifyHelper.RenderExpression(valueFactory, null, RenderValue, Database.DecorateName, RenderSubQuery); + + _columns = _columns == null ? column : string.Format("{0}, {1}", _columns, column); + _values = _values == null ? value : string.Format("{0}, {1}", _values, value); + return this; + } + public IDynamicTypedInsertQueryBuilder InsertSql(Func, object> values) + { + if (values == null) + throw new ArgumentNullException("values"); + + object data = values(new TypedTableContext(null)); + foreach (KeyValuePair item in data.ToDictionary()) + { + string column = FixObjectName(TypedModifyHelper.GetMappedColumnByName(typeof(T), item.Key), onlyColumn: true); + string value = (item.Value as TypedSqlExpression) != null + ? TypedModifyHelper.RenderExpression(u => (TypedSqlExpression)item.Value, null, RenderValue, Database.DecorateName, RenderSubQuery) + : RenderValue(item.Value); + + _columns = _columns == null ? column : string.Format("{0}, {1}", _columns, column); + _values = _values == null ? value : string.Format("{0}, {1}", _values, value); + } + return this; + } + public new IDynamicTypedInsertQueryBuilder Values(Func fn, params Func[] func) + { + base.Values(fn, func); + return this; + } + public new IDynamicTypedInsertQueryBuilder Insert(string column, object value) + { + base.Insert(column, value); + return this; + } + public new IDynamicTypedInsertQueryBuilder Insert(object o) + { + base.Insert(o); + return this; + } + private string RenderValue(object value) + { + if (value == null) + return "NULL"; + + DynamicSchemaColumn? columnSchema = null; + return ParseConstant(value, Parameters, columnSchema); + } + private string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query) + { + foreach (KeyValuePair item in query.Parameters) + if (!Parameters.ContainsKey(item.Key)) + Parameters.Add(item.Key, item.Value); + + return query.CommandText(); + } + } + /// Typed wrapper over with property-to-column translation. + /// Mapped entity type. + internal class DynamicTypedSelectQueryBuilder : DynamicSelectQueryBuilder, IDynamicTypedSelectQueryBuilder + { + private sealed class TypedJoinInfo + { + public Type ModelType { get; set; } + public string Alias { get; set; } + } + private sealed class TypedSqlRenderContext : ITypedSqlRenderContext + { + private readonly DynamicTypedSelectQueryBuilder _builder; + + public TypedSqlRenderContext(DynamicTypedSelectQueryBuilder builder) + { + _builder = builder; + } + public string ResolveColumn(Type modelType, string memberName, string alias) + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(modelType); + if (mapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", modelType.FullName)); + + string mappedColumn = mapper.PropertyMap.TryGetValue(memberName) + ?? mapper.PropertyMap.Where(x => string.Equals(x.Key, memberName, StringComparison.OrdinalIgnoreCase)).Select(x => x.Value).FirstOrDefault() + ?? memberName; + + return string.IsNullOrEmpty(alias) + ? _builder.Database.DecorateName(mappedColumn) + : string.Format("{0}.{1}", alias, _builder.Database.DecorateName(mappedColumn)); + } + public string RenderValue(object value) + { + if (value == null) + return "NULL"; + + DynamicSchemaColumn? columnSchema = null; + return _builder.ParseConstant(value, _builder.Parameters, columnSchema); + } + public string DecorateName(string name) + { + return _builder.Database.DecorateName(name); + } + public string RenderSubQuery(IDynamicSelectQueryBuilder query) + { + if (query == null) + throw new ArgumentNullException("query"); + + foreach (var item in query.Parameters) + if (!_builder.Parameters.ContainsKey(item.Key)) + _builder.Parameters.Add(item.Key, item.Value); + + return query.CommandText(); + } + } + private readonly DynamicTypeMap _mapper; + private readonly List _typedJoins = new List(); + + public DynamicTypedSelectQueryBuilder(DynamicDatabase db) + : base(db) + { + _mapper = DynamicMapperCache.GetMapper() + ?? throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", typeof(T).FullName)); + } + public IDynamicTypedSelectQueryBuilder Where(Expression> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + string condition = ParseTypedCondition(predicate.Body); + + if (string.IsNullOrEmpty(WhereCondition)) + WhereCondition = condition; + else + WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition); + + return this; + } + public IDynamicTypedSelectQueryBuilder Join(Expression> on, string alias = null, DynamicJoinType joinType = DynamicJoinType.Inner, bool noLock = false) + { + return Join(on, alias, GetJoinKeyword(joinType), noLock); + } + public IDynamicTypedSelectQueryBuilder Join(Expression> on, string alias, string joinType, bool noLock = false) + { + if (string.IsNullOrEmpty(joinType)) + throw new ArgumentNullException("joinType"); + + DynamicTypeMap rightMapper = DynamicMapperCache.GetMapper(typeof(TRight)); + if (rightMapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", typeof(TRight).FullName)); + + string rightTable = rightMapper.Table == null || string.IsNullOrEmpty(rightMapper.Table.Name) + ? typeof(TRight).Name + : rightMapper.Table.Name; + string rightOwner = rightMapper.Table == null ? null : rightMapper.Table.Owner; + string rightAlias = string.IsNullOrEmpty(alias) ? "t" + (Tables.Count + 1).ToString() : alias; + + string leftPrefix = GetRootAliasOrTableName(); + if (string.IsNullOrEmpty(leftPrefix)) + throw new InvalidOperationException("Join requires source table to be present."); + + string condition = null; + if (on != null) + condition = ParseTypedJoinCondition(on.Body, leftPrefix, rightAlias, _mapper, rightMapper, on.Parameters[0], on.Parameters[1]); + + string ownerPrefix = string.IsNullOrEmpty(rightOwner) ? string.Empty : Database.DecorateName(rightOwner) + "."; + string rightTableExpr = ownerPrefix + Database.DecorateName(rightTable); + string joinExpr = string.Format("{0} {1} AS {2}", + joinType.Trim(), + rightTableExpr, + rightAlias); + + if (SupportNoLock && noLock) + joinExpr += " WITH(NOLOCK)"; + + if (!string.IsNullOrEmpty(condition)) + joinExpr += string.Format(" ON {0}", condition); + + RegisterTypedJoin(typeof(TRight), rightAlias); + AppendJoinClause(joinExpr); + return this; + } + public IDynamicTypedSelectQueryBuilder Join(Func, TypedJoinBuilder> specification) + { + if (specification == null) + throw new ArgumentNullException("specification"); + + TypedJoinBuilder spec = specification(new TypedJoinBuilder()); + if (spec == null) + throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + if (spec.OnPredicate != null) + return Join(spec.OnPredicate, spec.Alias, spec.CustomJoinType ?? GetJoinKeyword(spec.JoinType), spec.UseNoLock); + + DynamicTypeMap rightMapper = DynamicMapperCache.GetMapper(typeof(TRight)); + if (rightMapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", typeof(TRight).FullName)); + + string rightTable = rightMapper.Table == null || string.IsNullOrEmpty(rightMapper.Table.Name) + ? typeof(TRight).Name + : rightMapper.Table.Name; + string rightOwner = rightMapper.Table == null ? null : rightMapper.Table.Owner; + string rightAlias = string.IsNullOrEmpty(spec.Alias) ? "t" + (Tables.Count + 1).ToString() : spec.Alias; + + string ownerPrefix = string.IsNullOrEmpty(rightOwner) ? string.Empty : Database.DecorateName(rightOwner) + "."; + string rightTableExpr = ownerPrefix + Database.DecorateName(rightTable); + string joinExpr = string.Format("{0} {1} AS {2}", + (spec.CustomJoinType ?? GetJoinKeyword(spec.JoinType)).Trim(), + rightTableExpr, + rightAlias); + + if (SupportNoLock && spec.UseNoLock) + joinExpr += " WITH(NOLOCK)"; + + if (spec.OnSqlPredicate != null) + { + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + joinExpr += string.Format(" ON {0}", spec.OnSqlPredicate(new TypedTableContext(GetRootAliasOrTableName()), new TypedTableContext(rightAlias)).Render(context)); + } + else if (!string.IsNullOrEmpty(spec.OnRawCondition)) + joinExpr += string.Format(" ON {0}", spec.OnRawCondition); + + RegisterTypedJoin(typeof(TRight), rightAlias); + AppendJoinClause(joinExpr); + return this; + } + public new IDynamicTypedSelectQueryBuilder Join(params Func[] func) + { + base.Join(func); + return this; + } + public new IDynamicTypedSelectQueryBuilder Where(DynamicColumn column) + { + base.Where(column); + return this; + } + public new IDynamicTypedSelectQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value) + { + base.Where(column, op, value); + return this; + } + public new IDynamicTypedSelectQueryBuilder Where(string column, object value) + { + base.Where(column, value); + return this; + } + public new IDynamicTypedSelectQueryBuilder Where(object conditions, bool schema = false) + { + base.Where(conditions, schema); + return this; + } + public IDynamicTypedSelectQueryBuilder Select(Expression> selector, params Expression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSelector(selector); + + if (selectors != null) + foreach (var s in selectors) + { + if (s == null) + throw new ArgumentNullException("selectors", "Array of selectors cannot contain null."); + + AddSelectSelector(s); + } + return this; + } + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedSqlSelectable> selector, params Func, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector); + if (selectors != null) + foreach (Func, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item); + + return this; + } + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext(0))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext(0))); + + return this; + } + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + + return this; + } + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + + return this; + } + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + + return this; + } + public IDynamicTypedSelectQueryBuilder GroupBy(Expression> selector, params Expression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySelector(selector); + + if (selectors != null) + foreach (var s in selectors) + { + if (s == null) + throw new ArgumentNullException("selectors", "Array of selectors cannot contain null."); + + AddGroupBySelector(s); + } + return this; + } + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedSqlExpression> selector, params Func, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector); + if (selectors != null) + foreach (Func, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item); + + return this; + } + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext(0))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext(0))); + + return this; + } + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + + return this; + } + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + + return this; + } + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + + return this; + } + public IDynamicTypedSelectQueryBuilder OrderBy(Expression> selector, params Expression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySelector(selector); + + if (selectors != null) + foreach (var s in selectors) + { + if (s == null) + throw new ArgumentNullException("selectors", "Array of selectors cannot contain null."); + + AddOrderBySelector(s); + } + return this; + } + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedSqlOrderExpression> selector, params Func, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector); + if (selectors != null) + foreach (Func, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item); + + return this; + } + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext(0))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext(0))); + + return this; + } + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + + return this; + } + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + + return this; + } + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + + return this; + } + public new IDynamicTypedSelectQueryBuilder Top(int? top) + { + base.Top(top); + return this; + } + public new IDynamicTypedSelectQueryBuilder Limit(int? limit) + { + base.Limit(limit); + return this; + } + public new IDynamicTypedSelectQueryBuilder Offset(int? offset) + { + base.Offset(offset); + return this; + } + public new IDynamicTypedSelectQueryBuilder Distinct(bool distinct = true) + { + base.Distinct(distinct); + return this; + } + public IDynamicTypedSelectQueryBuilder Having(Expression> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + string condition = ParseTypedCondition(predicate.Body); + + if (string.IsNullOrEmpty(HavingCondition)) + HavingCondition = condition; + else + HavingCondition = string.Format("{0} AND {1}", HavingCondition, condition); + + return this; + } + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate), false); + + return this; + } + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0))), false); + return this; + } + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))), false); + return this; + } + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))), false); + return this; + } + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))), false); + return this; + } + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate), true); + + return this; + } + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0))), true); + return this; + } + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))), true); + return this; + } + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))), true); + return this; + } + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))), true); + return this; + } + public new IDynamicTypedSelectQueryBuilder Having(DynamicColumn column) + { + base.Having(column); + return this; + } + public new IDynamicTypedSelectQueryBuilder Having(string column, DynamicColumn.CompareOperator op, object value) + { + base.Having(column, op, value); + return this; + } + public new IDynamicTypedSelectQueryBuilder Having(string column, object value) + { + base.Having(column, value); + return this; + } + public new IDynamicTypedSelectQueryBuilder Having(object conditions, bool schema = false) + { + base.Having(conditions, schema); + return this; + } + private void AddSelectSelector(Expression> selector) + { + var body = UnwrapConvert(selector.Body); + + if (body is NewExpression ne) + { + foreach (var argument in ne.Arguments) + { + var parsed = ParseTypedSelectExpression(argument); + ((IDynamicSelectQueryBuilder)this).Select(x => parsed); + } + } + else + { + var parsed = ParseTypedSelectExpression(body); + ((IDynamicSelectQueryBuilder)this).Select(x => parsed); + } + } + private void AddSelectSqlSelector(Func, TypedSqlSelectable> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext())); + } + internal void AddSelectSqlSelector(TypedSqlSelectable item) + { + if (item == null) + throw new ArgumentNullException("item"); + + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + string rendered = item.Render(context); + _select = string.IsNullOrEmpty(_select) ? rendered : string.Format("{0}, {1}", _select, rendered); + } + private void AddGroupBySelector(Expression> selector) + { + var body = UnwrapConvert(selector.Body); + + if (body is NewExpression ne) + { + foreach (var argument in ne.Arguments) + { + var parsed = ParseTypedMemberAccess(argument); + ((IDynamicSelectQueryBuilder)this).GroupBy(x => parsed); + } + } + else + { + var parsed = ParseTypedMemberAccess(body); + ((IDynamicSelectQueryBuilder)this).GroupBy(x => parsed); + } + } + private void AddGroupBySqlSelector(Func, TypedSqlExpression> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext())); + } + internal void AddGroupBySqlSelector(TypedSqlExpression item) + { + if (item == null) + throw new ArgumentNullException("item"); + + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + string rendered = item.Render(context); + _groupby = string.IsNullOrEmpty(_groupby) ? rendered : string.Format("{0}, {1}", _groupby, rendered); + } + private void AddOrderBySelector(Expression> selector) + { + var body = UnwrapConvert(selector.Body); + bool ascending = true; + + if (body is MethodCallExpression call && IsAscOrDesc(call)) + { + ascending = call.Method.Name.ToUpper() != "DESC"; + body = UnwrapConvert(call.Object ?? call.Arguments.FirstOrDefault()); + } + string main = ParseTypedMemberAccess(body); + string parsed = string.Format("{0} {1}", main, ascending ? "ASC" : "DESC"); + ((IDynamicSelectQueryBuilder)this).OrderBy(x => parsed); + } + private void AddOrderBySqlSelector(Func, TypedSqlOrderExpression> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext())); + } + internal void AddOrderBySqlSelector(TypedSqlOrderExpression item) + { + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + string rendered = item.Render(context); + _orderby = string.IsNullOrEmpty(_orderby) ? rendered : string.Format("{0}, {1}", _orderby, rendered); + } + private string RenderSqlPredicate(Func, TypedSqlPredicate> predicate) + { + return RenderSqlPredicate(predicate(GetRootContext())); + } + private string RenderSqlPredicate(TypedSqlPredicate predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + return predicate.Render(context); + } + internal string RenderScopeSqlPredicate(TypedSqlPredicate predicate) + { + return RenderSqlPredicate(predicate); + } + private string ParseTypedCondition(Expression expression) + { + expression = UnwrapConvert(expression); + + if (expression is BinaryExpression binary) + { + switch (binary.NodeType) + { + case ExpressionType.AndAlso: + case ExpressionType.And: + return string.Format("({0} AND {1})", ParseTypedCondition(binary.Left), ParseTypedCondition(binary.Right)); + case ExpressionType.OrElse: + case ExpressionType.Or: + return string.Format("({0} OR {1})", ParseTypedCondition(binary.Left), ParseTypedCondition(binary.Right)); + case ExpressionType.Equal: + case ExpressionType.NotEqual: + case ExpressionType.GreaterThan: + case ExpressionType.GreaterThanOrEqual: + case ExpressionType.LessThan: + case ExpressionType.LessThanOrEqual: + { + DynamicSchemaColumn? columnSchema = null; + string left = ParseTypedValue(binary.Left, ref columnSchema); + string right = ParseTypedValue(binary.Right, ref columnSchema); + string op = GetBinaryOperator(binary.NodeType, IsNullConstant(binary.Right)); + return string.Format("({0} {1} {2})", left, op, right); + } + } + } + if (expression is UnaryExpression unary && unary.NodeType == ExpressionType.Not) + return string.Format("(NOT {0})", ParseTypedCondition(unary.Operand)); + + if (expression is MethodCallExpression call && IsEnumerableContains(call)) + { + DynamicSchemaColumn? col = null; + return ParseTypedContains(call, ref col); + } + throw new NotSupportedException(string.Format("Typed fluent where expression is not supported: {0}", expression)); + } + private string ParseTypedValue(Expression expression, ref DynamicSchemaColumn? columnSchema) + { + expression = UnwrapConvert(expression); + + if (IsMemberFromTypedParameter(expression)) + { + string col = ParseTypedMemberAccess(expression); + columnSchema = GetColumnFromSchema(col); + return col; + } + if (expression is MethodCallExpression call && IsEnumerableContains(call)) + return ParseTypedContains(call, ref columnSchema); + + object value = EvaluateExpression(expression); + return ParseConstant(value, Parameters, columnSchema); + } + private string ParseTypedContains(MethodCallExpression call, ref DynamicSchemaColumn? columnSchema) + { + // Supports: list.Contains(x.Property) and Enumerable.Contains(list, x.Property) + Expression collection; + Expression candidate; + + if (call.Object != null) + { + collection = call.Object; + candidate = call.Arguments[0]; + } + else + { + collection = call.Arguments[0]; + candidate = call.Arguments[1]; + } + candidate = UnwrapConvert(candidate); + if (!IsMemberFromTypedParameter(candidate)) + throw new NotSupportedException(string.Format("Typed Contains() must target a mapped member: {0}", call)); + + string left = ParseTypedMemberAccess(candidate); + columnSchema = GetColumnFromSchema(left); + + var values = EvaluateExpression(collection) as IEnumerable; + if (values == null && collection is MethodCallExpression implicitCall && + string.Equals(implicitCall.Method.Name, "op_Implicit", StringComparison.Ordinal) && + implicitCall.Arguments.Count > 0) + { + values = EvaluateExpression(implicitCall.Arguments[0]) as IEnumerable; + } + if (values == null) + throw new NotSupportedException(string.Format("Typed Contains() source is not enumerable: {0}", call)); + + var inList = new List(); + foreach (var item in values.Cast()) + inList.Add(ParseConstant(item, Parameters, columnSchema)); + + if (!inList.Any()) + return "(1 = 0)"; + + return string.Format("({0} IN({1}))", left, string.Join(", ", inList)); + } + private string ParseTypedMemberAccess(Expression expression) + { + expression = UnwrapConvert(expression); + if (!(expression is MemberExpression member) || !IsMemberFromTypedParameter(member)) + throw new NotSupportedException(string.Format("Typed fluent member access is not supported: {0}", expression)); + + string mappedColumn = null; + var property = member.Member as PropertyInfo; + if (property != null) + { + var attrs = property.GetCustomAttributes(typeof(ColumnAttribute), true); + var colAttr = attrs == null ? null : attrs.Cast().FirstOrDefault(); + if (colAttr != null && !string.IsNullOrEmpty(colAttr.Name)) + mappedColumn = colAttr.Name; + } + if (string.IsNullOrEmpty(mappedColumn)) + { + mappedColumn = _mapper.PropertyMap.TryGetValue(member.Member.Name) + ?? _mapper.PropertyMap + .Where(x => string.Equals(x.Key, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Value) + .FirstOrDefault() + ?? _mapper.ColumnsMap + .Where(x => string.Equals(x.Value.Name, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Key) + .FirstOrDefault() + ?? member.Member.Name; + } + string tablePrefix = GetRootAliasOrTableName(); + + string qualified = string.IsNullOrEmpty(tablePrefix) + ? mappedColumn + : string.Format("{0}.{1}", tablePrefix, mappedColumn); + + return FixObjectName(qualified); + } + private string ParseTypedSelectExpression(Expression expression) + { + expression = UnwrapConvert(expression); + + if (expression is MethodCallExpression call && IsAsCall(call)) + { + string left = ParseTypedMemberAccess(call.Object ?? call.Arguments.FirstOrDefault()); + var alias = EvaluateExpression(call.Arguments.Last()) == null ? null : EvaluateExpression(call.Arguments.Last()).ToString(); + alias = alias.Validated("Alias"); + + return string.Format("{0} AS {1}", left, Database.DecorateName(alias)); + } + return ParseTypedMemberAccess(expression); + } + private string GetRootAliasOrTableName() + { + var mappedTable = _mapper.Table == null || string.IsNullOrEmpty(_mapper.Table.Name) + ? _mapper.Type.Name + : _mapper.Table.Name; + + var table = Tables.FirstOrDefault(t => t.Name == mappedTable || t.Name == Database.StripName(mappedTable)); + if (table == null) + table = Tables.FirstOrDefault(); + + if (table == null) + return null; + + return string.IsNullOrEmpty(table.Alias) ? table.Name : table.Alias; + } + private TypedTableContext GetRootContext() + { + return new TypedTableContext(GetRootAliasOrTableName()); + } + private TypedTableContext GetJoinedContext(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(join.Alias); + } + private void RegisterTypedJoin(Type modelType, string alias) + { + _typedJoins.Add(new TypedJoinInfo + { + ModelType = modelType, + Alias = alias + }); + } + internal 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) + { + var member = expression as MemberExpression; + if (member == null) + return false; + + var parameter = member.Expression as ParameterExpression; + return parameter != null && parameter.Type == typeof(T); + } + private static string GetJoinKeyword(DynamicJoinType joinType) + { + switch (joinType) + { + case DynamicJoinType.Join: + return "JOIN"; + case DynamicJoinType.Left: + return "LEFT JOIN"; + case DynamicJoinType.Right: + return "RIGHT JOIN"; + case DynamicJoinType.Full: + return "FULL JOIN"; + case DynamicJoinType.LeftOuter: + return "LEFT OUTER JOIN"; + case DynamicJoinType.RightOuter: + return "RIGHT OUTER JOIN"; + case DynamicJoinType.FullOuter: + return "FULL OUTER JOIN"; + default: + return "INNER JOIN"; + } + } + private void AppendJoinClause(string joinClause) + { + _join = string.IsNullOrEmpty(_join) + ? joinClause + : string.Format("{0} {1}", _join, joinClause); + } + private string ParseTypedJoinCondition(Expression expression, string leftPrefix, string rightPrefix, DynamicTypeMap leftMapper, DynamicTypeMap rightMapper, ParameterExpression leftParameter, ParameterExpression rightParameter) + { + expression = UnwrapConvert(expression); + + if (expression is BinaryExpression binary) + { + switch (binary.NodeType) + { + case ExpressionType.AndAlso: + case ExpressionType.And: + return string.Format("({0} AND {1})", + ParseTypedJoinCondition(binary.Left, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter), + ParseTypedJoinCondition(binary.Right, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter)); + case ExpressionType.OrElse: + case ExpressionType.Or: + return string.Format("({0} OR {1})", + ParseTypedJoinCondition(binary.Left, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter), + ParseTypedJoinCondition(binary.Right, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter)); + case ExpressionType.Equal: + case ExpressionType.NotEqual: + case ExpressionType.GreaterThan: + case ExpressionType.GreaterThanOrEqual: + case ExpressionType.LessThan: + case ExpressionType.LessThanOrEqual: + { + string left = ParseTypedJoinValue(binary.Left, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter); + string right = ParseTypedJoinValue(binary.Right, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter); + string op = GetBinaryOperator(binary.NodeType, IsNullConstant(binary.Right)); + return string.Format("({0} {1} {2})", left, op, right); + } + } + } + if (expression is UnaryExpression unary && unary.NodeType == ExpressionType.Not) + return string.Format("(NOT {0})", ParseTypedJoinCondition(unary.Operand, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter)); + + throw new NotSupportedException(string.Format("Typed join condition is not supported: {0}", expression)); + } + private string ParseTypedJoinValue(Expression expression, string leftPrefix, string rightPrefix, DynamicTypeMap leftMapper, DynamicTypeMap rightMapper, ParameterExpression leftParameter, ParameterExpression rightParameter) + { + expression = UnwrapConvert(expression); + MemberExpression member = expression as MemberExpression; + if (member != null && member.Expression is ParameterExpression parameter) + { + if (parameter == leftParameter) + return ParseTypedJoinMemberByMapper(member, leftPrefix, leftMapper); + if (parameter == rightParameter) + return ParseTypedJoinMemberByMapper(member, rightPrefix, rightMapper); + } + DynamicSchemaColumn? col = null; + object value = EvaluateExpression(expression); + return ParseConstant(value, Parameters, col); + } + private string ParseTypedJoinMember(Expression expression, string tablePrefix, DynamicTypeMap mapper) + { + expression = UnwrapConvert(expression); + MemberExpression member = expression as MemberExpression; + if (member == null || !(member.Expression is ParameterExpression) || ((ParameterExpression)member.Expression).Type != typeof(TModel)) + throw new NotSupportedException(string.Format("Typed join member access is not supported: {0}", expression)); + + string mappedColumn = null; + PropertyInfo property = member.Member as PropertyInfo; + if (property != null) + { + var attrs = property.GetCustomAttributes(typeof(ColumnAttribute), true); + ColumnAttribute colAttr = attrs == null ? null : attrs.Cast().FirstOrDefault(); + if (colAttr != null && !string.IsNullOrEmpty(colAttr.Name)) + mappedColumn = colAttr.Name; + } + if (string.IsNullOrEmpty(mappedColumn)) + mappedColumn = mapper.PropertyMap.TryGetValue(member.Member.Name) + ?? mapper.PropertyMap + .Where(x => string.Equals(x.Key, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Value) + .FirstOrDefault() + ?? member.Member.Name; + + return string.Format("{0}.{1}", tablePrefix, Database.DecorateName(mappedColumn)); + } + private string ParseTypedJoinMemberByMapper(MemberExpression member, string tablePrefix, DynamicTypeMap mapper) + { + string mappedColumn = null; + PropertyInfo property = member.Member as PropertyInfo; + if (property != null) + { + var attrs = property.GetCustomAttributes(typeof(ColumnAttribute), true); + ColumnAttribute colAttr = attrs == null ? null : attrs.Cast().FirstOrDefault(); + if (colAttr != null && !string.IsNullOrEmpty(colAttr.Name)) + mappedColumn = colAttr.Name; + } + if (string.IsNullOrEmpty(mappedColumn)) + mappedColumn = mapper.PropertyMap.TryGetValue(member.Member.Name) + ?? mapper.PropertyMap + .Where(x => string.Equals(x.Key, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Value) + .FirstOrDefault() + ?? member.Member.Name; + + return string.Format("{0}.{1}", tablePrefix, Database.DecorateName(mappedColumn)); + } + private static Expression UnwrapConvert(Expression expression) + { + while (expression is UnaryExpression unary && + (unary.NodeType == ExpressionType.Convert || unary.NodeType == ExpressionType.ConvertChecked)) + expression = unary.Operand; + + return expression; + } + private static bool IsNullConstant(Expression expression) + { + expression = UnwrapConvert(expression); + return expression is ConstantExpression constant && constant.Value == null; + } + private static string GetBinaryOperator(ExpressionType type, bool rightIsNull) + { + switch (type) + { + case ExpressionType.Equal: return rightIsNull ? "IS" : "="; + case ExpressionType.NotEqual: return rightIsNull ? "IS NOT" : "<>"; + case ExpressionType.GreaterThan: return ">"; + case ExpressionType.GreaterThanOrEqual: return ">="; + case ExpressionType.LessThan: return "<"; + case ExpressionType.LessThanOrEqual: return "<="; + default: throw new NotSupportedException(string.Format("Expression operation is not supported: {0}", type)); + } + } + private static bool IsEnumerableContains(MethodCallExpression call) + { + if (!string.Equals(call.Method.Name, "Contains", StringComparison.Ordinal)) + return false; + + if (call.Object != null && call.Arguments.Count == 1) + return true; + + return call.Object == null && call.Arguments.Count == 2; + } + private static bool IsAsCall(MethodCallExpression call) + { + return string.Equals(call.Method.Name, "As", StringComparison.Ordinal) + && (call.Arguments.Count == 1 || call.Arguments.Count == 2); + } + private static bool IsAscOrDesc(MethodCallExpression call) + { + string name = call.Method.Name.ToUpper(); + return (name == "ASC" || name == "DESC") + && (call.Arguments.Count == 0 || call.Arguments.Count == 1); + } + private static object EvaluateExpression(Expression expression) + { + var objectMember = Expression.Convert(expression, typeof(object)); + var getter = Expression.Lambda>(objectMember).Compile(); + return getter(); + } + } + internal abstract class DynamicTypedSelectScopeQueryBuilderBase : IDynamicSelectQueryBuilder + { + protected readonly DynamicTypedSelectQueryBuilder Builder; + protected DynamicTypedSelectScopeQueryBuilderBase(DynamicTypedSelectQueryBuilder builder) { Builder = builder; } + public DynamicDatabase Database { get { return Builder.Database; } } + public IList Tables { get { return Builder.Tables; } } + public IDictionary Parameters { get { return Builder.Parameters; } } + public bool VirtualMode { get { return Builder.VirtualMode; } set { Builder.VirtualMode = value; } } + public bool SupportSchema { get { return Builder.SupportSchema; } } + public List> OnCreateTemporaryParameter { get { return Builder.OnCreateTemporaryParameter; } set { Builder.OnCreateTemporaryParameter = value; } } + public List> OnCreateParameter { get { return Builder.OnCreateParameter; } set { Builder.OnCreateParameter = value; } } + public bool IsDisposed { get { return Builder.IsDisposed; } } + public void Dispose() { Builder.Dispose(); } + public IDbCommand FillCommand(IDbCommand command) { return Builder.FillCommand(command); } + public string CommandText() { return Builder.CommandText(); } + public IEnumerable Execute() { return Builder.Execute(); } + public IEnumerable Execute() where T : class { return Builder.Execute(); } + public void ExecuteDataReader(Action reader) { Builder.ExecuteDataReader(reader); } + public object Scalar() { return Builder.Scalar(); } + #if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE + public TResult ScalarAs(TResult defaultValue = default(TResult)) { return Builder.ScalarAs(defaultValue); } + #endif + public IDynamicSelectQueryBuilder From(Func fn, params Func[] func) { Builder.From(fn, func); return this; } + public IDynamicSelectQueryBuilder Join(params Func[] func) { Builder.Join(func); return this; } + public IDynamicSelectQueryBuilder Where(Func func) { Builder.Where(func); return this; } + public IDynamicSelectQueryBuilder Where(DynamicColumn column) { Builder.Where(column); return this; } + public IDynamicSelectQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value) { Builder.Where(column, op, value); return this; } + public IDynamicSelectQueryBuilder Where(string column, object value) { Builder.Where(column, value); return this; } + public IDynamicSelectQueryBuilder Where(object conditions, bool schema = false) { Builder.Where(conditions, schema); return this; } + public IDynamicSelectQueryBuilder Select(Func fn, params Func[] func) { Builder.Select(fn, func); return this; } + public IDynamicSelectQueryBuilder SelectColumn(params DynamicColumn[] columns) { Builder.SelectColumn(columns); return this; } + public IDynamicSelectQueryBuilder SelectColumn(params string[] columns) { Builder.SelectColumn(columns); return this; } + public IDynamicSelectQueryBuilder GroupBy(Func fn, params Func[] func) { Builder.GroupBy(fn, func); return this; } + public IDynamicSelectQueryBuilder GroupByColumn(params DynamicColumn[] columns) { Builder.GroupByColumn(columns); return this; } + public IDynamicSelectQueryBuilder GroupByColumn(params string[] columns) { Builder.GroupByColumn(columns); return this; } + public IDynamicSelectQueryBuilder Having(Func func) { Builder.Having(func); return this; } + public IDynamicSelectQueryBuilder Having(DynamicColumn column) { Builder.Having(column); return this; } + public IDynamicSelectQueryBuilder Having(string column, DynamicColumn.CompareOperator op, object value) { Builder.Having(column, op, value); return this; } + public IDynamicSelectQueryBuilder Having(string column, object value) { Builder.Having(column, value); return this; } + public IDynamicSelectQueryBuilder Having(object conditions, bool schema = false) { Builder.Having(conditions, schema); return this; } + public IDynamicSelectQueryBuilder OrderBy(Func fn, params Func[] func) { Builder.OrderBy(fn, func); return this; } + public IDynamicSelectQueryBuilder OrderByColumn(params DynamicColumn[] columns) { Builder.OrderByColumn(columns); return this; } + public IDynamicSelectQueryBuilder OrderByColumn(params string[] columns) { Builder.OrderByColumn(columns); return this; } + public IDynamicSelectQueryBuilder Top(int? top) { Builder.Top(top); return this; } + public IDynamicSelectQueryBuilder Limit(int? limit) { Builder.Limit(limit); return this; } + public IDynamicSelectQueryBuilder Offset(int? offset) { Builder.Offset(offset); return this; } + public IDynamicSelectQueryBuilder Distinct(bool distinct = true) { Builder.Distinct(distinct); return this; } + protected TypedJoinBuilder ApplyJoinSpec(TypedJoinBuilder builder, string alias, string customJoinType, DynamicJoinType joinType, bool noLock, string condition) + { + if (!string.IsNullOrEmpty(alias)) builder.As(alias); + if (!string.IsNullOrEmpty(customJoinType)) builder.Type(customJoinType); + else + { + switch (joinType) + { + case DynamicJoinType.Join: builder.Join(); break; + case DynamicJoinType.Left: builder.Left(); break; + case DynamicJoinType.Right: builder.Right(); break; + case DynamicJoinType.Full: builder.Full(); break; + case DynamicJoinType.LeftOuter: builder.LeftOuter(); break; + case DynamicJoinType.RightOuter: builder.RightOuter(); break; + case DynamicJoinType.FullOuter: builder.FullOuter(); break; + default: builder.Inner(); break; + } + } + if (noLock) builder.NoLock(); + if (!string.IsNullOrEmpty(condition)) builder.OnRaw(condition); + return builder; + } + protected void AddSelect(TypedSqlSelectable item) { Builder.AddSelectSqlSelector(item); } + protected void AddGroupBy(TypedSqlExpression item) { Builder.AddGroupBySqlSelector(item); } + protected void AddOrderBy(TypedSqlOrderExpression item) { Builder.AddOrderBySqlSelector(item); } + protected void AddWhere(TypedSqlPredicate predicate) { Builder.AppendSqlCondition(Builder.RenderScopeSqlPredicate(predicate), false); } + protected void AddHaving(TypedSqlPredicate predicate) { Builder.AppendSqlCondition(Builder.RenderScopeSqlPredicate(predicate), true); } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1) : base(builder) + { + _alias1 = alias1; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t2" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedSqlSelectable> selector, params Func, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedSqlExpression> selector, params Func, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedSqlOrderExpression> selector, params Func, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t3" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t4" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t5" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t6" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t7" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t8" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t9" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t10" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t11" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t12" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t13" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, _alias12, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + private readonly string _alias13; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12, string alias13) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + _alias13 = alias13; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t14" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, _alias12, _alias13, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + private readonly string _alias13; + private readonly string _alias14; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12, string alias13, string alias14) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + _alias13 = alias13; + _alias14 = alias14; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t15" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, _alias12, _alias13, _alias14, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + private readonly string _alias13; + private readonly string _alias14; + private readonly string _alias15; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12, string alias13, string alias14, string alias15) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + _alias13 = alias13; + _alias14 = alias14; + _alias15 = alias15; + } + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t16" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, _alias12, _alias13, _alias14, _alias15, alias); + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + } + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + private readonly string _alias13; + private readonly string _alias14; + private readonly string _alias15; + private readonly string _alias16; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12, string alias13, string alias14, string alias15, string alias16) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + _alias13 = alias13; + _alias14 = alias14; + _alias15 = alias15; + _alias16 = alias16; + } + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + } + /// Typed wrapper over with property-to-column translation. + /// Mapped entity type. + internal class DynamicTypedUpdateQueryBuilder : DynamicUpdateQueryBuilder, IDynamicTypedUpdateQueryBuilder + { + internal DynamicTypedUpdateQueryBuilder(DynamicDatabase db) + : this(db, false) + { + } + internal DynamicTypedUpdateQueryBuilder(DynamicDatabase db, bool mapType) + : base(db) + { + if (mapType) + this.Table(typeof(T)); + else + this.Table(typeof(T).Name); + } + public IDynamicTypedUpdateQueryBuilder Where(Expression> predicate) + { + TypedModifyHelper.ApplyWhere((c, o, v) => base.Where(c, o, v), predicate); + return this; + } + public IDynamicTypedUpdateQueryBuilder Set(Expression> selector, object value) + { + base.Values(TypedModifyHelper.GetMappedColumn(selector), value); + return this; + } + public IDynamicTypedUpdateQueryBuilder Values(T value) + { + base.Values(value); + return this; + } + public IDynamicTypedUpdateQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate) + { + string condition = TypedModifyHelper.RenderPredicate(predicate, null, RenderValue, Database.DecorateName, RenderSubQuery); + if (string.IsNullOrEmpty(WhereCondition)) + WhereCondition = condition; + else + WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition); + + return this; + } + public IDynamicTypedUpdateQueryBuilder SetSql(Expression> selector, Func, TypedSqlExpression> valueFactory) + { + string column = FixObjectName(TypedModifyHelper.GetMappedColumn(selector), onlyColumn: true); + string value = TypedModifyHelper.RenderExpression(valueFactory, null, RenderValue, Database.DecorateName, RenderSubQuery); + string assignment = string.Format("{0} = {1}", column, value); + _columns = _columns == null ? assignment : string.Format("{0}, {1}", _columns, assignment); + return this; + } + public IDynamicTypedUpdateQueryBuilder SetSql(Func, object> values) + { + if (values == null) + throw new ArgumentNullException("values"); + + object data = values(new TypedTableContext(null)); + foreach (KeyValuePair item in data.ToDictionary()) + { + string column = FixObjectName(TypedModifyHelper.GetMappedColumnByName(typeof(T), item.Key), onlyColumn: true); + string value = (item.Value as TypedSqlExpression) != null + ? TypedModifyHelper.RenderExpression(u => (TypedSqlExpression)item.Value, null, RenderValue, Database.DecorateName, RenderSubQuery) + : RenderValue(item.Value); + + string assignment = string.Format("{0} = {1}", column, value); + _columns = _columns == null ? assignment : string.Format("{0}, {1}", _columns, assignment); + } + return this; + } + public new IDynamicTypedUpdateQueryBuilder Update(string column, object value) + { + base.Update(column, value); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Update(object conditions) + { + base.Update(conditions); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Set(params Func[] func) + { + base.Set(func); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Values(string column, object value) + { + base.Values(column, value); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Values(object o) + { + base.Values(o); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Where(Func func) + { + base.Where(func); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Where(DynamicColumn column) + { + base.Where(column); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value) + { + base.Where(column, op, value); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Where(string column, object value) + { + base.Where(column, value); + return this; + } + public new IDynamicTypedUpdateQueryBuilder Where(object conditions, bool schema = false) + { + base.Where(conditions, schema); + return this; + } + private string RenderValue(object value) + { + if (value == null) + return "NULL"; + + DynamicSchemaColumn? columnSchema = null; + return ParseConstant(value, Parameters, columnSchema); + } + private string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query) + { + foreach (KeyValuePair item in query.Parameters) + if (!Parameters.ContainsKey(item.Key)) + Parameters.Add(item.Key, item.Value); + + return query.CommandText(); + } + } /// Update query builder. internal class DynamicUpdateQueryBuilder : DynamicModifyBuilder, IDynamicUpdateQueryBuilder, DynamicQueryBuilder.IQueryWithWhere { - private string _columns; + protected string _columns; internal DynamicUpdateQueryBuilder(DynamicDatabase db) : base(db) @@ -10584,6 +14124,173 @@ namespace DynamORM } #endregion IExtendedDisposable } + /// Helper methods for typed modify builders. + internal static class TypedModifyHelper + { + private sealed class ModifyRenderContext : ITypedSqlRenderContext + { + private readonly Func, string> _resolveColumn; + private readonly Func _renderValue; + private readonly Func _decorateName; + private readonly Func _renderSubQuery; + + public ModifyRenderContext(Func, string> resolveColumn, Func renderValue, Func decorateName, Func renderSubQuery) + { + _resolveColumn = resolveColumn; + _renderValue = renderValue; + _decorateName = decorateName; + _renderSubQuery = renderSubQuery; + } + public string ResolveColumn(Type modelType, string memberName, string alias) + { + return _resolveColumn(modelType, memberName, alias, _decorateName); + } + public string RenderValue(object value) + { + return _renderValue(value); + } + public string DecorateName(string name) + { + return _decorateName(name); + } + public string RenderSubQuery(IDynamicSelectQueryBuilder query) + { + return _renderSubQuery(query); + } + } + public static string GetMappedColumn(Expression> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + return GetMappedColumn(typeof(T), selector.Body); + } + public static void ApplyWhere(Action addCondition, Expression> predicate) + { + if (addCondition == null) + throw new ArgumentNullException("addCondition"); + if (predicate == null) + throw new ArgumentNullException("predicate"); + + ApplyWhereInternal(typeof(T), addCondition, predicate.Body); + } + public static string RenderPredicate( + Func, TypedSqlPredicate> predicate, + string alias, + Func renderValue, + Func decorateName, + Func renderSubQuery) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + ModifyRenderContext context = new ModifyRenderContext(ResolveColumn, renderValue, decorateName, renderSubQuery); + return predicate(new TypedTableContext(alias)).Render(context); + } + public static string RenderExpression( + Func, TypedSqlExpression> expression, + string alias, + Func renderValue, + Func decorateName, + Func renderSubQuery) + { + if (expression == null) + throw new ArgumentNullException("expression"); + + ModifyRenderContext context = new ModifyRenderContext(ResolveColumn, renderValue, decorateName, renderSubQuery); + return expression(new TypedTableContext(alias)).Render(context); + } + private static void ApplyWhereInternal(Type modelType, Action addCondition, Expression expression) + { + expression = UnwrapConvert(expression); + BinaryExpression be = expression as BinaryExpression; + if (be == null) + throw new NotSupportedException(string.Format("Typed where expression is currently limited to AND-composed binary comparisons: {0}", expression)); + + if (be.NodeType == ExpressionType.AndAlso || be.NodeType == ExpressionType.And) + { + ApplyWhereInternal(modelType, addCondition, be.Left); + ApplyWhereInternal(modelType, addCondition, be.Right); + return; + } + string col = GetMappedColumn(modelType, be.Left); + object val = EvaluateExpression(be.Right); + + switch (be.NodeType) + { + case ExpressionType.Equal: + addCondition(col, DynamicColumn.CompareOperator.Eq, val); + return; + case ExpressionType.NotEqual: + addCondition(col, DynamicColumn.CompareOperator.Not, val); + return; + case ExpressionType.GreaterThan: + addCondition(col, DynamicColumn.CompareOperator.Gt, val); + return; + case ExpressionType.GreaterThanOrEqual: + addCondition(col, DynamicColumn.CompareOperator.Gte, val); + return; + case ExpressionType.LessThan: + addCondition(col, DynamicColumn.CompareOperator.Lt, val); + return; + case ExpressionType.LessThanOrEqual: + addCondition(col, DynamicColumn.CompareOperator.Lte, val); + return; + } + throw new NotSupportedException(string.Format("Typed where expression is currently limited to AND-composed binary comparisons: {0}", expression)); + } + private static string GetMappedColumn(Type modelType, Expression expression) + { + expression = UnwrapConvert(expression); + MemberExpression member = expression as MemberExpression; + if (member == null) + throw new NotSupportedException(string.Format("Selector must target a mapped property: {0}", expression)); + + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(modelType); + if (mapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", modelType.FullName)); + + return mapper.PropertyMap.TryGetValue(member.Member.Name) + ?? mapper.PropertyMap + .Where(x => string.Equals(x.Key, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Value) + .FirstOrDefault() + ?? member.Member.Name; + } + private static string ResolveColumn(Type modelType, string memberName, string alias, Func decorateName) + { + string mapped = GetMappedColumnByName(modelType, memberName); + return string.IsNullOrEmpty(alias) + ? decorateName(mapped) + : string.Format("{0}.{1}", alias, decorateName(mapped)); + } + internal static string GetMappedColumnByName(Type modelType, string memberName) + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(modelType); + if (mapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", modelType.FullName)); + + return mapper.PropertyMap.TryGetValue(memberName) + ?? mapper.PropertyMap.Where(x => string.Equals(x.Key, memberName, StringComparison.OrdinalIgnoreCase)).Select(x => x.Value).FirstOrDefault() + ?? memberName; + } + private static Expression UnwrapConvert(Expression expression) + { + while (expression is UnaryExpression && + (((UnaryExpression)expression).NodeType == ExpressionType.Convert || + ((UnaryExpression)expression).NodeType == ExpressionType.ConvertChecked)) + expression = ((UnaryExpression)expression).Operand; + + return expression; + } + private static object EvaluateExpression(Expression expression) + { + expression = UnwrapConvert(expression); + var objectMember = Expression.Convert(expression, typeof(object)); + var getter = Expression.Lambda>(objectMember).Compile(); + return getter(); + } + } } } namespace Helpers @@ -14152,6 +17859,727 @@ namespace DynamORM } } } + namespace TypedSql + { + /// Render context used by typed SQL DSL nodes. + public interface ITypedSqlRenderContext + { + /// Resolve mapped column for given model member. + string ResolveColumn(Type modelType, string memberName, string alias); + + /// Render value as SQL parameter or literal fragment. + string RenderValue(object value); + + /// Decorate SQL identifier. + string DecorateName(string name); + + /// Render subquery SQL and merge any parameters into current context. + string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query); + } + /// Entry point for the typed SQL DSL. + public static class Sql + { + /// Create parameterized value expression. + public static TypedSqlExpression Val(T value) + { + return new TypedSqlValueExpression(value); + } + /// Create parameterized value expression. + public static TypedSqlExpression Val(object value) + { + return new TypedSqlValueExpression(value); + } + /// Create typed table context for an explicitly named alias, including joined aliases. + public static TypedTableContext Table(string alias) + { + return new TypedTableContext(alias); + } + /// Create raw SQL expression. + public static TypedSqlExpression Raw(string sql) + { + return new TypedSqlRawExpression(sql); + } + /// Create raw ORDER BY fragment. + public static TypedSqlOrderExpression RawOrder(string sql) + { + return new TypedSqlRawOrderExpression(Raw(sql)); + } + /// Create generic function call. + public static TypedSqlExpression Func(string name, params TypedSqlExpression[] arguments) + { + return new TypedSqlFunctionExpression(name, arguments); + } + /// Create COUNT(*) expression. + public static TypedSqlExpression Count() + { + return Raw("COUNT(*)"); + } + /// Create COUNT(expr) expression. + public static TypedSqlExpression Count(TypedSqlExpression expression) + { + return Func("COUNT", expression); + } + /// Create COALESCE expression. + public static TypedSqlExpression Coalesce(params TypedSqlExpression[] expressions) + { + return Func("COALESCE", expressions); + } + /// Create SUM expression. + public static TypedSqlExpression Sum(TypedSqlExpression expression) + { + return Func("SUM", expression); + } + /// Create AVG expression. + public static TypedSqlExpression Avg(TypedSqlExpression expression) + { + return Func("AVG", expression); + } + /// Create MIN expression. + public static TypedSqlExpression Min(TypedSqlExpression expression) + { + return Func("MIN", expression); + } + /// Create MAX expression. + public static TypedSqlExpression Max(TypedSqlExpression expression) + { + return Func("MAX", expression); + } + /// Create ABS expression. + public static TypedSqlExpression Abs(TypedSqlExpression expression) + { + return Func("ABS", expression); + } + /// Create UPPER expression. + public static TypedSqlExpression Upper(TypedSqlExpression expression) + { + return Func("UPPER", expression); + } + /// Create LOWER expression. + public static TypedSqlExpression Lower(TypedSqlExpression expression) + { + return Func("LOWER", expression); + } + /// Create TRIM expression. + public static TypedSqlExpression Trim(TypedSqlExpression expression) + { + return Func("TRIM", expression); + } + /// Create LENGTH expression. + public static TypedSqlExpression Length(TypedSqlExpression expression) + { + return Func("LENGTH", expression); + } + /// Create NULLIF expression. + public static TypedSqlExpression NullIf(TypedSqlExpression left, TypedSqlExpression right) + { + return Func("NULLIF", left, right); + } + /// Create CURRENT_TIMESTAMP expression. + public static TypedSqlExpression CurrentTimestamp() + { + return Raw("CURRENT_TIMESTAMP"); + } + /// Create scalar subquery expression. + public static TypedSqlExpression SubQuery(IDynamicSelectQueryBuilder query) + { + return new TypedSqlSubQueryExpression(query); + } + /// Create scalar typed subquery expression without manually constructing the builder. + public static TypedSqlExpression SubQuery(DynamicDatabase db, Func, IDynamicSelectQueryBuilder> configure, string alias = null, bool noLock = false) + { + if (db == null) + throw new ArgumentNullException("db"); + if (configure == null) + throw new ArgumentNullException("configure"); + + return new TypedSqlSubQueryExpression(configure(db.FromTyped(alias, noLock))); + } + /// Create scalar typed subquery expression using the scoped typed builder API. + public static TypedSqlExpression SubQueryScope(DynamicDatabase db, Func, IDynamicSelectQueryBuilder> configure, string alias = null, bool noLock = false) + { + if (db == null) + throw new ArgumentNullException("db"); + if (configure == null) + throw new ArgumentNullException("configure"); + + return new TypedSqlSubQueryExpression(configure(db.FromTypedScope(alias, noLock))); + } + /// Create EXISTS predicate. + public static TypedSqlPredicate Exists(IDynamicSelectQueryBuilder query) + { + return new TypedSqlExistsPredicate(query); + } + /// Create EXISTS predicate from typed subquery factory. + public static TypedSqlPredicate Exists(DynamicDatabase db, Func, IDynamicSelectQueryBuilder> configure, string alias = null, bool noLock = false) + { + if (db == null) + throw new ArgumentNullException("db"); + if (configure == null) + throw new ArgumentNullException("configure"); + + return new TypedSqlExistsPredicate(configure(db.FromTyped(alias, noLock))); + } + /// Create EXISTS predicate from scoped typed subquery factory. + public static TypedSqlPredicate ExistsScope(DynamicDatabase db, Func, IDynamicSelectQueryBuilder> configure, string alias = null, bool noLock = false) + { + if (db == null) + throw new ArgumentNullException("db"); + if (configure == null) + throw new ArgumentNullException("configure"); + + return new TypedSqlExistsPredicate(configure(db.FromTypedScope(alias, noLock))); + } + /// Create CASE expression builder. + public static TypedSqlCaseBuilder Case() + { + return new TypedSqlCaseBuilder(); + } + } + /// Builder for CASE expressions. + /// Result type. + public sealed class TypedSqlCaseBuilder + { + private readonly IList> _cases = new List>(); + + /// Add WHEN ... THEN ... clause. + public TypedSqlCaseBuilder When(TypedSqlPredicate predicate, object value) + { + _cases.Add(new KeyValuePair( + predicate, + value as TypedSqlExpression ?? Sql.Val(value))); + return this; + } + /// Finalize CASE expression with ELSE clause. + public TypedSqlExpression Else(object value) + { + return new TypedSqlCaseExpression(_cases, value as TypedSqlExpression ?? Sql.Val(value)); + } + /// Finalize CASE expression without ELSE clause. + public TypedSqlExpression End() + { + return new TypedSqlCaseExpression(_cases, null); + } + } + /// Base selectable SQL fragment for the typed DSL. + public abstract class TypedSqlSelectable + { + internal abstract string Render(ITypedSqlRenderContext context); + } + /// Base SQL expression for the typed DSL. + public abstract class TypedSqlExpression : TypedSqlSelectable + { + /// Add arithmetic expression. + public static TypedSqlExpression operator +(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "+", right); + } + /// Subtract arithmetic expression. + public static TypedSqlExpression operator -(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "-", right); + } + /// Multiply arithmetic expression. + public static TypedSqlExpression operator *(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "*", right); + } + /// Divide arithmetic expression. + public static TypedSqlExpression operator /(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "/", right); + } + /// Modulo arithmetic expression. + public static TypedSqlExpression operator %(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "%", right); + } + /// Alias this expression in SELECT clause. + public TypedSqlAliasedExpression As(string alias) + { + return new TypedSqlAliasedExpression(this, alias); + } + /// Order ascending. + public TypedSqlOrderExpression Asc() + { + return new TypedSqlOrderExpression(this, true); + } + /// Order descending. + public TypedSqlOrderExpression Desc() + { + return new TypedSqlOrderExpression(this, false); + } + /// Add expression to another value. + public TypedSqlExpression Add(object value) + { + return new TypedSqlBinaryExpression(this, "+", value as TypedSqlExpression ?? Sql.Val(value)); + } + /// Subtract another value. + public TypedSqlExpression Sub(object value) + { + return new TypedSqlBinaryExpression(this, "-", value as TypedSqlExpression ?? Sql.Val(value)); + } + /// Multiply by another value. + public TypedSqlExpression Mul(object value) + { + return new TypedSqlBinaryExpression(this, "*", value as TypedSqlExpression ?? Sql.Val(value)); + } + /// Divide by another value. + public TypedSqlExpression Div(object value) + { + return new TypedSqlBinaryExpression(this, "/", value as TypedSqlExpression ?? Sql.Val(value)); + } + /// Modulo by another value. + public TypedSqlExpression Mod(object value) + { + return new TypedSqlBinaryExpression(this, "%", value as TypedSqlExpression ?? Sql.Val(value)); + } + /// Equality predicate. + public TypedSqlPredicate Eq(object value) + { + return new TypedSqlBinaryPredicate(this, "=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + /// Inequality predicate. + public TypedSqlPredicate NotEq(object value) + { + return new TypedSqlBinaryPredicate(this, "<>", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + /// Greater-than predicate. + public TypedSqlPredicate Gt(object value) + { + return new TypedSqlBinaryPredicate(this, ">", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + /// Greater-than-or-equal predicate. + public TypedSqlPredicate Gte(object value) + { + return new TypedSqlBinaryPredicate(this, ">=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + /// Less-than predicate. + public TypedSqlPredicate Lt(object value) + { + return new TypedSqlBinaryPredicate(this, "<", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + /// Less-than-or-equal predicate. + public TypedSqlPredicate Lte(object value) + { + return new TypedSqlBinaryPredicate(this, "<=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + /// IS NULL predicate. + public TypedSqlPredicate IsNull() + { + return new TypedSqlUnaryPredicate(this, "IS NULL"); + } + /// IS NOT NULL predicate. + public TypedSqlPredicate IsNotNull() + { + return new TypedSqlUnaryPredicate(this, "IS NOT NULL"); + } + /// LIKE predicate. + public TypedSqlPredicate Like(string pattern) + { + return new TypedSqlBinaryPredicate(this, "LIKE", Sql.Val(pattern)); + } + /// IN predicate. + public TypedSqlPredicate In(params object[] values) + { + return new TypedSqlInPredicate(this, values); + } + /// IN predicate. + public TypedSqlPredicate In(IEnumerable values) + { + return new TypedSqlInPredicate(this, values); + } + /// NOT IN predicate. + public TypedSqlPredicate NotIn(params object[] values) + { + return new TypedSqlInPredicate(this, values, true); + } + /// NOT IN predicate. + public TypedSqlPredicate NotIn(IEnumerable values) + { + return new TypedSqlInPredicate(this, values, true); + } + /// BETWEEN predicate. + public TypedSqlPredicate Between(object lower, object upper) + { + return new TypedSqlBetweenPredicate(this, lower is TypedSqlExpression ? (TypedSqlExpression)lower : Sql.Val(lower), upper is TypedSqlExpression ? (TypedSqlExpression)upper : Sql.Val(upper)); + } + /// Starts-with LIKE predicate. + public TypedSqlPredicate StartsWith(string value) + { + return Like((value ?? string.Empty) + "%"); + } + /// Ends-with LIKE predicate. + public TypedSqlPredicate EndsWith(string value) + { + return Like("%" + (value ?? string.Empty)); + } + /// Contains LIKE predicate. + public TypedSqlPredicate Contains(string value) + { + return Like("%" + (value ?? string.Empty) + "%"); + } + } + /// Typed SQL expression. + public abstract class TypedSqlExpression : TypedSqlExpression + { + } + /// Typed SQL predicate expression. + public abstract class TypedSqlPredicate : TypedSqlExpression + { + /// Combine with AND. + public TypedSqlPredicate And(TypedSqlPredicate right) + { + return new TypedSqlCombinedPredicate(this, "AND", right); + } + /// Combine with OR. + public TypedSqlPredicate Or(TypedSqlPredicate right) + { + return new TypedSqlCombinedPredicate(this, "OR", right); + } + /// Negate predicate. + public TypedSqlPredicate Not() + { + return new TypedSqlNegatedPredicate(this); + } + } + /// Aliased SQL expression. + public sealed class TypedSqlAliasedExpression : TypedSqlSelectable + { + private readonly TypedSqlExpression _expression; + private readonly string _alias; + + internal TypedSqlAliasedExpression(TypedSqlExpression expression, string alias) + { + _expression = expression; + _alias = alias; + } + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("{0} AS {1}", _expression.Render(context), context.DecorateName(_alias)); + } + } + /// Ordered SQL expression. + public class TypedSqlOrderExpression : TypedSqlSelectable + { + private readonly TypedSqlExpression _expression; + private readonly bool _ascending; + private readonly string _nullOrdering; + private readonly bool _raw; + + internal TypedSqlOrderExpression(TypedSqlExpression expression, bool ascending, string nullOrdering = null, bool raw = false) + { + _expression = expression; + _ascending = ascending; + _nullOrdering = nullOrdering; + _raw = raw; + } + /// Append NULLS FIRST ordering. + public TypedSqlOrderExpression NullsFirst() + { + return new TypedSqlOrderExpression(_expression, _ascending, "NULLS FIRST", _raw); + } + /// Append NULLS LAST ordering. + public TypedSqlOrderExpression NullsLast() + { + return new TypedSqlOrderExpression(_expression, _ascending, "NULLS LAST", _raw); + } + internal override string Render(ITypedSqlRenderContext context) + { + string rendered = _raw + ? _expression.Render(context) + : string.Format("{0} {1}", _expression.Render(context), _ascending ? "ASC" : "DESC"); + if (!string.IsNullOrEmpty(_nullOrdering)) + rendered = string.Format("{0} {1}", rendered, _nullOrdering); + + return rendered; + } + } + internal sealed class TypedSqlRawOrderExpression : TypedSqlOrderExpression + { + internal TypedSqlRawOrderExpression(TypedSqlExpression expression) + : base(expression, true, null, true) + { + } + } + internal sealed class TypedSqlBinaryExpression : TypedSqlExpression + { + private readonly TypedSqlExpression _left; + private readonly string _operator; + private readonly TypedSqlExpression _right; + + internal TypedSqlBinaryExpression(TypedSqlExpression left, string op, TypedSqlExpression right) + { + _left = left; + _operator = op; + _right = right; + } + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0} {1} {2})", _left.Render(context), _operator, _right.Render(context)); + } + } + internal sealed class TypedSqlColumnExpression : TypedSqlExpression + { + private readonly Type _modelType; + private readonly string _memberName; + private readonly string _alias; + + internal TypedSqlColumnExpression(Type modelType, string memberName, string alias) + { + _modelType = modelType; + _memberName = memberName; + _alias = alias; + } + internal override string Render(ITypedSqlRenderContext context) + { + return context.ResolveColumn(_modelType, _memberName, _alias); + } + } + internal sealed class TypedSqlValueExpression : TypedSqlExpression, ITypedSqlNullValue + { + private readonly object _value; + + internal TypedSqlValueExpression(object value) + { + _value = value; + } + internal override string Render(ITypedSqlRenderContext context) + { + return context.RenderValue(_value); + } + public bool IsNullValue + { + get { return _value == null; } + } + } + internal sealed class TypedSqlRawExpression : TypedSqlExpression + { + private readonly string _sql; + + internal TypedSqlRawExpression(string sql) + { + _sql = sql; + } + internal override string Render(ITypedSqlRenderContext context) + { + return _sql; + } + } + internal sealed class TypedSqlFunctionExpression : TypedSqlExpression + { + private readonly string _name; + private readonly IList _arguments; + + internal TypedSqlFunctionExpression(string name, params TypedSqlExpression[] arguments) + { + _name = name; + _arguments = arguments ?? new TypedSqlExpression[0]; + } + internal override string Render(ITypedSqlRenderContext context) + { + List rendered = new List(); + foreach (TypedSqlExpression argument in _arguments) + rendered.Add(argument.Render(context)); + + return string.Format("{0}({1})", _name, string.Join(", ", rendered.ToArray())); + } + } + internal sealed class TypedSqlUnaryPredicate : TypedSqlPredicate + { + private readonly TypedSqlExpression _expression; + private readonly string _operator; + + internal TypedSqlUnaryPredicate(TypedSqlExpression expression, string op) + { + _expression = expression; + _operator = op; + } + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0} {1})", _expression.Render(context), _operator); + } + } + internal sealed class TypedSqlBinaryPredicate : TypedSqlPredicate + { + private readonly TypedSqlExpression _left; + private readonly string _operator; + private readonly TypedSqlExpression _right; + + internal TypedSqlBinaryPredicate(TypedSqlExpression left, string op, TypedSqlExpression right) + { + _left = left; + _operator = op; + _right = right; + } + internal override string Render(ITypedSqlRenderContext context) + { + string op = _operator; + TypedSqlValueExpression objRight = _right as TypedSqlValueExpression; + if ((objRight != null && objRight.IsNullValue) || (_right is ITypedSqlNullValue && ((ITypedSqlNullValue)_right).IsNullValue)) + op = _operator == "=" ? "IS" : _operator == "<>" ? "IS NOT" : _operator; + + return string.Format("({0} {1} {2})", _left.Render(context), op, _right.Render(context)); + } + } + internal interface ITypedSqlNullValue + { + bool IsNullValue { get; } + } + internal sealed class TypedSqlInPredicate : TypedSqlPredicate + { + private readonly TypedSqlExpression _left; + private readonly IEnumerable _values; + private readonly bool _negated; + + internal TypedSqlInPredicate(TypedSqlExpression left, IEnumerable values, bool negated = false) + { + _left = left; + _values = values; + _negated = negated; + } + internal override string Render(ITypedSqlRenderContext context) + { + List rendered = new List(); + foreach (object value in _values) + rendered.Add((value as TypedSqlExpression ?? Sql.Val(value)).Render(context)); + + if (rendered.Count == 0) + return _negated ? "(1 = 1)" : "(1 = 0)"; + + return string.Format("({0} {1}({2}))", _left.Render(context), _negated ? "NOT IN" : "IN", string.Join(", ", rendered.ToArray())); + } + } + internal sealed class TypedSqlBetweenPredicate : TypedSqlPredicate + { + private readonly TypedSqlExpression _left; + private readonly TypedSqlExpression _lower; + private readonly TypedSqlExpression _upper; + + internal TypedSqlBetweenPredicate(TypedSqlExpression left, TypedSqlExpression lower, TypedSqlExpression upper) + { + _left = left; + _lower = lower; + _upper = upper; + } + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0} BETWEEN {1} AND {2})", _left.Render(context), _lower.Render(context), _upper.Render(context)); + } + } + internal sealed class TypedSqlCombinedPredicate : TypedSqlPredicate + { + private readonly TypedSqlPredicate _left; + private readonly string _operator; + private readonly TypedSqlPredicate _right; + + internal TypedSqlCombinedPredicate(TypedSqlPredicate left, string op, TypedSqlPredicate right) + { + _left = left; + _operator = op; + _right = right; + } + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0} {1} {2})", _left.Render(context), _operator, _right.Render(context)); + } + } + internal sealed class TypedSqlNegatedPredicate : TypedSqlPredicate + { + private readonly TypedSqlPredicate _predicate; + + internal TypedSqlNegatedPredicate(TypedSqlPredicate predicate) + { + _predicate = predicate; + } + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("(NOT {0})", _predicate.Render(context)); + } + } + internal sealed class TypedSqlCaseExpression : TypedSqlExpression + { + private readonly IList> _cases; + private readonly TypedSqlExpression _elseExpression; + + internal TypedSqlCaseExpression(IList> cases, TypedSqlExpression elseExpression) + { + _cases = cases; + _elseExpression = elseExpression; + } + internal override string Render(ITypedSqlRenderContext context) + { + List items = new List(); + items.Add("CASE"); + + foreach (KeyValuePair item in _cases) + items.Add(string.Format("WHEN {0} THEN {1}", item.Key.Render(context), item.Value.Render(context))); + + if (_elseExpression != null) + items.Add(string.Format("ELSE {0}", _elseExpression.Render(context))); + + items.Add("END"); + return string.Join(" ", items.ToArray()); + } + } + internal sealed class TypedSqlSubQueryExpression : TypedSqlExpression + { + private readonly IDynamicSelectQueryBuilder _query; + + internal TypedSqlSubQueryExpression(IDynamicSelectQueryBuilder query) + { + _query = query; + } + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0})", context.RenderSubQuery(_query)); + } + } + internal sealed class TypedSqlExistsPredicate : TypedSqlPredicate + { + private readonly IDynamicSelectQueryBuilder _query; + + internal TypedSqlExistsPredicate(IDynamicSelectQueryBuilder query) + { + _query = query; + } + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("(EXISTS ({0}))", context.RenderSubQuery(_query)); + } + } + /// Typed table context used by the typed SQL DSL. + /// Mapped entity type. + public sealed class TypedTableContext + { + internal TypedTableContext(string alias) + { + Alias = alias; + } + /// Gets table alias used by the current query. + public string Alias { get; private set; } + + /// Creates a mapped column expression. + public TypedSqlExpression Col(Expression> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + MemberExpression member = selector.Body as MemberExpression; + if (member == null && selector.Body is UnaryExpression) + member = ((UnaryExpression)selector.Body).Operand as MemberExpression; + + if (member == null) + throw new NotSupportedException(string.Format("Column selector must target a mapped property: {0}", selector)); + + return new TypedSqlColumnExpression(typeof(T), member.Member.Name, Alias); + } + /// Select all columns from this typed table context. + public TypedSqlExpression All() + { + return Sql.Raw(string.IsNullOrEmpty(Alias) ? "*" : Alias + ".*"); + } + } + } namespace Validation { /// Required attribute can be used to validate fields in objects using mapper class. diff --git a/DynamORM.Net40.csproj b/DynamORM.Net40.csproj index d84347f..47bb223 100644 --- a/DynamORM.Net40.csproj +++ b/DynamORM.Net40.csproj @@ -5,7 +5,7 @@ Copyright © RUSSEK Software 2012-2026 RUSSEK Software Grzegorz Russek - 1.9 + 2.0 DynamORM MIT false diff --git a/DynamORM.Tests/DynamORM.Tests.csproj b/DynamORM.Tests/DynamORM.Tests.csproj index 428d6ba..bd146fa 100644 --- a/DynamORM.Tests/DynamORM.Tests.csproj +++ b/DynamORM.Tests/DynamORM.Tests.csproj @@ -6,7 +6,7 @@ Copyright © RUSSEK Software 2012-2026 RUSSEK Software Grzegorz Russek - 1.8 + 2.0 https://git.dr4cul4.pl/RUSSEK-Software/DynamORM https://dr4cul4.pl DynamORM diff --git a/DynamORM.Tests/Helpers/TypedFluentUser.cs b/DynamORM.Tests/Helpers/TypedFluentUser.cs new file mode 100644 index 0000000..52cd8da --- /dev/null +++ b/DynamORM.Tests/Helpers/TypedFluentUser.cs @@ -0,0 +1,42 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using DynamORM.Mapper; + +namespace DynamORM.Tests.Helpers +{ + [Table(Name = "sample_users")] + public class TypedFluentUser + { + [Column("id_user", true)] + public long Id { get; set; } + + [Column("user_code")] + public string Code { get; set; } + } +} diff --git a/DynamORM.Tests/Helpers/TypedJoinModels.cs b/DynamORM.Tests/Helpers/TypedJoinModels.cs new file mode 100644 index 0000000..e29b31a --- /dev/null +++ b/DynamORM.Tests/Helpers/TypedJoinModels.cs @@ -0,0 +1,33 @@ +/* + * 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 = "Users", Owner = "dbo")] + public class TypedJoinUser + { + [Column("Id_User", true)] + public long IdUser { get; set; } + + [Column("Active")] + public int Active { get; set; } + } + + [Table(Name = "UserClients", Owner = "dbo")] + public class TypedJoinUserClient + { + [Column("User_Id", true)] + public long UserId { get; set; } + + [Column("Users")] + public string Users { get; set; } + + [Column("Deleted")] + public int Deleted { get; set; } + } +} diff --git a/DynamORM.Tests/Helpers/TypedMultiJoinModels.cs b/DynamORM.Tests/Helpers/TypedMultiJoinModels.cs new file mode 100644 index 0000000..4e1c2ca --- /dev/null +++ b/DynamORM.Tests/Helpers/TypedMultiJoinModels.cs @@ -0,0 +1,49 @@ +/* + * 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; } + } + + [Table(Name = "UserDepartments", Owner = "dbo")] + public class TypedJoinUserDepartment + { + [Column("Department_Id", true)] + public long DepartmentId { get; set; } + + [Column("Region_Id")] + public long RegionId { get; set; } + + [Column("Department_Name")] + public string DepartmentName { get; set; } + } +} diff --git a/DynamORM.Tests/Modify/ParserTests.cs b/DynamORM.Tests/Modify/ParserTests.cs index 9cdc1c6..a5216ab 100644 --- a/DynamORM.Tests/Modify/ParserTests.cs +++ b/DynamORM.Tests/Modify/ParserTests.cs @@ -66,7 +66,7 @@ namespace DynamORM.Tests.Modify /// Tests the basic insert. /// [Test] - public void TestInsertBasic() + public void TestTypedInsertBasic() { IDynamicInsertQueryBuilder cmd = new DynamicInsertQueryBuilder(Database, "Users"); diff --git a/DynamORM.Tests/Modify/TypedModifyExtensionsTests.cs b/DynamORM.Tests/Modify/TypedModifyExtensionsTests.cs new file mode 100644 index 0000000..d138246 --- /dev/null +++ b/DynamORM.Tests/Modify/TypedModifyExtensionsTests.cs @@ -0,0 +1,73 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using DynamORM.Tests.Helpers; +using NUnit.Framework; + +namespace DynamORM.Tests.Modify +{ + [TestFixture] + public class TypedModifyExtensionsTests : TestsBase + { + [SetUp] + public void SetUp() + { + CreateTestDatabase(); + CreateDynamicDatabase( + DynamicDatabaseOptions.SingleConnection | + DynamicDatabaseOptions.SingleTransaction | + DynamicDatabaseOptions.SupportLimitOffset | + DynamicDatabaseOptions.SupportSchema); + } + + [TearDown] + public void TearDown() + { + DestroyDynamicDatabase(); + DestroyTestDatabase(); + } + + [Test] + public void TestTypedUpdateBuilderSetAndWhere() + { + var cmd = Database.UpdateTyped() + .Set(u => u.Code, "778") + .Where(u => u.Id == 1 && u.Code == "1"); + + Assert.AreEqual( + string.Format("UPDATE \"sample_users\" SET \"code\" = [${0}] WHERE (\"id\" = [${1}]) AND (\"code\" = [${2}])", + cmd.Parameters.Keys.ElementAt(0), + cmd.Parameters.Keys.ElementAt(1), + cmd.Parameters.Keys.ElementAt(2)), + cmd.CommandText()); + } + + [Test] + public void TestTypedDeleteBuilderWhere() + { + var cmd = Database.DeleteTyped() + .Where(u => u.Id == 3); + + Assert.AreEqual( + string.Format("DELETE FROM \"sample_users\" WHERE (\"id\" = [${0}])", cmd.Parameters.Keys.First()), + cmd.CommandText()); + } + + [Test] + public void TestTypedInsertBuilderColumns() + { + var cmd = Database.InsertTyped() + .Insert(u => u.Code, "901") + .Insert(u => u.First, "TypedB"); + + Assert.AreEqual( + string.Format("INSERT INTO \"sample_users\" (\"code\", \"first\") VALUES ([${0}], [${1}])", + cmd.Parameters.Keys.ElementAt(0), + cmd.Parameters.Keys.ElementAt(1)), + cmd.CommandText()); + } + } +} diff --git a/DynamORM.Tests/Modify/TypedParserTests.cs b/DynamORM.Tests/Modify/TypedParserTests.cs new file mode 100644 index 0000000..e20ae79 --- /dev/null +++ b/DynamORM.Tests/Modify/TypedParserTests.cs @@ -0,0 +1,224 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System.Linq; +using DynamORM.Builders; +using DynamORM.Builders.Implementation; +using NUnit.Framework; +using DynamORM.Tests.Helpers; +using System.Collections.Generic; +using static System.Data.Entity.Infrastructure.Design.Executor; +using System.Runtime.InteropServices; + +namespace DynamORM.Tests.Modify +{ + /// New parser tests. + [TestFixture] + public class TypedParserTests : TestsBase + { + /// Setup test parameters. + [SetUp] + public virtual void SetUp() + { + CreateTestDatabase(); + CreateDynamicDatabase( + DynamicDatabaseOptions.SingleConnection | + DynamicDatabaseOptions.SingleTransaction | + DynamicDatabaseOptions.SupportLimitOffset); + } + + /// Tear down test objects. + [TearDown] + public virtual void TearDown() + { + DestroyDynamicDatabase(); + DestroyTestDatabase(); + } + + #region Insert + + /// + /// Tests the basic insert. + /// + [Test] + public void TestTypedInsertBasic() + { + var cmd = new DynamicTypedInsertQueryBuilder(Database); + + cmd.Values(x => x.Users.Code = "001", x => x.Users.Name = "Admin", x => x.Users.IsAdmin = 1); + + Assert.AreEqual(string.Format(@"INSERT INTO ""Users"" (""Code"", ""Name"", ""IsAdmin"") VALUES ({0})", + string.Join(", ", cmd.Parameters.Keys.Select(p => string.Format("[${0}]", p)))), cmd.CommandText()); + } + + /// + /// Tests the insert with sub query. + /// + [Test] + public void TestInsertSubQuery() + { + var cmd = new DynamicTypedInsertQueryBuilder(Database); + + cmd.Values(x => x.Code = "001", x => x.Name = "Admin", x => x.IsAdmin = x(cmd + .SubQuery(a => a.AccessRights.As(a.a)) + .Select(a => a.IsAdmin) + .Where(a => a.User_Id == "001"))); + + Assert.AreEqual(string.Format(@"INSERT INTO ""Users"" (""Code"", ""Name"", ""IsAdmin"") VALUES ({0}, (SELECT a.""IsAdmin"" FROM ""AccessRights"" AS a WHERE (a.""User_Id"" = [${1}])))", + string.Join(", ", cmd.Parameters.Keys.Take(2).Select(p => string.Format("[${0}]", p))), cmd.Parameters.Keys.Last()), cmd.CommandText()); + } + + /// + /// Tests the basic insert using object. + /// + [Test] + public void TestInsertBasicObject() + { + var cmd = new DynamicTypedInsertQueryBuilder(Database); + cmd.Values(x => new { Code = "001", Name = "Admin", IsAdmin = 1 }); + + Assert.AreEqual(string.Format(@"INSERT INTO ""Users"" (""Code"", ""Name"", ""IsAdmin"") VALUES ({0})", + string.Join(", ", cmd.Parameters.Keys.Select(p => string.Format("[${0}]", p)))), cmd.CommandText()); + } + + /// + /// Tests the insert using object with sub query. + /// + [Test] + public void TestInsertSubQueryObject() + { + var cmd = new DynamicTypedInsertQueryBuilder(Database); + + cmd.Values(x => new + { + Code = "001", + Name = "Admin", + IsAdmin = x(cmd + .SubQuery(a => a.AccessRights.As(a.a)) + .Select(a => a.IsAdmin) + .Where(a => a.User_Id == "001")) + }); + + Assert.AreEqual(string.Format(@"INSERT INTO ""Users"" (""Code"", ""Name"", ""IsAdmin"") VALUES ({0}, (SELECT a.""IsAdmin"" FROM ""AccessRights"" AS a WHERE (a.""User_Id"" = [${1}])))", + string.Join(", ", cmd.Parameters.Keys.Take(2).Select(p => string.Format("[${0}]", p))), cmd.Parameters.Keys.Last()), cmd.CommandText()); + } + + #endregion Insert + + #region Update + + /// + /// Tests the basic update. + /// + [Test] + public void TestUpdateBasicSet() + { + var cmd = new DynamicTypedUpdateQueryBuilder(Database); + + cmd.Set(x => x.Users.Code = "001", x => x.Users.Name = "Admin", x => x.Users.IsAdmin = 1) + .Where(x => x.Users.Id_User == 1); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = [${2}] WHERE (""Users"".""Id_User"" = [${3}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2], cmd.Parameters.Keys.ToArray()[3]), cmd.CommandText()); + } + + /// + /// Tests the basic update. + /// + [Test] + public void TestUpdateBasicValues() + { + var cmd = new DynamicTypedUpdateQueryBuilder(Database); + + cmd + .Values("Code", "001") + .Values("Name", "Admin") + .Values("IsAdmin", "1") + .Where(x => x.Users.Id_User == 1); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = [${2}] WHERE (""Users"".""Id_User"" = [${3}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2], cmd.Parameters.Keys.ToArray()[3]), cmd.CommandText()); + } + + /// + /// Tests the insert with sub query. + /// + [Test] + public void TestUpdateSubQuery() + { + var cmd = new DynamicTypedUpdateQueryBuilder(Database); + cmd.Set(x => x.Users.Code = "001", x => x.Users.Name = "Admin", x => x.Users.IsAdmin = x(cmd + .SubQuery(a => a.AccessRights.As(a.a)) + .Select(a => a.IsAdmin) + .Where(a => a.User_Id == a.Users.Id_User))) + .Where(x => x.Users.Id_User == 1); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = (SELECT a.""IsAdmin"" FROM ""AccessRights"" AS a WHERE (a.""User_Id"" = ""Users"".""Id_User"")) WHERE (""Users"".""Id_User"" = [${2}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + } + + /// + /// Tests the basic insert using object. + /// + [Test] + public void TestUpdateBasicObject() + { + var cmd = new DynamicTypedUpdateQueryBuilder(Database); + + cmd.Set(x => new { Code = "001", Name = "Admin", IsAdmin = 1 }) + .Where(x => new { Id_User = 1 }); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = [${2}] WHERE (""Id_User"" = [${3}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2], cmd.Parameters.Keys.ToArray()[3]), cmd.CommandText()); + } + + /// + /// Tests the basic insert using object. + /// + [Test] + public void TestUpdateSubQueryObject() + { + var cmd = new DynamicTypedUpdateQueryBuilder(Database); + + cmd.Set(x => new + { + Code = "001", + Name = "Admin", + IsAdmin = x(cmd + .SubQuery(a => a.AccessRights.As(a.a)) + .Select(a => a.IsAdmin) + .Where(a => a.User_Id == a.Users.Id_User)) + }).Where(x => new { Id_User = 1 }); + + Assert.AreEqual(string.Format(@"UPDATE ""Users"" SET ""Code"" = [${0}], ""Name"" = [${1}], ""IsAdmin"" = (SELECT a.""IsAdmin"" FROM ""AccessRights"" AS a WHERE (a.""User_Id"" = ""Users"".""Id_User"")) WHERE (""Id_User"" = [${2}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + } + + #endregion Update + } +} \ No newline at end of file diff --git a/DynamORM.Tests/Select/TypedFluentBuilderTests.cs b/DynamORM.Tests/Select/TypedFluentBuilderTests.cs new file mode 100644 index 0000000..d479c38 --- /dev/null +++ b/DynamORM.Tests/Select/TypedFluentBuilderTests.cs @@ -0,0 +1,142 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using DynamORM.Builders; +using DynamORM.Tests.Helpers; +using NUnit.Framework; + +namespace DynamORM.Tests.Select +{ + [TestFixture] + public class TypedFluentBuilderTests : TestsBase + { + [SetUp] + public void SetUp() + { + CreateTestDatabase(); + CreateDynamicDatabase( + DynamicDatabaseOptions.SingleConnection | + DynamicDatabaseOptions.SingleTransaction | + DynamicDatabaseOptions.SupportLimitOffset); + } + + [TearDown] + public void TearDown() + { + DestroyDynamicDatabase(); + DestroyTestDatabase(); + } + + [Test] + public void TestTypedWhereAndSelectUsesPropertyMap() + { + var cmd = Database.FromTyped("u") + .Where(u => u.Id == 1) + .Select(u => u.Code.As("CodeAlias")) + .OrderBy(u => u.Code.Desc()); + + Assert.AreEqual( + string.Format("SELECT u.\"user_code\" AS \"CodeAlias\" FROM \"sample_users\" AS u WHERE (u.\"id_user\" = [${0}]) ORDER BY u.\"user_code\" DESC", cmd.Parameters.Keys.First()), + cmd.CommandText()); + } + + [Test] + public void TestTypedWhereSupportsContains() + { + var ids = new[] { 1L, 2L, 3L }.ToList(); + + var cmd = Database.FromTyped("u") + .Where(u => ids.Contains(u.Id)) + .Select(u => u.Id); + + Assert.AreEqual( + string.Format("SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (u.\"id_user\" IN([${0}], [${1}], [${2}]))", + cmd.Parameters.Keys.ElementAt(0), + cmd.Parameters.Keys.ElementAt(1), + cmd.Parameters.Keys.ElementAt(2)), + cmd.CommandText()); + } + + [Test] + public void TestTypedGroupByHavingOrderBy() + { + var cmd = Database.FromTyped("u") + .Select(u => u.Code) + .GroupBy(u => u.Code) + .Having(u => u.Code != null) + .OrderBy(u => u.Code.Asc()); + + Assert.AreEqual("SELECT u.\"user_code\" FROM \"sample_users\" AS u GROUP BY u.\"user_code\" HAVING (u.\"user_code\" IS NOT NULL) ORDER BY u.\"user_code\" ASC", + cmd.CommandText()); + } + + [Test] + public void TestTypedJoin() + { + var cmd = Database.FromTyped("u") + .Join(j => j.Inner().As("x").On((l, r) => l.Id == r.Id)) + .Select(u => u.Id); + + Assert.AreEqual("SELECT u.\"id_user\" FROM \"sample_users\" AS u INNER JOIN \"sample_users\" AS x ON (u.\"id_user\" = x.\"id_user\")", + cmd.CommandText()); + } + + [Test] + public void TestTypedLeftJoin() + { + var cmd = Database.FromTyped("u") + .Join(j => j.Left().As("x").On((l, r) => l.Id == r.Id)) + .Select(u => u.Id); + + Assert.AreEqual("SELECT u.\"id_user\" FROM \"sample_users\" AS u LEFT JOIN \"sample_users\" AS x ON (u.\"id_user\" = x.\"id_user\")", + cmd.CommandText()); + } + + [Test] + public void TestTypedRightJoin() + { + var cmd = Database.FromTyped("u") + .Join(j => j.Right().As("x").On((l, r) => l.Id == r.Id)) + .Select(u => u.Id); + + Assert.AreEqual("SELECT u.\"id_user\" FROM \"sample_users\" AS u RIGHT JOIN \"sample_users\" AS x ON (u.\"id_user\" = x.\"id_user\")", + cmd.CommandText()); + } + + [Test] + public void TestTypedFullJoin() + { + var cmd = Database.FromTyped("u") + .Join(j => j.Full().As("x").On((l, r) => l.Id == r.Id)) + .Select(u => u.Id); + + Assert.AreEqual("SELECT u.\"id_user\" FROM \"sample_users\" AS u FULL JOIN \"sample_users\" AS x ON (u.\"id_user\" = x.\"id_user\")", + cmd.CommandText()); + } + } +} diff --git a/DynamORM.Tests/Select/TypedFluentJoinSyntaxTests.cs b/DynamORM.Tests/Select/TypedFluentJoinSyntaxTests.cs new file mode 100644 index 0000000..d11945a --- /dev/null +++ b/DynamORM.Tests/Select/TypedFluentJoinSyntaxTests.cs @@ -0,0 +1,102 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System.Linq; +using DynamORM.Tests.Helpers; +using NUnit.Framework; + +namespace DynamORM.Tests.Select +{ + [TestFixture] + public class TypedFluentJoinSyntaxTests : TestsBase + { + [SetUp] + public void SetUp() + { + CreateTestDatabase(); + CreateDynamicDatabase( + DynamicDatabaseOptions.SingleConnection | + DynamicDatabaseOptions.SingleTransaction | + DynamicDatabaseOptions.SupportNoLock); + } + + [TearDown] + public void TearDown() + { + DestroyDynamicDatabase(); + DestroyTestDatabase(); + } + + [Test] + public void TestTypedJoinDefaultJoinKeyword() + { + var cmd = Database.FromTyped("usr") + .Join(j => j.As("uc").On((u, c) => u.IdUser == c.UserId)); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS usr JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")", cmd.CommandText()); + } + + [Test] + public void TestTypedInnerJoinWithAndNull() + { + var cmd = Database.FromTyped("usr") + .Join(j => j.Inner().As("uc").On((u, c) => u.IdUser == c.UserId && c.Users != null)) + .Select(u => u.IdUser); + + Assert.AreEqual("SELECT usr.\"Id_User\" FROM \"dbo\".\"Users\" AS usr INNER JOIN \"dbo\".\"UserClients\" AS uc ON ((usr.\"Id_User\" = uc.\"User_Id\") AND (uc.\"Users\" IS NOT NULL))", cmd.CommandText()); + } + + [Test] + public void TestTypedJoinWithNoLock() + { + var cmd = Database.FromTyped("usr", noLock: true) + .Join(j => j.Inner().As("uc").NoLock().On((u, c) => u.IdUser == c.UserId)); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS usr WITH(NOLOCK) INNER JOIN \"dbo\".\"UserClients\" AS uc WITH(NOLOCK) ON (usr.\"Id_User\" = uc.\"User_Id\")", cmd.CommandText()); + } + + [Test] + public void TestTypedLeftOuterJoin() + { + var cmd = Database.FromTyped("usr") + .Join(j => j.LeftOuter().As("uc").On((u, c) => u.IdUser == c.UserId)); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS usr LEFT OUTER JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")", cmd.CommandText()); + } + + [Test] + public void TestTypedRightOuterJoin() + { + var cmd = Database.FromTyped("usr") + .Join(j => j.RightOuter().As("uc").On((u, c) => u.IdUser == c.UserId)); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS usr RIGHT OUTER JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")", cmd.CommandText()); + } + + [Test] + public void TestTypedCustomJoinTypeCrossApply() + { + var cmd = Database.FromTyped("usr") + .Join(j => j.Type("CROSS APPLY").As("uc")); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS usr CROSS APPLY \"dbo\".\"UserClients\" AS uc", cmd.CommandText()); + } + + [Test] + public void TestTypedJoinAndWhereParameterOrder() + { + var cmd = Database.FromTyped("usr") + .Join(j => j.As("uc").On((u, c) => u.IdUser == c.UserId && c.Deleted == 0)) + .Where(u => u.Active == 1); + + Assert.AreEqual( + string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr JOIN \"dbo\".\"UserClients\" AS uc ON ((usr.\"Id_User\" = uc.\"User_Id\") AND (uc.\"Deleted\" = [${0}])) WHERE (usr.\"Active\" = [${1}])", + cmd.Parameters.Keys.ElementAt(0), + cmd.Parameters.Keys.ElementAt(1)), + cmd.CommandText()); + } + } +} diff --git a/DynamORM.Tests/Select/TypedParserTests.cs b/DynamORM.Tests/Select/TypedParserTests.cs new file mode 100644 index 0000000..ae50f7e --- /dev/null +++ b/DynamORM.Tests/Select/TypedParserTests.cs @@ -0,0 +1,860 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System.Linq; +using DynamORM.Builders; +using DynamORM.Builders.Implementation; +using DynamORM.Tests.Helpers; +using NUnit.Framework; + +namespace DynamORM.Tests.Select +{ + /// + /// New parser tests. + /// + [TestFixture] + public class TypedParserTests : TestsBase + { + /// Setup test parameters. + [SetUp] + public virtual void SetUp() + { + CreateTestDatabase(); + CreateDynamicDatabase( + DynamicDatabaseOptions.SingleConnection | + DynamicDatabaseOptions.SingleTransaction | + DynamicDatabaseOptions.SupportLimitOffset | + DynamicDatabaseOptions.SupportNoLock); + } + + /// Tear down test objects. + [TearDown] + public virtual void TearDown() + { + try + { + DestroyDynamicDatabase(); + DestroyTestDatabase(); + } + catch { } + } + + + /// + /// Tests from typed method. + /// + [Test] + public void TestFromGetTyped() + { + var cmd = Database.From(); + + Assert.AreEqual("SELECT * FROM \"sample_users\"", cmd.CommandText()); + } + + /// + /// Tests from typed method. + /// + [Test] + public void TestFromGetTypedAs() + { + var cmd = Database.From("u"); + + Assert.AreEqual("SELECT * FROM \"sample_users\" AS u", cmd.CommandText()); + } + + /// + /// Tests from method using invoke with sub query. + /// + [Test] + public void TestFromSubQuery4() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u(new DynamicSelectQueryBuilder(Database).From(x => x.dbo.Users.NoLock())).As("u")); + + Assert.AreEqual("SELECT * FROM (SELECT * FROM \"dbo\".\"Users\" WITH(NOLOCK)) AS u", cmd.CommandText()); + } + + /// + /// Tests where method with alias. + /// + [Test] + public void TestWhereAlias() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Where(u => u.c.UserName == "admin"); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS c WHERE (c.\"UserName\" = [${0}])", cmd.Parameters.Keys.First()), cmd.CommandText()); + } + + /// + /// Tests where method with alias. + /// + [Test] + public void TestHavingAlias() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Having(u => u.Sum(u.c.ClientsCount) > 10); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS c HAVING (Sum(c.\"ClientsCount\") > [${0}])", cmd.Parameters.Keys.First()), cmd.CommandText()); + } + + /// + /// Tests complex where method with alias. + /// + [Test] + public void TestWhereAliasComplex() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Where(u => u.c.UserName == "admin" || u.c.UserName == "root") + .Where(u => u.c.IsActive = true); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS c WHERE ((c.\"UserName\" = [${0}]) OR (c.\"UserName\" = [${1}])) AND c.\"IsActive\" = ([${2}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + } + + /// + /// Tests where method with alias using in. + /// + [Test] + public void TestWhereAliasIn() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + int[] ids = new int[] { 0, 1, 2, 3, 4, 5 }; + + cmd.From(u => u.dbo.Users.As(u.c)) + .Where(u => u.c.UserName == "admin" || u.c.UserName == "root") + .Where(u => u.c.IsActive == true) + .Where(u => u.c.Id_User.In(ids)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS c WHERE ((c.\"UserName\" = [${0}]) OR (c.\"UserName\" = [${1}])) AND (c.\"IsActive\" = [${2}]) AND c.\"Id_User\" IN({3})", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2], + string.Join(", ", cmd.Parameters.Keys.Skip(3).Select(p => string.Format("[${0}]", p)))), cmd.CommandText()); + } + + /// + /// Tests where method with alias using between. + /// + [Test] + public void TestWhereAliasBetween1() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + int[] ids = new int[] { 0, 5 }; + + cmd.From(u => u.dbo.Users.As(u.c)) + .Where(u => u.c.UserName == "admin" || u.c.UserName == "root") + .Where(u => u.c.IsActive == true) + .Where(u => u.c.Id_User.Between(ids)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS c WHERE ((c.\"UserName\" = [${0}]) OR (c.\"UserName\" = [${1}])) AND (c.\"IsActive\" = [${2}]) AND c.\"Id_User\" BETWEEN [${3}] AND [${4}]", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2], + cmd.Parameters.Keys.ToArray()[3], cmd.Parameters.Keys.ToArray()[4]), cmd.CommandText()); + } + + /// + /// Tests where method with alias using between. + /// + [Test] + public void TestWhereAliasBetween2() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + int[] ids = new int[] { 0, 5 }; + + cmd.From(u => u.dbo.Users.As(u.c)) + .Where(u => u.c.UserName == "admin" || u.c.UserName == "root") + .Where(u => u.c.IsActive == true) + .Where(u => u.c.Id_User.Between(ids[0], ids[1])); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS c WHERE ((c.\"UserName\" = [${0}]) OR (c.\"UserName\" = [${1}])) AND (c.\"IsActive\" = [${2}]) AND c.\"Id_User\" BETWEEN [${3}] AND [${4}]", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2], + cmd.Parameters.Keys.ToArray()[3], cmd.Parameters.Keys.ToArray()[4]), cmd.CommandText()); + } + + /// + /// Tests where method without alias. + /// + [Test] + public void TestWhereNoAlias() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users) + .Where(u => u.UserName == "admin"); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" WHERE (\"UserName\" = [${0}])", cmd.Parameters.Keys.First()), cmd.CommandText()); + } + + /// + /// Tests where method with full column name. + /// + [Test] + public void TestWhereNoAliasTableName() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users) + .Where(u => u.dbo.Users.UserName == "admin"); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" WHERE (\"dbo\".\"Users\".\"UserName\" = [${0}])", cmd.Parameters.Keys.First()), cmd.CommandText()); + } + + /// + /// Tests simple join method. + /// + [Test] + public void TestJoinClassic() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(u => u.dbo.UserClients.AS(u.uc).On(u.usr.Id_User == u.uc.User_Id)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")"), cmd.CommandText()); + } + + /// + /// Tests inner join method. + /// + [Test] + public void TestInnerJoin() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(u => u.Inner().dbo.UserClients.AS(u.uc).On(u.usr.Id_User == u.uc.User_Id)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr INNER JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")"), cmd.CommandText()); + } + + /// + /// Tests inner join method with aliases mix. + /// + [Test] + public void TestInnerJoin2() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(usr => usr.Inner().dbo.UserClients.AS(usr.uc).On(usr.Id_User == usr.uc.User_Id && usr.uc.Users != null)) + .Select(usr => usr.All(), uc => uc.Users); + + Assert.AreEqual(string.Format("SELECT usr.*, uc.\"Users\" FROM \"dbo\".\"Users\" AS usr INNER JOIN \"dbo\".\"UserClients\" AS uc ON ((usr.\"Id_User\" = uc.\"User_Id\") AND (uc.\"Users\" IS NOT NULL))"), cmd.CommandText()); + } + + /// + /// Tests from method using invoke with sub query. + /// + [Test] + public void TestInnerJoin3() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .SubQuery((b, s) => b.Join(usr => usr(s.From(x => x.dbo.UserClients)).Inner().As(usr.uc).On(usr.Id_User == usr.uc.User_Id && usr.uc.Users != null))) + .Select(usr => usr.All(), uc => uc.Users); + + Assert.AreEqual(string.Format("SELECT usr.*, uc.\"Users\" FROM \"dbo\".\"Users\" AS usr INNER JOIN (SELECT * FROM \"dbo\".\"UserClients\") AS uc ON ((usr.\"Id_User\" = uc.\"User_Id\") AND (uc.\"Users\" IS NOT NULL))"), cmd.CommandText()); + } + + /// + /// Tests from method using invoke with sub query. + /// + [Test] + public void TestInnerJoin4() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .SubQuery((b, s) => b.Join(usr => usr(s.From(x => x.dbo.UserClients).Where(x => x.Deleted == 0)).Inner().As(usr.uc).On(usr.Id_User == usr.uc.User_Id && usr.uc.Users != null))) + .Select(usr => usr.All(), uc => uc.Users); + + Assert.AreEqual(string.Format("SELECT usr.*, uc.\"Users\" FROM \"dbo\".\"Users\" AS usr INNER JOIN (SELECT * FROM \"dbo\".\"UserClients\" WHERE (\"Deleted\" = [${0}])) AS uc ON ((usr.\"Id_User\" = uc.\"User_Id\") AND (uc.\"Users\" IS NOT NULL))", cmd.Parameters.Keys.First()), cmd.CommandText()); + } + + /// + /// Tests from method using invoke with sub query an no lock. + /// + [Test] + public void TestInnerJoin5() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr).NoLock()) + .SubQuery((b, s) => b.Join(usr => usr(s.From(x => x.dbo.UserClients.NoLock()).Where(x => x.Deleted == 0)).Inner().As(usr.uc).On(usr.Id_User == usr.uc.User_Id && usr.uc.Users != null))) + .Select(usr => usr.All(), uc => uc.Users); + + Assert.AreEqual(string.Format("SELECT usr.*, uc.\"Users\" FROM \"dbo\".\"Users\" AS usr WITH(NOLOCK) INNER JOIN (SELECT * FROM \"dbo\".\"UserClients\" WITH(NOLOCK) WHERE (\"Deleted\" = [${0}])) AS uc ON ((usr.\"Id_User\" = uc.\"User_Id\") AND (uc.\"Users\" IS NOT NULL))", cmd.Parameters.Keys.First()), cmd.CommandText()); + } + + /// + /// Tests inner join method with no lock. + /// + [Test] + public void TestInnerJoin6() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr).NoLock()) + .Join(u => u.Inner().dbo.UserClients.AS(u.uc).NoLock().On(u.usr.Id_User == u.uc.User_Id)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr WITH(NOLOCK) INNER JOIN \"dbo\".\"UserClients\" AS uc WITH(NOLOCK) ON (usr.\"Id_User\" = uc.\"User_Id\")"), cmd.CommandText()); + } + + /// + /// Tests left outer join method. + /// + [Test] + public void TestLeftOuterJoin() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(u => u.LeftOuter().dbo.UserClients.AS(u.uc).On(u.usr.Id_User == u.uc.User_Id)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr LEFT OUTER JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")"), cmd.CommandText()); + } + + /// + /// Tests left join method. + /// + [Test] + public void TestLeftJoin() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(u => u.Left().dbo.UserClients.AS(u.uc).On(u.usr.Id_User == u.uc.User_Id)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr LEFT JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")"), cmd.CommandText()); + } + + /// + /// Tests right outer join method. + /// + [Test] + public void TestRightOuterJoin() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(u => u.RightOuter().dbo.UserClients.AS(u.uc).On(u.usr.Id_User == u.uc.User_Id)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr RIGHT OUTER JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")"), cmd.CommandText()); + } + + /// + /// Tests right join method. + /// + [Test] + public void TestRightJoin() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(u => u.Right().dbo.UserClients.AS(u.uc).On(u.usr.Id_User == u.uc.User_Id)); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr RIGHT JOIN \"dbo\".\"UserClients\" AS uc ON (usr.\"Id_User\" = uc.\"User_Id\")"), cmd.CommandText()); + } + + /// + /// Tests complex join with parameters. + /// + [Test] + public void TestJoinClassicWithParamAndWhere() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.usr)) + .Join(u => u.dbo.UserClients.AS(u.uc).On(u.usr.Id_User == u.uc.User_Id && u.uc.Deleted == 0)) + .Where(u => u.usr.Active == true); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS usr JOIN \"dbo\".\"UserClients\" AS uc ON ((usr.\"Id_User\" = uc.\"User_Id\") AND (uc.\"Deleted\" = [${0}])) WHERE (usr.\"Active\" = [${1}])", + cmd.Parameters.Keys.First(), cmd.Parameters.Keys.Last()), cmd.CommandText()); + } + + /// + /// Tests select all. + /// + [Test] + public void TestSelectAll1() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.c.All()); + + Assert.AreEqual("SELECT c.* FROM \"dbo\".\"Users\" AS c", cmd.CommandText()); + } + + /// + /// Tests select all. + /// + [Test] + public void TestSelectAll2() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users) + .Select(u => u.dbo.Users.All()); + + Assert.AreEqual("SELECT \"dbo\".\"Users\".* FROM \"dbo\".\"Users\"", cmd.CommandText()); + } + + /// + /// Tests select field. + /// + [Test] + public void TestSelectField1() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.c.UserName); + + Assert.AreEqual("SELECT c.\"UserName\" FROM \"dbo\".\"Users\" AS c", cmd.CommandText()); + } + + /// + /// Tests select field. + /// + [Test] + public void TestSelectField2() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users) + .Select(u => u.dbo.Users.UserName); + + Assert.AreEqual("SELECT \"dbo\".\"Users\".\"UserName\" FROM \"dbo\".\"Users\"", cmd.CommandText()); + } + + /// + /// Tests select field with alias. + /// + [Test] + public void TestSelectFieldAlias1() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.c.UserName.As(u.Name)); + + Assert.AreEqual("SELECT c.\"UserName\" AS \"Name\" FROM \"dbo\".\"Users\" AS c", cmd.CommandText()); + } + + /// + /// Tests select field with alias. + /// + [Test] + public void TestSelectFieldAlias2() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users) + .Select(u => u.dbo.Users.UserName.As(u.Name)); + + Assert.AreEqual("SELECT \"dbo\".\"Users\".\"UserName\" AS \"Name\" FROM \"dbo\".\"Users\"", cmd.CommandText()); + } + + /// + /// Tests select field with alias. + /// + [Test] + public void TestSelectFieldAlias3() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.u)) + .Select(u => u.UserName.As(u.Name)); + + Assert.AreEqual("SELECT u.\"UserName\" AS \"Name\" FROM \"dbo\".\"Users\" AS u", cmd.CommandText()); + } + + /// + /// Tests select field with alias. + /// + [Test] + public void TestSelectFieldAlias4() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.u)) + .Select(u => u.UserName.As(u.u.Name)); + + Assert.AreEqual("SELECT u.\"UserName\" AS \"Name\" FROM \"dbo\".\"Users\" AS u", cmd.CommandText()); + } + + /// + /// Tests select aggregate field with alias (Sum). + /// + [Test] + public void TestSelectAggregateField1() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.Sum(u.c.UserName).As(u.Name)); + + Assert.AreEqual("SELECT Sum(c.\"UserName\") AS \"Name\" FROM \"dbo\".\"Users\" AS c", cmd.CommandText()); + } + + /// + /// Tests select aggregate field with alias (Coalesce). + /// + [Test] + public void TestSelectAggregateField2() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.Coalesce(u.c.UserName, u.c.FirstName + " " + u.c.LastName).As(u.Name)); + + Assert.AreEqual(string.Format("SELECT Coalesce(c.\"UserName\", ((c.\"FirstName\" + [${0}]) + c.\"LastName\")) AS \"Name\" FROM \"dbo\".\"Users\" AS c", + cmd.Parameters.Keys.First()), cmd.CommandText()); + } + + /// + /// Tests select aggregate field with alias (Sum). + /// + [Test] + public void TestSelectAggregateField3() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users) + .Select(u => u.Sum(u.dbo.Users.UserName)); + + Assert.AreEqual("SELECT Sum(\"dbo\".\"Users\".\"UserName\") FROM \"dbo\".\"Users\"", cmd.CommandText()); + } + + /// + /// Tests select aggregate field with alias (Sum). + /// + [Test] + public void TestSelectAggregateField4() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.Sum(u("\"UserName\"")).As(u.Name)); + + Assert.AreEqual("SELECT Sum(\"UserName\") AS \"Name\" FROM \"dbo\".\"Users\" AS c", cmd.CommandText()); + } + + /// + /// Tests select aggregate field with alias (Sum). + /// + [Test] + public void TestSelectAggregateField5() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u(u.Sum(u("\"UserName\"")), " + 1").As(u.Name)); + + Assert.AreEqual("SELECT Sum(\"UserName\") + 1 AS \"Name\" FROM \"dbo\".\"Users\" AS c", cmd.CommandText()); + } + + /// + /// Tests select from anonymous type. + /// + [Test] + public void TestSelectAnon() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => new + { + Id_User = u.c.Id_User, + Name = u.c.UserName, + }); + + Assert.AreEqual("SELECT c.\"Id_User\" AS \"Id_User\", c.\"UserName\" AS \"Name\" FROM \"dbo\".\"Users\" AS c", cmd.CommandText()); + } + + /// + /// Tests select escaped case. + /// + [Test] + public void TestSelectCaseEscaped1() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u("CASE ", u.c.IsActive, " WHEN ", 1, " THEN ", 0, " ELSE ", 1, " END").As(u.Deleted)); + + Assert.AreEqual(string.Format("SELECT CASE c.\"IsActive\" WHEN [${0}] THEN [${1}] ELSE [${2}] END AS \"Deleted\" FROM \"dbo\".\"Users\" AS c", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + } + + /// + /// Tests select escaped case. + /// + [Test] + public void TestSelectCaseEscaped2() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u("CASE WHEN ", u.c.IsActive == 1, " THEN ", 0, " ELSE ", 1, " END").As(u.Deleted)); + + Assert.AreEqual(string.Format("SELECT CASE WHEN (c.\"IsActive\" = [${0}]) THEN [${1}] ELSE [${2}] END AS \"Deleted\" FROM \"dbo\".\"Users\" AS c", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + } + + /// + /// Tests select escaped case. + /// + [Test] + public void TestCoalesceEscaped() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u("COALESCE(", Database.DecorateName("ServerHash"), ", ", new byte[16] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, ")").As(u.Hash)); + + Assert.AreEqual(string.Format("SELECT COALESCE(\"ServerHash\", [${0}]) AS \"Hash\" FROM \"dbo\".\"Users\" AS c", + cmd.Parameters.Keys.ToArray()[0]), cmd.CommandText()); + } + + /// + /// Tests select escaped case. + /// + [Test] + public void TestCoalesce() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.Coalesce(u.c.ServerHash, new byte[16] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }).As(u.Hash)); + + Assert.AreEqual(string.Format("SELECT Coalesce(c.\"ServerHash\", [${0}]) AS \"Hash\" FROM \"dbo\".\"Users\" AS c", + cmd.Parameters.Keys.ToArray()[0]), cmd.CommandText()); + } + + /// + /// Tests select escaped case. + /// + [Test] + public void TestCoalesceCalculatedArgs() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.Coalesce(u.c.Test1 + "_", u.c.Test2 + "_", u.c.Test3 + "_").As(u.Hash)); + + Assert.AreEqual(string.Format("SELECT Coalesce((c.\"Test1\" + [${0}]), (c.\"Test2\" + [${1}]), (c.\"Test3\" + [${2}])) AS \"Hash\" FROM \"dbo\".\"Users\" AS c", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + + //var c = Database.Open().CreateCommand(); + //cmd.FillCommand(c); + //c.Dispose(); + } + + /// + /// Tests select escaped case. + /// + [Test] + public void TestCoalesceInWhere() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u.ServerHash.As(u.Hash)) + .Where(u => u.Coalesce(u.c.ServerHash, new byte[16] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) == new byte[16] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); + + Assert.AreEqual(string.Format("SELECT \"ServerHash\" AS \"Hash\" FROM \"dbo\".\"Users\" AS c WHERE (Coalesce(c.\"ServerHash\", [${0}]) = [${1}])", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1]), cmd.CommandText()); + } + + /// + /// Tests select escaped case with sub query. + /// + [Test] + public void TestSelectCaseEscapedAndSub() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u("CASE WHEN ", u.c.IsActive == 1, " AND ", u.c.IsAdmin == u(cmd.SubQuery() + .From(x => x.dbo.AccessRights.As(x.a)) + .Where(x => x.a.User_Id == x.c.Id_User) + .Select(x => x.a.IsAdmin)), " THEN ", 0, " ELSE ", 1, " END").As(u.Deleted)); + + Assert.AreEqual(string.Format("SELECT CASE WHEN (c.\"IsActive\" = [${0}]) AND (c.\"IsAdmin\" = (SELECT a.\"IsAdmin\" FROM \"dbo\".\"AccessRights\" AS a WHERE (a.\"User_Id\" = c.\"Id_User\"))) THEN [${1}] ELSE [${2}] END AS \"Deleted\" FROM \"dbo\".\"Users\" AS c", + cmd.Parameters.Keys.ToArray()[0], cmd.Parameters.Keys.ToArray()[1], cmd.Parameters.Keys.ToArray()[2]), cmd.CommandText()); + } + + /// + /// Tests group by. + /// + [Test] + public void TestGroupBy() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .GroupBy(u => u.c.UserName); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS c GROUP BY c.\"UserName\"", cmd.CommandText()); + } + + /// + /// Tests order by. + /// + [Test] + public void TestOrderBy() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .OrderBy(u => u.c.UserName); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS c ORDER BY c.\"UserName\" ASC", cmd.CommandText()); + } + + /// + /// Tests order by using string with number. + /// + [Test] + public void TestOrderByNumberedColumnStr() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .OrderBy(u => "1 DESC"); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS c ORDER BY 1 DESC", cmd.CommandText()); + } + + /// + /// Tests order by using member with number. + /// + [Test] + public void TestOrderByNumberedColFn() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .OrderBy(u => u.Desc(1)); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS c ORDER BY 1 DESC", cmd.CommandText()); + } + + /// + /// Tests order by using member with field. + /// + [Test] + public void TestOrderByAlt() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .OrderBy(u => u.Desc(u.c.UserName)); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS c ORDER BY c.\"UserName\" DESC", cmd.CommandText()); + } + + /// + /// Tests sub query select. + /// + [Test] + public void TestSubQuerySelect() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Select(u => u(cmd.SubQuery() + .From(x => x.dbo.AccessRights.As(x.a)) + .Where(x => x.a.User_Id == x.c.Id_User) + .Select(x => x.a.IsAdmin)).As(u.IsAdmin)); + + Assert.AreEqual("SELECT (SELECT a.\"IsAdmin\" FROM \"dbo\".\"AccessRights\" AS a WHERE (a.\"User_Id\" = c.\"Id_User\")) AS \"IsAdmin\" FROM \"dbo\".\"Users\" AS c", cmd.CommandText()); + } + + /// + /// Tests sub query where. + /// + [Test] + public void TestSubQueryWhere() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Where(u => u.c.IsAdmin == u(cmd.SubQuery() + .From(x => x.dbo.AccessRights.As(x.a)) + .Where(x => x.a.User_Id == x.c.Id_User) + .Select(x => x.a.IsAdmin))); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS c WHERE (c.\"IsAdmin\" = (SELECT a.\"IsAdmin\" FROM \"dbo\".\"AccessRights\" AS a WHERE (a.\"User_Id\" = c.\"Id_User\")))", cmd.CommandText()); + } + + /// + /// Tests sub query in. + /// + [Test] + public void TestSubQueryWhereIn() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Where(u => u.c.Id_User.In(u(cmd.SubQuery() + .From(x => x.dbo.AccessRights.As(x.a)) + .Where(x => x.a.IsAdmin == 1) + .Select(x => x.a.User_Id)))); + + Assert.AreEqual(string.Format("SELECT * FROM \"dbo\".\"Users\" AS c WHERE c.\"Id_User\" IN((SELECT a.\"User_Id\" FROM \"dbo\".\"AccessRights\" AS a WHERE (a.\"IsAdmin\" = [${0}])))", cmd.Parameters.Keys.First()), cmd.CommandText()); + } + + /// + /// Tests sub query join. + /// + [Test] + public void TestSubQueryJoin() + { + IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database); + + cmd.From(u => u.dbo.Users.As(u.c)) + .Join(u => u.Inner()(cmd.SubQuery() + .From(x => x.dbo.AccessRights.As(x.a)) + .Select(x => x.a.IsAdmin, x => x.a.User_Id)).As(u.ar).On(u.ar.User_Id == u.c.Id_User)); + + Assert.AreEqual("SELECT * FROM \"dbo\".\"Users\" AS c INNER JOIN (SELECT a.\"IsAdmin\", a.\"User_Id\" FROM \"dbo\".\"AccessRights\" AS a) AS ar ON (ar.\"User_Id\" = c.\"Id_User\")", cmd.CommandText()); + } + } +} \ No newline at end of file diff --git a/DynamORM.Tests/TypedSql/TypedSqlDslTests.cs b/DynamORM.Tests/TypedSql/TypedSqlDslTests.cs new file mode 100644 index 0000000..37fb232 --- /dev/null +++ b/DynamORM.Tests/TypedSql/TypedSqlDslTests.cs @@ -0,0 +1,502 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System.Linq; +using System.Text.RegularExpressions; +using DynamORM.Tests.Helpers; +using DynamORM.TypedSql; +using NUnit.Framework; + +namespace DynamORM.Tests.TypedSql +{ + [TestFixture] + public class TypedSqlDslTests : TestsBase + { + private static string NormalizeSql(string sql) + { + int index = 0; + return Regex.Replace(sql, @"\[\$[^\]]+\]", m => string.Format("[${0}]", index++)); + } + + [SetUp] + public void SetUp() + { + CreateTestDatabase(); + CreateDynamicDatabase( + DynamicDatabaseOptions.SingleConnection | + DynamicDatabaseOptions.SingleTransaction | + DynamicDatabaseOptions.SupportLimitOffset | + DynamicDatabaseOptions.SupportNoLock); + } + + [TearDown] + public void TearDown() + { + DestroyDynamicDatabase(); + DestroyTestDatabase(); + } + + [Test] + public void TestSelectSqlWithFunctionsAndOrdering() + { + var cmd = Database.FromTyped("u") + .SelectSql( + u => Sql.Count().As("cnt"), + u => Sql.Coalesce(u.Col(x => x.Code), Sql.Val("N/A")).As("code_value")) + .GroupBySql(u => Sql.Coalesce(u.Col(x => x.Code), Sql.Val("N/A"))) + .HavingSql(u => Sql.Count().Gt(1)) + .OrderBySql(u => Sql.Count().Desc()); + + Assert.AreEqual( + "SELECT COUNT(*) AS \"cnt\", COALESCE(u.\"user_code\", [$0]) AS \"code_value\" FROM \"sample_users\" AS u GROUP BY COALESCE(u.\"user_code\", [$1]) HAVING (COUNT(*) > [$2]) ORDER BY COUNT(*) DESC", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestSelectSqlWithCase() + { + var cmd = Database.FromTyped("u") + .SelectSql(u => Sql.Case() + .When(u.Col(x => x.Code).Eq("A"), "Alpha") + .When(u.Col(x => x.Code).Eq("B"), "Beta") + .Else("Other") + .As("category")); + + Assert.AreEqual( + "SELECT CASE WHEN (u.\"user_code\" = [$0]) THEN [$1] WHEN (u.\"user_code\" = [$2]) THEN [$3] ELSE [$4] END AS \"category\" FROM \"sample_users\" AS u", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestJoinOnSql() + { + var cmd = Database.FromTyped("u") + .Join(j => j.Left().As("x").OnSql((l, r) => l.Col(a => a.Id).Eq(r.Col(a => a.Id)).And(r.Col(a => a.Code).IsNotNull()))) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual("SELECT u.\"id_user\" FROM \"sample_users\" AS u LEFT JOIN \"sample_users\" AS x ON ((u.\"id_user\" = x.\"id_user\") AND (x.\"user_code\" IS NOT NULL))", + cmd.CommandText()); + } + + [Test] + public void TestUpdateSetSqlAndWhereSql() + { + var cmd = Database.UpdateTyped() + .SetSql(u => u.Code, u => Sql.Coalesce(Sql.Val("900"), u.Col(x => x.Code))) + .WhereSql(u => u.Col(x => x.Id).Eq(1).And(u.Col(x => x.Code).IsNotNull())); + + Assert.AreEqual( + "UPDATE \"sample_users\" SET \"code\" = COALESCE([$0], \"code\") WHERE ((\"id\" = [$1]) AND (\"code\" IS NOT NULL))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestInsertSqlSupportsCase() + { + var cmd = Database.InsertTyped() + .InsertSql(u => u.Code, u => Sql.Coalesce(Sql.Val("901"), Sql.Val("fallback"))) + .InsertSql(u => u.First, u => Sql.Case().When(Sql.Val(1).Eq(1), "Typed").Else("Other")); + + Assert.AreEqual( + "INSERT INTO \"sample_users\" (\"code\", \"first\") VALUES (COALESCE([$0], [$1]), CASE WHEN ([$2] = [$3]) THEN [$4] ELSE [$5] END)", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestDeleteWhereSql() + { + var cmd = Database.DeleteTyped() + .WhereSql(u => u.Col(x => x.Id).Eq(2).And(u.Col(x => x.Code).NotEq("X"))); + + Assert.AreEqual( + "DELETE FROM \"sample_users\" WHERE ((\"id\" = [$0]) AND (\"code\" <> [$1]))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestWhereSqlSupportsLikeInAndBetween() + { + var cmd = Database.FromTyped("u") + .WhereSql(u => u.Col(x => x.Code).Like("A%") + .And(u.Col(x => x.Id).In(1, 2, 3)) + .And(u.Col(x => x.Id).Between(1, 10))) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (((u.\"user_code\" LIKE [$0]) AND (u.\"id_user\" IN([$1], [$2], [$3]))) AND (u.\"id_user\" BETWEEN [$4] AND [$5]))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestWhereSqlSupportsNotIn() + { + var cmd = Database.FromTyped("u") + .WhereSql(u => u.Col(x => x.Id).NotIn(1, 2)) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (u.\"id_user\" NOT IN([$0], [$1]))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestWhereSqlSupportsEmptyNotIn() + { + var cmd = Database.FromTyped("u") + .WhereSql(u => u.Col(x => x.Id).NotIn(new int[0])) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (1 = 1)", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestWhereSqlSupportsPatternHelpers() + { + var cmd = Database.FromTyped("u") + .WhereSql(u => u.Col(x => x.Code).StartsWith("AB") + .And(u.Col(x => x.Code).EndsWith("YZ")) + .And(u.Col(x => x.Code).Contains("MID"))) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (((u.\"user_code\" LIKE [$0]) AND (u.\"user_code\" LIKE [$1])) AND (u.\"user_code\" LIKE [$2]))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestWhereSqlSupportsEmptyIn() + { + var cmd = Database.FromTyped("u") + .WhereSql(u => u.Col(x => x.Id).In(new int[0])) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (1 = 0)", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestSelectSqlSupportsStandardFunctions() + { + var cmd = Database.FromTyped("u") + .SelectSql( + u => Sql.Sum(u.Col(x => x.Id)).As("sum_id"), + u => Sql.Avg(u.Col(x => x.Id)).As("avg_id"), + u => Sql.Min(u.Col(x => x.Id)).As("min_id"), + u => Sql.Max(u.Col(x => x.Id)).As("max_id"), + u => Sql.Abs(Sql.Val(-5)).As("abs_value"), + u => Sql.Upper(u.Col(x => x.Code)).As("upper_code"), + u => Sql.Lower(u.Col(x => x.Code)).As("lower_code"), + u => Sql.Trim(u.Col(x => x.Code)).As("trim_code"), + u => Sql.Length(u.Col(x => x.Code)).As("len_code"), + u => Sql.NullIf(u.Col(x => x.Code), Sql.Val("X")).As("nullif_code"), + u => Sql.CurrentTimestamp().As("ts")); + + Assert.AreEqual( + "SELECT SUM(u.\"id_user\") AS \"sum_id\", AVG(u.\"id_user\") AS \"avg_id\", MIN(u.\"id_user\") AS \"min_id\", MAX(u.\"id_user\") AS \"max_id\", ABS([$0]) AS \"abs_value\", UPPER(u.\"user_code\") AS \"upper_code\", LOWER(u.\"user_code\") AS \"lower_code\", TRIM(u.\"user_code\") AS \"trim_code\", LENGTH(u.\"user_code\") AS \"len_code\", NULLIF(u.\"user_code\", [$1]) AS \"nullif_code\", CURRENT_TIMESTAMP AS \"ts\" FROM \"sample_users\" AS u", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestSelectSqlSupportsArithmeticExpressions() + { + var cmd = Database.FromTyped("u") + .SelectSql( + u => (u.Col(x => x.Id) + Sql.Val(1)).As("plus_one"), + u => u.Col(x => x.Id).Sub(2).As("minus_two"), + u => u.Col(x => x.Id).Mul(3).As("times_three"), + u => u.Col(x => x.Id).Div(4).As("div_four"), + u => u.Col(x => x.Id).Mod(5).As("mod_five")); + + Assert.AreEqual( + "SELECT (u.\"id_user\" + [$0]) AS \"plus_one\", (u.\"id_user\" - [$1]) AS \"minus_two\", (u.\"id_user\" * [$2]) AS \"times_three\", (u.\"id_user\" / [$3]) AS \"div_four\", (u.\"id_user\" % [$4]) AS \"mod_five\" FROM \"sample_users\" AS u", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestSelectSqlSupportsCustomFunction() + { + var cmd = Database.FromTyped("u") + .SelectSql(u => Sql.Func("CUSTOM_FUNC", u.Col(x => x.Code), Sql.Val(5)).As("custom_value")); + + Assert.AreEqual( + "SELECT CUSTOM_FUNC(u.\"user_code\", [$0]) AS \"custom_value\" FROM \"sample_users\" AS u", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestSelectSqlSupportsWildcardAll() + { + var cmd = Database.FromTyped("u") + .SelectSql(u => u.All()); + + Assert.AreEqual( + "SELECT u.* FROM \"sample_users\" AS u", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestSelectSqlSupportsJoinedAliasHelpers() + { + var other = Sql.Table("x"); + var cmd = Database.FromTyped("u") + .Join(j => j.Left().As("x").OnSql((l, r) => l.Col(a => a.Id).Eq(r.Col(a => a.Id)))) + .SelectSql( + u => u.All(), + u => other.All(), + u => other.Col(x => x.Code).As("joined_code")); + + Assert.AreEqual( + "SELECT u.*, x.*, x.\"user_code\" AS \"joined_code\" FROM \"sample_users\" AS u LEFT JOIN \"sample_users\" AS x ON (u.\"id_user\" = x.\"id_user\")", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestWhereSqlSupportsJoinedAliasHelpers() + { + var other = Sql.Table("x"); + var cmd = Database.FromTyped("u") + .Join(j => j.Left().As("x").OnSql((l, r) => l.Col(a => a.Id).Eq(r.Col(a => a.Id)))) + .WhereSql(u => other.Col(x => x.Code).IsNotNull()) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u LEFT JOIN \"sample_users\" AS x ON (u.\"id_user\" = x.\"id_user\") WHERE (x.\"user_code\" IS NOT NULL)", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestSelectSqlSupportsScalarSubQuery() + { + var sq = Database.From(x => x.sample_users.As("x")) + .Select(x => x.x.id_user) + .Where(x => x.x.user_code == "A"); + + var cmd = Database.FromTyped("u") + .SelectSql(u => Sql.SubQuery(sq).As("sub_id")); + + Assert.AreEqual( + "SELECT (SELECT x.\"id_user\" FROM \"sample_users\" AS x WHERE (x.\"user_code\" = [$0])) AS \"sub_id\" FROM \"sample_users\" AS u", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestWhereSqlSupportsExists() + { + var sq = Database.From(x => x.sample_users.As("x")) + .Select(x => x.x.id_user) + .Where(x => x.x.user_code == "A"); + + var cmd = Database.FromTyped("u") + .WhereSql(u => Sql.Exists(sq)) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (EXISTS (SELECT x.\"id_user\" FROM \"sample_users\" AS x WHERE (x.\"user_code\" = [$0])))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestSelectSqlSupportsTypedSubQueryHelper() + { + var cmd = Database.FromTyped("u") + .SelectSql(u => Sql.SubQuery( + Database, + sq => sq + .SelectSql(x => x.Col(a => a.Id)) + .WhereSql(x => x.Col(a => a.Code).Eq("A")), + "x").As("sub_id")); + + Assert.AreEqual( + "SELECT (SELECT x.\"id_user\" FROM \"sample_users\" AS x WHERE (x.\"user_code\" = [$0])) AS \"sub_id\" FROM \"sample_users\" AS u", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestOrderBySqlSupportsNullOrderingAndRawFragments() + { + var cmd = Database.FromTyped("u") + .SelectSql(u => u.Col(x => x.Id)) + .OrderBySql( + u => u.Col(x => x.Code).Asc().NullsLast(), + u => Sql.RawOrder("2 DESC")); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u ORDER BY u.\"user_code\" ASC NULLS LAST, 2 DESC", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestWhereSqlSupportsTypedExistsHelper() + { + var cmd = Database.FromTyped("u") + .WhereSql(u => Sql.Exists( + Database, + sq => sq + .SelectSql(x => x.Col(a => a.Id)) + .WhereSql(x => x.Col(a => a.Code).Eq("A")), + "x")) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (EXISTS (SELECT x.\"id_user\" FROM \"sample_users\" AS x WHERE (x.\"user_code\" = [$0])))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestInsertSqlObjectProjection() + { + var sq = Database.From(x => x.sample_users.As("x")) + .Select(x => x.x.user_code) + .Where(x => x.x.id_user == 1); + + var cmd = Database.InsertTyped() + .InsertSql(u => new + { + Code = Sql.SubQuery(sq), + First = Sql.Upper(Sql.Val("typed")) + }); + + Assert.AreEqual( + "INSERT INTO \"sample_users\" (\"code\", \"first\") VALUES ((SELECT x.\"user_code\" FROM \"sample_users\" AS x WHERE (x.\"id_user\" = [$0])), UPPER([$1]))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestUpdateSqlObjectProjection() + { + var sq = Database.From(x => x.sample_users.As("x")) + .Select(x => x.x.user_code) + .Where(x => x.x.id_user == 1); + + var cmd = Database.UpdateTyped() + .SetSql(u => new + { + Code = Sql.SubQuery(sq), + First = Sql.Lower(Sql.Val("TYPED")) + }) + .WhereSql(u => u.Col(x => x.Id).Eq(1)); + + Assert.AreEqual( + "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())); + } + + [Test] + public void TestSelectSqlSupportsPositionalJoinedContexts() + { + var cmd = Database.FromTyped("u") + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))) + .SelectSql( + (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("u") + .Join(j => j.Inner().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))) + .SelectSql( + (u, c) => u.Col(x => x.IdUser), + (u, c) => Sql.Count(c.Col(x => x.UserId)).As("cnt")) + .WhereSql((u, c) => u.Col(x => x.Active).Eq(1).And(c.Col(x => x.Deleted).Eq(0))) + .GroupBySql( + (u, c) => u.Col(x => x.IdUser), + (u, c) => c.Col(x => x.Users)) + .HavingSql((u, c) => Sql.Count(c.Col(x => x.UserId)).Gt(0)) + .OrderBySql( + (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("u") + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))) + .Join(j => j.Left().As("r").OnSql((u, r) => u.Col(x => x.IdUser).Eq(r.Col(x => x.UserId)))) + .Join(j => j.Left().As("g").OnSql((u, g) => u.Col(x => x.IdUser).Eq(g.Col(x => x.UserId)))) + .SelectSql( + (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( + (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( + (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("u") + .Join(j => j.Left().As("b").OnSql((u, b) => u.Col(x => x.Id).Eq(b.Col(x => x.Id)))) + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.Id).Eq(c.Col(x => x.Id)))) + .Join(j => j.Left().As("d").OnSql((u, d) => u.Col(x => x.Id).Eq(d.Col(x => x.Id)))) + .Join(j => j.Left().As("e").OnSql((u, e) => u.Col(x => x.Id).Eq(e.Col(x => x.Id)))) + .SelectSql( + (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( + (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("u") + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))); + + var ex = Assert.Throws(() => + builder.SelectSql((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("u") + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))); + + var ex = Assert.Throws(() => + builder.SelectSql((u, c, r) => r.Col(x => x.RoleId).As("role_id"))); + + Assert.AreEqual( + "Typed join context at position 2 is not available.", + ex.Message); + } + } +} diff --git a/DynamORM.Tests/TypedSql/TypedSqlScopeDslTests.cs b/DynamORM.Tests/TypedSql/TypedSqlScopeDslTests.cs new file mode 100644 index 0000000..b139eb8 --- /dev/null +++ b/DynamORM.Tests/TypedSql/TypedSqlScopeDslTests.cs @@ -0,0 +1,214 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System.Text.RegularExpressions; +using DynamORM.Tests.Helpers; +using DynamORM.TypedSql; +using NUnit.Framework; + +namespace DynamORM.Tests.TypedSql +{ + [TestFixture] + public class TypedSqlScopeDslTests : TestsBase + { + private static string NormalizeSql(string sql) + { + int index = 0; + return Regex.Replace(sql, @"\[\$[^\]]+\]", m => string.Format("[${0}]", index++)); + } + + [SetUp] + public void SetUp() + { + CreateTestDatabase(); + CreateDynamicDatabase( + DynamicDatabaseOptions.SingleConnection | + DynamicDatabaseOptions.SingleTransaction | + DynamicDatabaseOptions.SupportLimitOffset | + DynamicDatabaseOptions.SupportNoLock); + } + + [TearDown] + public void TearDown() + { + DestroyDynamicDatabase(); + DestroyTestDatabase(); + } + + [Test] + public void TestScopeBuilderSupportsTwoTableSelectAndWhere() + { + var cmd = Database.FromTypedScope("u") + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))) + .SelectSql( + (u, c) => u.Col(x => x.IdUser).As("user_id"), + (u, c) => c.Col(x => x.Users).As("users")) + .WhereSql((u, c) => u.Col(x => x.Active).Eq(1).And(c.Col(x => x.Deleted).Eq(0))); + + Assert.AreEqual( + "SELECT u.\"Id_User\" AS \"user_id\", c.\"Users\" AS \"users\" FROM \"dbo\".\"Users\" AS u LEFT JOIN \"dbo\".\"UserClients\" AS c ON (u.\"Id_User\" = c.\"User_Id\") WHERE ((u.\"Active\" = [$0]) AND (c.\"Deleted\" = [$1]))", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestScopeBuilderSupportsJoinOnPreviousJoinedAlias() + { + var cmd = Database.FromTypedScope("u") + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))) + .Join(j => j.Left().As("r").OnSql((u, c, r) => c.Col(x => x.UserId).Eq(r.Col(x => x.UserId)))) + .SelectSql( + (u, c, r) => u.Col(x => x.IdUser), + (u, c, r) => c.Col(x => x.Users).As("users"), + (u, c, r) => r.Col(x => x.RoleName).As("role_name")) + .OrderBySql( + (u, c, r) => c.Col(x => x.Users).Asc(), + (u, c, r) => r.Col(x => x.RoleName).Desc()); + + Assert.AreEqual( + "SELECT u.\"Id_User\", c.\"Users\" AS \"users\", r.\"Role_Name\" AS \"role_name\" 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 (c.\"User_Id\" = r.\"User_Id\") ORDER BY c.\"Users\" ASC, r.\"Role_Name\" DESC", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestScopeBuilderSupportsCustomJoinTypeAndNoLock() + { + var cmd = Database.FromTypedScope("u") + .Join(j => j.Type("CROSS APPLY").As("c").NoLock()) + .SelectSql( + (u, c) => u.Col(x => x.IdUser), + (u, c) => c.All()); + + Assert.AreEqual( + "SELECT u.\"Id_User\", c.* FROM \"dbo\".\"Users\" AS u CROSS APPLY \"dbo\".\"UserClients\" AS c WITH(NOLOCK)", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestScopeBuilderSupportsHavingAcrossFourJoinedTables() + { + var cmd = Database.FromTypedScope("u") + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))) + .Join(j => j.Left().As("r").OnSql((u, c, r) => u.Col(x => x.IdUser).Eq(r.Col(x => x.UserId)))) + .Join(j => j.Left().As("g").OnSql((u, c, r, g) => r.Col(x => x.UserId).Eq(g.Col(x => x.UserId)))) + .SelectSql( + (u, c, r, g) => u.Col(x => x.IdUser), + (u, c, r, g) => Sql.Count(g.Col(x => x.RegionId)).As("region_count")) + .GroupBySql((u, c, r, g) => u.Col(x => x.IdUser)) + .HavingSql((u, c, r, g) => Sql.Count(g.Col(x => x.RegionId)).Gt(0)); + + Assert.AreEqual( + "SELECT u.\"Id_User\", COUNT(g.\"Region_Id\") AS \"region_count\" 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 (r.\"User_Id\" = g.\"User_Id\") GROUP BY u.\"Id_User\" HAVING (COUNT(g.\"Region_Id\") > [$0])", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestScopeBuilderSupportsFiveTypedTables() + { + var cmd = Database.FromTypedScope("u") + .Join(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId)))) + .Join(j => j.Left().As("r").OnSql((u, c, r) => c.Col(x => x.UserId).Eq(r.Col(x => x.UserId)))) + .Join(j => j.Left().As("g").OnSql((u, c, r, g) => r.Col(x => x.UserId).Eq(g.Col(x => x.UserId)))) + .Join(j => j.Left().As("d").OnSql((u, c, r, g, d) => g.Col(x => x.RegionId).Eq(d.Col(x => x.RegionId)))) + .SelectSql( + (u, c, r, g, d) => u.Col(x => x.IdUser).As("user_id"), + (u, c, r, g, d) => d.Col(x => x.DepartmentName).As("department_name")) + .WhereSql((u, c, r, g, d) => d.Col(x => x.DepartmentId).Gt(0)) + .OrderBySql((u, c, r, g, d) => d.Col(x => x.DepartmentName).Asc()); + + Assert.AreEqual( + "SELECT u.\"Id_User\" AS \"user_id\", d.\"Department_Name\" AS \"department_name\" 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 (c.\"User_Id\" = r.\"User_Id\") LEFT JOIN \"dbo\".\"UserRegions\" AS g ON (r.\"User_Id\" = g.\"User_Id\") LEFT JOIN \"dbo\".\"UserDepartments\" AS d ON (g.\"Region_Id\" = d.\"Region_Id\") WHERE (d.\"Department_Id\" > [$0]) ORDER BY d.\"Department_Name\" ASC", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestScopeBuilderSupportsTenTypedTables() + { + var cmd = Database.FromTypedScope("a") + .Join(j => j.Left().As("b").OnSql((a, b) => a.Col(x => x.Id).Eq(b.Col(x => x.Id)))) + .Join(j => j.Left().As("c").OnSql((a, b, c) => b.Col(x => x.Id).Eq(c.Col(x => x.Id)))) + .Join(j => j.Left().As("d").OnSql((a, b, c, d) => c.Col(x => x.Id).Eq(d.Col(x => x.Id)))) + .Join(j => j.Left().As("e").OnSql((a, b, c, d, e) => d.Col(x => x.Id).Eq(e.Col(x => x.Id)))) + .Join(j => j.Left().As("f").OnSql((a, b, c, d, e, f) => e.Col(x => x.Id).Eq(f.Col(x => x.Id)))) + .Join(j => j.Left().As("g").OnSql((a, b, c, d, e, f, g) => f.Col(x => x.Id).Eq(g.Col(x => x.Id)))) + .Join(j => j.Left().As("h").OnSql((a, b, c, d, e, f, g, h) => g.Col(x => x.Id).Eq(h.Col(x => x.Id)))) + .Join(j => j.Left().As("i").OnSql((a, b, c, d, e, f, g, h, i) => h.Col(x => x.Id).Eq(i.Col(x => x.Id)))) + .Join(j => j.Left().As("j").OnSql((a, b, c, d, e, f, g, h, i, j) => i.Col(x => x.Id).Eq(j.Col(x => x.Id)))) + .SelectSql( + (a, b, c, d, e, f, g, h, i, j) => a.Col(x => x.Id).As("root_id"), + (a, b, c, d, e, f, g, h, i, j) => j.Col(x => x.Code).As("last_code")) + .WhereSql((a, b, c, d, e, f, g, h, i, j) => j.Col(x => x.Code).IsNotNull()) + .OrderBySql((a, b, c, d, e, f, g, h, i, j) => j.Col(x => x.Code).Asc()); + + Assert.AreEqual( + "SELECT a.\"id_user\" AS \"root_id\", j.\"user_code\" AS \"last_code\" FROM \"sample_users\" AS a LEFT JOIN \"sample_users\" AS b ON (a.\"id_user\" = b.\"id_user\") LEFT JOIN \"sample_users\" AS c ON (b.\"id_user\" = c.\"id_user\") LEFT JOIN \"sample_users\" AS d ON (c.\"id_user\" = d.\"id_user\") LEFT JOIN \"sample_users\" AS e ON (d.\"id_user\" = e.\"id_user\") LEFT JOIN \"sample_users\" AS f ON (e.\"id_user\" = f.\"id_user\") LEFT JOIN \"sample_users\" AS g ON (f.\"id_user\" = g.\"id_user\") LEFT JOIN \"sample_users\" AS h ON (g.\"id_user\" = h.\"id_user\") LEFT JOIN \"sample_users\" AS i ON (h.\"id_user\" = i.\"id_user\") LEFT JOIN \"sample_users\" AS j ON (i.\"id_user\" = j.\"id_user\") WHERE (j.\"user_code\" IS NOT NULL) ORDER BY j.\"user_code\" ASC", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestScopeBuilderSupportsSixteenTypedTables() + { + var cmd = Database.FromTypedScope("a") + .Join(j => j.Left().As("b").OnSql((a, b) => a.Col(x => x.Id).Eq(b.Col(x => x.Id)))) + .Join(j => j.Left().As("c").OnSql((a, b, c) => b.Col(x => x.Id).Eq(c.Col(x => x.Id)))) + .Join(j => j.Left().As("d").OnSql((a, b, c, d) => c.Col(x => x.Id).Eq(d.Col(x => x.Id)))) + .Join(j => j.Left().As("e").OnSql((a, b, c, d, e) => d.Col(x => x.Id).Eq(e.Col(x => x.Id)))) + .Join(j => j.Left().As("f").OnSql((a, b, c, d, e, f) => e.Col(x => x.Id).Eq(f.Col(x => x.Id)))) + .Join(j => j.Left().As("g").OnSql((a, b, c, d, e, f, g) => f.Col(x => x.Id).Eq(g.Col(x => x.Id)))) + .Join(j => j.Left().As("h").OnSql((a, b, c, d, e, f, g, h) => g.Col(x => x.Id).Eq(h.Col(x => x.Id)))) + .Join(j => j.Left().As("i").OnSql((a, b, c, d, e, f, g, h, i) => h.Col(x => x.Id).Eq(i.Col(x => x.Id)))) + .Join(j => j.Left().As("j").OnSql((a, b, c, d, e, f, g, h, i, j) => i.Col(x => x.Id).Eq(j.Col(x => x.Id)))) + .Join(j => j.Left().As("k").OnSql((a, b, c, d, e, f, g, h, i, j, k) => j.Col(x => x.Id).Eq(k.Col(x => x.Id)))) + .Join(j => j.Left().As("l").OnSql((a, b, c, d, e, f, g, h, i, j, k, l) => k.Col(x => x.Id).Eq(l.Col(x => x.Id)))) + .Join(j => j.Left().As("m").OnSql((a, b, c, d, e, f, g, h, i, j, k, l, m) => l.Col(x => x.Id).Eq(m.Col(x => x.Id)))) + .Join(j => j.Left().As("n").OnSql((a, b, c, d, e, f, g, h, i, j, k, l, m, n) => m.Col(x => x.Id).Eq(n.Col(x => x.Id)))) + .Join(j => j.Left().As("o").OnSql((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) => n.Col(x => x.Id).Eq(o.Col(x => x.Id)))) + .Join(j => j.Left().As("p").OnSql((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) => o.Col(x => x.Id).Eq(p.Col(x => x.Id)))) + .SelectSql( + (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) => a.Col(x => x.Id).As("root_id"), + (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) => p.Col(x => x.Code).As("tail_code")) + .WhereSql((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) => p.Col(x => x.Code).IsNotNull()); + + Assert.AreEqual( + "SELECT a.\"id_user\" AS \"root_id\", p.\"user_code\" AS \"tail_code\" FROM \"sample_users\" AS a LEFT JOIN \"sample_users\" AS b ON (a.\"id_user\" = b.\"id_user\") LEFT JOIN \"sample_users\" AS c ON (b.\"id_user\" = c.\"id_user\") LEFT JOIN \"sample_users\" AS d ON (c.\"id_user\" = d.\"id_user\") LEFT JOIN \"sample_users\" AS e ON (d.\"id_user\" = e.\"id_user\") LEFT JOIN \"sample_users\" AS f ON (e.\"id_user\" = f.\"id_user\") LEFT JOIN \"sample_users\" AS g ON (f.\"id_user\" = g.\"id_user\") LEFT JOIN \"sample_users\" AS h ON (g.\"id_user\" = h.\"id_user\") LEFT JOIN \"sample_users\" AS i ON (h.\"id_user\" = i.\"id_user\") LEFT JOIN \"sample_users\" AS j ON (i.\"id_user\" = j.\"id_user\") LEFT JOIN \"sample_users\" AS k ON (j.\"id_user\" = k.\"id_user\") LEFT JOIN \"sample_users\" AS l ON (k.\"id_user\" = l.\"id_user\") LEFT JOIN \"sample_users\" AS m ON (l.\"id_user\" = m.\"id_user\") LEFT JOIN \"sample_users\" AS n ON (m.\"id_user\" = n.\"id_user\") LEFT JOIN \"sample_users\" AS o ON (n.\"id_user\" = o.\"id_user\") LEFT JOIN \"sample_users\" AS p ON (o.\"id_user\" = p.\"id_user\") WHERE (p.\"user_code\" IS NOT NULL)", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestScopeSubQueryHelperSupportsScopedJoinChain() + { + var cmd = Database.FromTyped("u") + .SelectSql(u => Sql.SubQueryScope( + Database, + sq => sq + .Join(j => j.Left().As("c").OnSql((x, c) => x.Col(a => a.IdUser).Eq(c.Col(a => a.UserId)))) + .Join(j => j.Left().As("r").OnSql((x, c, r) => c.Col(a => a.UserId).Eq(r.Col(a => a.UserId)))) + .SelectSql((x, c, r) => r.Col(a => a.RoleName)), + "x").As("role_name")); + + Assert.AreEqual( + "SELECT (SELECT r.\"Role_Name\" FROM \"dbo\".\"Users\" AS x LEFT JOIN \"dbo\".\"UserClients\" AS c ON (x.\"Id_User\" = c.\"User_Id\") LEFT JOIN \"dbo\".\"UserRoles\" AS r ON (c.\"User_Id\" = r.\"User_Id\")) AS \"role_name\" FROM \"sample_users\" AS u", + NormalizeSql(cmd.CommandText())); + } + + [Test] + public void TestScopeExistsHelperSupportsScopedJoinChain() + { + var cmd = Database.FromTyped("u") + .WhereSql(u => Sql.ExistsScope( + Database, + sq => sq + .Join(j => j.Left().As("c").OnSql((x, c) => x.Col(a => a.IdUser).Eq(c.Col(a => a.UserId)))) + .Join(j => j.Left().As("r").OnSql((x, c, r) => c.Col(a => a.UserId).Eq(r.Col(a => a.UserId)))) + .SelectSql((x, c, r) => r.Col(a => a.RoleId)), + "x")) + .SelectSql(u => u.Col(x => x.Id)); + + Assert.AreEqual( + "SELECT u.\"id_user\" FROM \"sample_users\" AS u WHERE (EXISTS (SELECT r.\"Role_Id\" FROM \"dbo\".\"Users\" AS x LEFT JOIN \"dbo\".\"UserClients\" AS c ON (x.\"Id_User\" = c.\"User_Id\") LEFT JOIN \"dbo\".\"UserRoles\" AS r ON (c.\"User_Id\" = r.\"User_Id\")))", + NormalizeSql(cmd.CommandText())); + } + } +} diff --git a/DynamORM/Builders/DynamicJoinType.cs b/DynamORM/Builders/DynamicJoinType.cs new file mode 100644 index 0000000..b81a498 --- /dev/null +++ b/DynamORM/Builders/DynamicJoinType.cs @@ -0,0 +1,21 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +namespace DynamORM.Builders +{ + /// Typed join kind used by typed fluent builder APIs. + public enum DynamicJoinType + { + Inner = 0, + Join, + Left, + Right, + Full, + LeftOuter, + RightOuter, + FullOuter + } +} diff --git a/DynamORM/Builders/IDynamicTypedDeleteQueryBuilder.cs b/DynamORM/Builders/IDynamicTypedDeleteQueryBuilder.cs new file mode 100644 index 0000000..d643ea3 --- /dev/null +++ b/DynamORM/Builders/IDynamicTypedDeleteQueryBuilder.cs @@ -0,0 +1,25 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Linq.Expressions; +using DynamORM.TypedSql; + +namespace DynamORM.Builders +{ + /// Typed delete query builder for mapped entities. + /// Mapped entity type. + public interface IDynamicTypedDeleteQueryBuilder : IDynamicDeleteQueryBuilder + { + /// Add typed where predicate using mapped properties. + /// Predicate to parse. + /// Builder instance. + IDynamicTypedDeleteQueryBuilder Where(Expression> predicate); + + /// Add typed SQL DSL where predicate. + IDynamicTypedDeleteQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate); + } +} diff --git a/DynamORM/Builders/IDynamicTypedInsertQueryBuilder.cs b/DynamORM/Builders/IDynamicTypedInsertQueryBuilder.cs new file mode 100644 index 0000000..87a6f1c --- /dev/null +++ b/DynamORM/Builders/IDynamicTypedInsertQueryBuilder.cs @@ -0,0 +1,35 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Linq.Expressions; +using DynamORM.TypedSql; + +namespace DynamORM.Builders +{ + /// Typed insert query builder for mapped entities. + /// Mapped entity type. + public interface IDynamicTypedInsertQueryBuilder : IDynamicInsertQueryBuilder + { + /// Add typed insert assignment using mapped property selector. + /// Property type. + /// Property selector. + /// Value to insert. + /// Builder instance. + IDynamicTypedInsertQueryBuilder Insert(Expression> selector, object value); + + /// Add values from mapped object. + /// Mapped object value. + /// Builder instance. + IDynamicTypedInsertQueryBuilder Insert(T value); + + /// Add typed SQL DSL insert assignment. + IDynamicTypedInsertQueryBuilder InsertSql(Expression> selector, Func, TypedSqlExpression> valueFactory); + + /// Add typed SQL DSL insert assignments from object projection. + IDynamicTypedInsertQueryBuilder InsertSql(Func, object> values); + } +} diff --git a/DynamORM/Builders/IDynamicTypedSelectQueryBuilder.cs b/DynamORM/Builders/IDynamicTypedSelectQueryBuilder.cs new file mode 100644 index 0000000..9982dcf --- /dev/null +++ b/DynamORM/Builders/IDynamicTypedSelectQueryBuilder.cs @@ -0,0 +1,169 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Linq.Expressions; +using DynamORM.TypedSql; + +namespace DynamORM.Builders +{ + /// Typed select query builder for mapped entities. + /// Mapped entity type. + public interface IDynamicTypedSelectQueryBuilder : IDynamicSelectQueryBuilder + { + /// Add typed join to mapped table. + /// Joined mapped entity type. + /// Join ON predicate. + /// Optional alias for joined table. + /// Join type. + /// Adds NOLOCK hint to joined source when supported by provider options. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Join(Expression> on, string alias = null, DynamicJoinType joinType = DynamicJoinType.Inner, bool noLock = false); + + /// Add typed join with custom join type text (for example: CROSS APPLY). + /// Joined mapped entity type. + /// Optional join ON predicate. + /// Optional alias for joined table. + /// Join type text. + /// Adds NOLOCK hint to joined source when supported by provider options. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Join(Expression> on, string alias, string joinType, bool noLock = false); + + /// Add typed join using join-spec builder syntax (As(), join kind and On()). + /// Joined mapped entity type. + /// Join specification builder callback. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Join(Func, TypedJoinBuilder> specification); + + /// Add typed where predicate using mapped properties. + /// Predicate to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Where(Expression> predicate); + + /// Add typed having predicate using mapped properties. + /// Predicate to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Having(Expression> predicate); + + /// Add typed selected columns using mapped properties. + /// Projection type. + /// Selector to parse. + /// Additional selectors to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder Select(Expression> selector, params Expression>[] selectors); + + /// Add typed group by columns using mapped properties. + /// Projection type. + /// Selector to parse. + /// Additional selectors to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder GroupBy(Expression> selector, params Expression>[] selectors); + + /// Add typed order by columns using mapped properties. Supports Asc()/Desc(). + /// Projection type. + /// Selector to parse. + /// Additional selectors to parse. + /// Builder instance. + IDynamicTypedSelectQueryBuilder OrderBy(Expression> selector, params Expression>[] selectors); + + /// Add typed SQL DSL select items. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedSqlSelectable> selector, params Func, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL where predicate. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL group by expressions. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedSqlExpression> selector, params Func, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL order by expressions. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedSqlOrderExpression> selector, params Func, TypedSqlOrderExpression>[] selectors); + + /// Add typed SQL DSL select items using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL select items using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL select items using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL select items using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + + /// Add typed SQL DSL where predicate using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL where predicate using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL where predicate using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL where predicate using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL having predicate using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL group-by expression using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL group-by expression using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL group-by expression using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL group-by expression using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + + /// Add typed SQL DSL order-by expression using root and first joined table contexts. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedSqlOrderExpression>[] selectors); + + /// Add typed SQL DSL order-by expression using root and first two joined table contexts. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + + /// Add typed SQL DSL order-by expression using root and first three joined table contexts. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + + /// Add typed SQL DSL order-by expression using root and first four joined table contexts. + IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } +} diff --git a/DynamORM/Builders/IDynamicTypedSelectScopeQueryBuilder.cs b/DynamORM/Builders/IDynamicTypedSelectScopeQueryBuilder.cs new file mode 100644 index 0000000..d27fab9 --- /dev/null +++ b/DynamORM/Builders/IDynamicTypedSelectScopeQueryBuilder.cs @@ -0,0 +1,171 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using DynamORM.TypedSql; + +namespace DynamORM.Builders +{ + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedSqlSelectable> selector, params Func, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedSqlExpression> selector, params Func, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedSqlOrderExpression> selector, params Func, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification); + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + + public interface IDynamicTypedSelectScopeQueryBuilder : IDynamicSelectQueryBuilder + { + IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors); + IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate); + IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors); + IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors); + } + +} \ No newline at end of file diff --git a/DynamORM/Builders/IDynamicTypedUpdateQueryBuilder.cs b/DynamORM/Builders/IDynamicTypedUpdateQueryBuilder.cs new file mode 100644 index 0000000..5d3aa9e --- /dev/null +++ b/DynamORM/Builders/IDynamicTypedUpdateQueryBuilder.cs @@ -0,0 +1,43 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Linq.Expressions; +using DynamORM.TypedSql; + +namespace DynamORM.Builders +{ + /// Typed update query builder for mapped entities. + /// Mapped entity type. + public interface IDynamicTypedUpdateQueryBuilder : IDynamicUpdateQueryBuilder + { + /// Add typed where predicate using mapped properties. + /// Predicate to parse. + /// Builder instance. + IDynamicTypedUpdateQueryBuilder Where(Expression> predicate); + + /// Add typed assignment using mapped property selector. + /// Property type. + /// Property selector. + /// Assigned value. + /// Builder instance. + IDynamicTypedUpdateQueryBuilder Set(Expression> selector, object value); + + /// Add update values from mapped object. + /// Mapped object value. + /// Builder instance. + IDynamicTypedUpdateQueryBuilder Values(T value); + + /// Add typed SQL DSL where predicate. + IDynamicTypedUpdateQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate); + + /// Add typed SQL DSL assignment. + IDynamicTypedUpdateQueryBuilder SetSql(Expression> selector, Func, TypedSqlExpression> valueFactory); + + /// Add typed SQL DSL assignments from object projection. + IDynamicTypedUpdateQueryBuilder SetSql(Func, object> values); + } +} diff --git a/DynamORM/Builders/Implementation/DynamicInsertQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicInsertQueryBuilder.cs index 35d78bf..45aa71d 100644 --- a/DynamORM/Builders/Implementation/DynamicInsertQueryBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicInsertQueryBuilder.cs @@ -40,8 +40,8 @@ namespace DynamORM.Builders.Implementation /// Implementation of dynamic insert query builder. internal class DynamicInsertQueryBuilder : DynamicModifyBuilder, IDynamicInsertQueryBuilder { - private string _columns; - private string _values; + protected string _columns; + protected string _values; /// /// Initializes a new instance of the class. @@ -221,4 +221,4 @@ namespace DynamORM.Builders.Implementation #endregion IExtendedDisposable } -} \ No newline at end of file +} diff --git a/DynamORM/Builders/Implementation/DynamicSelectQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicSelectQueryBuilder.cs index 5bc86d3..e95dfb4 100644 --- a/DynamORM/Builders/Implementation/DynamicSelectQueryBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicSelectQueryBuilder.cs @@ -42,17 +42,17 @@ using DynamORM.Mapper; namespace DynamORM.Builders.Implementation { /// Implementation of dynamic select query builder. - internal class DynamicSelectQueryBuilder : DynamicQueryBuilder, IDynamicSelectQueryBuilder, DynamicQueryBuilder.IQueryWithWhere, DynamicQueryBuilder.IQueryWithHaving + internal class DynamicSelectQueryBuilder : DynamicQueryBuilder, IDynamicSelectQueryBuilder, DynamicQueryBuilder.IQueryWithWhere, DynamicQueryBuilder.IQueryWithHaving { private int? _limit = null; private int? _offset = null; private bool _distinct = false; - private string _select; - private string _from; - private string _join; - private string _groupby; - private string _orderby; + protected string _select; + private string _from; + protected string _join; + protected string _groupby; + protected string _orderby; #region IQueryWithHaving @@ -1452,4 +1452,4 @@ namespace DynamORM.Builders.Implementation #endregion IExtendedDisposable } -} \ No newline at end of file +} diff --git a/DynamORM/Builders/Implementation/DynamicTypedDeleteQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicTypedDeleteQueryBuilder.cs new file mode 100644 index 0000000..9b94847 --- /dev/null +++ b/DynamORM/Builders/Implementation/DynamicTypedDeleteQueryBuilder.cs @@ -0,0 +1,98 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using DynamORM.Builders.Extensions; +using DynamORM.TypedSql; + +namespace DynamORM.Builders.Implementation +{ + /// Typed wrapper over with property-to-column translation. + /// Mapped entity type. + internal class DynamicTypedDeleteQueryBuilder : DynamicDeleteQueryBuilder, IDynamicTypedDeleteQueryBuilder + { + internal DynamicTypedDeleteQueryBuilder(DynamicDatabase db) + : this(db, false) + { + } + + internal DynamicTypedDeleteQueryBuilder(DynamicDatabase db, bool mapType) + : base(db) + { + if (mapType) + this.Table(typeof(T)); + else + this.Table(typeof(T).Name); + } + + public IDynamicTypedDeleteQueryBuilder Where(Expression> predicate) + { + TypedModifyHelper.ApplyWhere((c, o, v) => base.Where(c, o, v), predicate); + return this; + } + + public IDynamicTypedDeleteQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate) + { + string condition = TypedModifyHelper.RenderPredicate(predicate, null, RenderValue, Database.DecorateName, RenderSubQuery); + if (string.IsNullOrEmpty(WhereCondition)) + WhereCondition = condition; + else + WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition); + + return this; + } + + public new IDynamicTypedDeleteQueryBuilder Where(Func func) + { + base.Where(func); + return this; + } + + public new IDynamicTypedDeleteQueryBuilder Where(DynamicColumn column) + { + base.Where(column); + return this; + } + + public new IDynamicTypedDeleteQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value) + { + base.Where(column, op, value); + return this; + } + + public new IDynamicTypedDeleteQueryBuilder Where(string column, object value) + { + base.Where(column, value); + return this; + } + + public new IDynamicTypedDeleteQueryBuilder Where(object conditions, bool schema = false) + { + base.Where(conditions, schema); + return this; + } + + private string RenderValue(object value) + { + if (value == null) + return "NULL"; + + DynamicSchemaColumn? columnSchema = null; + return ParseConstant(value, Parameters, columnSchema); + } + + private string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query) + { + foreach (KeyValuePair item in query.Parameters) + if (!Parameters.ContainsKey(item.Key)) + Parameters.Add(item.Key, item.Value); + + return query.CommandText(); + } + } +} diff --git a/DynamORM/Builders/Implementation/DynamicTypedInsertQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicTypedInsertQueryBuilder.cs new file mode 100644 index 0000000..7436587 --- /dev/null +++ b/DynamORM/Builders/Implementation/DynamicTypedInsertQueryBuilder.cs @@ -0,0 +1,112 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using DynamORM.Builders.Extensions; +using DynamORM.Helpers.Dynamics; +using DynamORM.TypedSql; + +namespace DynamORM.Builders.Implementation +{ + /// Typed wrapper over with property-to-column translation. + /// Mapped entity type. + internal class DynamicTypedInsertQueryBuilder : DynamicInsertQueryBuilder, IDynamicTypedInsertQueryBuilder + { + internal DynamicTypedInsertQueryBuilder(DynamicDatabase db) + : this(db, false) + { + } + + internal DynamicTypedInsertQueryBuilder(DynamicDatabase db, bool mapType) + : base(db) + { + if (mapType) + this.Table(typeof(T)); + else + this.Table(typeof(T).Name); + } + + public IDynamicTypedInsertQueryBuilder Insert(Expression> selector, object value) + { + base.Insert(TypedModifyHelper.GetMappedColumn(selector), value); + return this; + } + + public IDynamicTypedInsertQueryBuilder Insert(T value) + { + base.Insert(value); + return this; + } + + public IDynamicTypedInsertQueryBuilder InsertSql(Expression> selector, Func, TypedSqlExpression> valueFactory) + { + string column = FixObjectName(TypedModifyHelper.GetMappedColumn(selector), onlyColumn: true); + string value = TypedModifyHelper.RenderExpression(valueFactory, null, RenderValue, Database.DecorateName, RenderSubQuery); + + _columns = _columns == null ? column : string.Format("{0}, {1}", _columns, column); + _values = _values == null ? value : string.Format("{0}, {1}", _values, value); + return this; + } + + public IDynamicTypedInsertQueryBuilder InsertSql(Func, object> values) + { + if (values == null) + throw new ArgumentNullException("values"); + + object data = values(new TypedTableContext(null)); + foreach (KeyValuePair item in data.ToDictionary()) + { + string column = FixObjectName(TypedModifyHelper.GetMappedColumnByName(typeof(T), item.Key), onlyColumn: true); + string value = (item.Value as TypedSqlExpression) != null + ? TypedModifyHelper.RenderExpression(u => (TypedSqlExpression)item.Value, null, RenderValue, Database.DecorateName, RenderSubQuery) + : RenderValue(item.Value); + + _columns = _columns == null ? column : string.Format("{0}, {1}", _columns, column); + _values = _values == null ? value : string.Format("{0}, {1}", _values, value); + } + + return this; + } + + public new IDynamicTypedInsertQueryBuilder Values(Func fn, params Func[] func) + { + base.Values(fn, func); + return this; + } + + public new IDynamicTypedInsertQueryBuilder Insert(string column, object value) + { + base.Insert(column, value); + return this; + } + + public new IDynamicTypedInsertQueryBuilder Insert(object o) + { + base.Insert(o); + return this; + } + + private string RenderValue(object value) + { + if (value == null) + return "NULL"; + + DynamicSchemaColumn? columnSchema = null; + return ParseConstant(value, Parameters, columnSchema); + } + + private string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query) + { + foreach (KeyValuePair item in query.Parameters) + if (!Parameters.ContainsKey(item.Key)) + Parameters.Add(item.Key, item.Value); + + return query.CommandText(); + } + } +} diff --git a/DynamORM/Builders/Implementation/DynamicTypedSelectQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicTypedSelectQueryBuilder.cs new file mode 100644 index 0000000..5b02ad4 --- /dev/null +++ b/DynamORM/Builders/Implementation/DynamicTypedSelectQueryBuilder.cs @@ -0,0 +1,1204 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using DynamORM.Helpers; +using DynamORM.Mapper; +using DynamORM.TypedSql; + +namespace DynamORM.Builders.Implementation +{ + /// Typed wrapper over with property-to-column translation. + /// Mapped entity type. + internal class DynamicTypedSelectQueryBuilder : DynamicSelectQueryBuilder, IDynamicTypedSelectQueryBuilder + { + private sealed class TypedJoinInfo + { + public Type ModelType { get; set; } + public string Alias { get; set; } + } + + private sealed class TypedSqlRenderContext : ITypedSqlRenderContext + { + private readonly DynamicTypedSelectQueryBuilder _builder; + + public TypedSqlRenderContext(DynamicTypedSelectQueryBuilder builder) + { + _builder = builder; + } + + public string ResolveColumn(Type modelType, string memberName, string alias) + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(modelType); + if (mapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", modelType.FullName)); + + string mappedColumn = mapper.PropertyMap.TryGetValue(memberName) + ?? mapper.PropertyMap.Where(x => string.Equals(x.Key, memberName, StringComparison.OrdinalIgnoreCase)).Select(x => x.Value).FirstOrDefault() + ?? memberName; + + return string.IsNullOrEmpty(alias) + ? _builder.Database.DecorateName(mappedColumn) + : string.Format("{0}.{1}", alias, _builder.Database.DecorateName(mappedColumn)); + } + + public string RenderValue(object value) + { + if (value == null) + return "NULL"; + + DynamicSchemaColumn? columnSchema = null; + return _builder.ParseConstant(value, _builder.Parameters, columnSchema); + } + + public string DecorateName(string name) + { + return _builder.Database.DecorateName(name); + } + + public string RenderSubQuery(IDynamicSelectQueryBuilder query) + { + if (query == null) + throw new ArgumentNullException("query"); + + foreach (var item in query.Parameters) + if (!_builder.Parameters.ContainsKey(item.Key)) + _builder.Parameters.Add(item.Key, item.Value); + + return query.CommandText(); + } + } + + private readonly DynamicTypeMap _mapper; + private readonly List _typedJoins = new List(); + + public DynamicTypedSelectQueryBuilder(DynamicDatabase db) + : base(db) + { + _mapper = DynamicMapperCache.GetMapper() + ?? throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", typeof(T).FullName)); + } + + public IDynamicTypedSelectQueryBuilder Where(Expression> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + string condition = ParseTypedCondition(predicate.Body); + + if (string.IsNullOrEmpty(WhereCondition)) + WhereCondition = condition; + else + WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition); + + return this; + } + + public IDynamicTypedSelectQueryBuilder Join(Expression> on, string alias = null, DynamicJoinType joinType = DynamicJoinType.Inner, bool noLock = false) + { + return Join(on, alias, GetJoinKeyword(joinType), noLock); + } + + public IDynamicTypedSelectQueryBuilder Join(Expression> on, string alias, string joinType, bool noLock = false) + { + if (string.IsNullOrEmpty(joinType)) + throw new ArgumentNullException("joinType"); + + DynamicTypeMap rightMapper = DynamicMapperCache.GetMapper(typeof(TRight)); + if (rightMapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", typeof(TRight).FullName)); + + string rightTable = rightMapper.Table == null || string.IsNullOrEmpty(rightMapper.Table.Name) + ? typeof(TRight).Name + : rightMapper.Table.Name; + string rightOwner = rightMapper.Table == null ? null : rightMapper.Table.Owner; + string rightAlias = string.IsNullOrEmpty(alias) ? "t" + (Tables.Count + 1).ToString() : alias; + + string leftPrefix = GetRootAliasOrTableName(); + if (string.IsNullOrEmpty(leftPrefix)) + throw new InvalidOperationException("Join requires source table to be present."); + + string condition = null; + if (on != null) + condition = ParseTypedJoinCondition(on.Body, leftPrefix, rightAlias, _mapper, rightMapper, on.Parameters[0], on.Parameters[1]); + + string ownerPrefix = string.IsNullOrEmpty(rightOwner) ? string.Empty : Database.DecorateName(rightOwner) + "."; + string rightTableExpr = ownerPrefix + Database.DecorateName(rightTable); + string joinExpr = string.Format("{0} {1} AS {2}", + joinType.Trim(), + rightTableExpr, + rightAlias); + + if (SupportNoLock && noLock) + joinExpr += " WITH(NOLOCK)"; + + if (!string.IsNullOrEmpty(condition)) + joinExpr += string.Format(" ON {0}", condition); + + RegisterTypedJoin(typeof(TRight), rightAlias); + AppendJoinClause(joinExpr); + return this; + } + + public IDynamicTypedSelectQueryBuilder Join(Func, TypedJoinBuilder> specification) + { + if (specification == null) + throw new ArgumentNullException("specification"); + + TypedJoinBuilder spec = specification(new TypedJoinBuilder()); + if (spec == null) + throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + if (spec.OnPredicate != null) + return Join(spec.OnPredicate, spec.Alias, spec.CustomJoinType ?? GetJoinKeyword(spec.JoinType), spec.UseNoLock); + + DynamicTypeMap rightMapper = DynamicMapperCache.GetMapper(typeof(TRight)); + if (rightMapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", typeof(TRight).FullName)); + + string rightTable = rightMapper.Table == null || string.IsNullOrEmpty(rightMapper.Table.Name) + ? typeof(TRight).Name + : rightMapper.Table.Name; + string rightOwner = rightMapper.Table == null ? null : rightMapper.Table.Owner; + string rightAlias = string.IsNullOrEmpty(spec.Alias) ? "t" + (Tables.Count + 1).ToString() : spec.Alias; + + string ownerPrefix = string.IsNullOrEmpty(rightOwner) ? string.Empty : Database.DecorateName(rightOwner) + "."; + string rightTableExpr = ownerPrefix + Database.DecorateName(rightTable); + string joinExpr = string.Format("{0} {1} AS {2}", + (spec.CustomJoinType ?? GetJoinKeyword(spec.JoinType)).Trim(), + rightTableExpr, + rightAlias); + + if (SupportNoLock && spec.UseNoLock) + joinExpr += " WITH(NOLOCK)"; + + if (spec.OnSqlPredicate != null) + { + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + joinExpr += string.Format(" ON {0}", spec.OnSqlPredicate(new TypedTableContext(GetRootAliasOrTableName()), new TypedTableContext(rightAlias)).Render(context)); + } + else if (!string.IsNullOrEmpty(spec.OnRawCondition)) + joinExpr += string.Format(" ON {0}", spec.OnRawCondition); + + RegisterTypedJoin(typeof(TRight), rightAlias); + AppendJoinClause(joinExpr); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Join(params Func[] func) + { + base.Join(func); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Where(DynamicColumn column) + { + base.Where(column); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value) + { + base.Where(column, op, value); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Where(string column, object value) + { + base.Where(column, value); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Where(object conditions, bool schema = false) + { + base.Where(conditions, schema); + return this; + } + + public IDynamicTypedSelectQueryBuilder Select(Expression> selector, params Expression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSelector(selector); + + if (selectors != null) + foreach (var s in selectors) + { + if (s == null) + throw new ArgumentNullException("selectors", "Array of selectors cannot contain null."); + + AddSelectSelector(s); + } + + return this; + } + + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedSqlSelectable> selector, params Func, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector); + if (selectors != null) + foreach (Func, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item); + + return this; + } + + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext(0))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext(0))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> item in selectors) + AddSelectSqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder GroupBy(Expression> selector, params Expression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySelector(selector); + + if (selectors != null) + foreach (var s in selectors) + { + if (s == null) + throw new ArgumentNullException("selectors", "Array of selectors cannot contain null."); + + AddGroupBySelector(s); + } + + return this; + } + + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedSqlExpression> selector, params Func, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector); + if (selectors != null) + foreach (Func, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item); + + return this; + } + + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext(0))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext(0))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> item in selectors) + AddGroupBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder OrderBy(Expression> selector, params Expression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySelector(selector); + + if (selectors != null) + foreach (var s in selectors) + { + if (s == null) + throw new ArgumentNullException("selectors", "Array of selectors cannot contain null."); + + AddOrderBySelector(s); + } + + return this; + } + + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedSqlOrderExpression> selector, params Func, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector); + if (selectors != null) + foreach (Func, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item); + + return this; + } + + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext(0))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext(0))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))); + + return this; + } + + public IDynamicTypedSelectQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + if (selectors != null) + foreach (Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> item in selectors) + AddOrderBySqlSelector(item(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))); + + return this; + } + + public new IDynamicTypedSelectQueryBuilder Top(int? top) + { + base.Top(top); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Limit(int? limit) + { + base.Limit(limit); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Offset(int? offset) + { + base.Offset(offset); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Distinct(bool distinct = true) + { + base.Distinct(distinct); + return this; + } + + public IDynamicTypedSelectQueryBuilder Having(Expression> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + string condition = ParseTypedCondition(predicate.Body); + + if (string.IsNullOrEmpty(HavingCondition)) + HavingCondition = condition; + else + HavingCondition = string.Format("{0} AND {1}", HavingCondition, condition); + + return this; + } + + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate), false); + + return this; + } + + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0))), false); + return this; + } + + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))), false); + return this; + } + + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))), false); + return this; + } + + public IDynamicTypedSelectQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))), false); + return this; + } + + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate), true); + + return this; + } + + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0))), true); + return this; + } + + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1))), true); + return this; + } + + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2))), true); + return this; + } + + public IDynamicTypedSelectQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + AppendSqlCondition(RenderSqlPredicate(predicate(GetRootContext(), GetJoinedContext(0), GetJoinedContext(1), GetJoinedContext(2), GetJoinedContext(3))), true); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Having(DynamicColumn column) + { + base.Having(column); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Having(string column, DynamicColumn.CompareOperator op, object value) + { + base.Having(column, op, value); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Having(string column, object value) + { + base.Having(column, value); + return this; + } + + public new IDynamicTypedSelectQueryBuilder Having(object conditions, bool schema = false) + { + base.Having(conditions, schema); + return this; + } + + private void AddSelectSelector(Expression> selector) + { + var body = UnwrapConvert(selector.Body); + + if (body is NewExpression ne) + { + foreach (var argument in ne.Arguments) + { + var parsed = ParseTypedSelectExpression(argument); + ((IDynamicSelectQueryBuilder)this).Select(x => parsed); + } + } + else + { + var parsed = ParseTypedSelectExpression(body); + ((IDynamicSelectQueryBuilder)this).Select(x => parsed); + } + } + + private void AddSelectSqlSelector(Func, TypedSqlSelectable> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddSelectSqlSelector(selector(GetRootContext())); + } + + internal void AddSelectSqlSelector(TypedSqlSelectable item) + { + if (item == null) + throw new ArgumentNullException("item"); + + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + string rendered = item.Render(context); + _select = string.IsNullOrEmpty(_select) ? rendered : string.Format("{0}, {1}", _select, rendered); + } + + private void AddGroupBySelector(Expression> selector) + { + var body = UnwrapConvert(selector.Body); + + if (body is NewExpression ne) + { + foreach (var argument in ne.Arguments) + { + var parsed = ParseTypedMemberAccess(argument); + ((IDynamicSelectQueryBuilder)this).GroupBy(x => parsed); + } + } + else + { + var parsed = ParseTypedMemberAccess(body); + ((IDynamicSelectQueryBuilder)this).GroupBy(x => parsed); + } + } + + private void AddGroupBySqlSelector(Func, TypedSqlExpression> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddGroupBySqlSelector(selector(GetRootContext())); + } + + internal void AddGroupBySqlSelector(TypedSqlExpression item) + { + if (item == null) + throw new ArgumentNullException("item"); + + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + string rendered = item.Render(context); + _groupby = string.IsNullOrEmpty(_groupby) ? rendered : string.Format("{0}, {1}", _groupby, rendered); + } + + private void AddOrderBySelector(Expression> selector) + { + var body = UnwrapConvert(selector.Body); + bool ascending = true; + + if (body is MethodCallExpression call && IsAscOrDesc(call)) + { + ascending = call.Method.Name.ToUpper() != "DESC"; + body = UnwrapConvert(call.Object ?? call.Arguments.FirstOrDefault()); + } + + string main = ParseTypedMemberAccess(body); + string parsed = string.Format("{0} {1}", main, ascending ? "ASC" : "DESC"); + ((IDynamicSelectQueryBuilder)this).OrderBy(x => parsed); + } + + private void AddOrderBySqlSelector(Func, TypedSqlOrderExpression> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + AddOrderBySqlSelector(selector(GetRootContext())); + } + + internal void AddOrderBySqlSelector(TypedSqlOrderExpression item) + { + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + string rendered = item.Render(context); + _orderby = string.IsNullOrEmpty(_orderby) ? rendered : string.Format("{0}, {1}", _orderby, rendered); + } + + private string RenderSqlPredicate(Func, TypedSqlPredicate> predicate) + { + return RenderSqlPredicate(predicate(GetRootContext())); + } + + private string RenderSqlPredicate(TypedSqlPredicate predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + TypedSqlRenderContext context = new TypedSqlRenderContext(this); + return predicate.Render(context); + } + + internal string RenderScopeSqlPredicate(TypedSqlPredicate predicate) + { + return RenderSqlPredicate(predicate); + } + + private string ParseTypedCondition(Expression expression) + { + expression = UnwrapConvert(expression); + + if (expression is BinaryExpression binary) + { + switch (binary.NodeType) + { + case ExpressionType.AndAlso: + case ExpressionType.And: + return string.Format("({0} AND {1})", ParseTypedCondition(binary.Left), ParseTypedCondition(binary.Right)); + case ExpressionType.OrElse: + case ExpressionType.Or: + return string.Format("({0} OR {1})", ParseTypedCondition(binary.Left), ParseTypedCondition(binary.Right)); + case ExpressionType.Equal: + case ExpressionType.NotEqual: + case ExpressionType.GreaterThan: + case ExpressionType.GreaterThanOrEqual: + case ExpressionType.LessThan: + case ExpressionType.LessThanOrEqual: + { + DynamicSchemaColumn? columnSchema = null; + string left = ParseTypedValue(binary.Left, ref columnSchema); + string right = ParseTypedValue(binary.Right, ref columnSchema); + string op = GetBinaryOperator(binary.NodeType, IsNullConstant(binary.Right)); + return string.Format("({0} {1} {2})", left, op, right); + } + } + } + + if (expression is UnaryExpression unary && unary.NodeType == ExpressionType.Not) + return string.Format("(NOT {0})", ParseTypedCondition(unary.Operand)); + + if (expression is MethodCallExpression call && IsEnumerableContains(call)) + { + DynamicSchemaColumn? col = null; + return ParseTypedContains(call, ref col); + } + + throw new NotSupportedException(string.Format("Typed fluent where expression is not supported: {0}", expression)); + } + + private string ParseTypedValue(Expression expression, ref DynamicSchemaColumn? columnSchema) + { + expression = UnwrapConvert(expression); + + if (IsMemberFromTypedParameter(expression)) + { + string col = ParseTypedMemberAccess(expression); + columnSchema = GetColumnFromSchema(col); + return col; + } + + if (expression is MethodCallExpression call && IsEnumerableContains(call)) + return ParseTypedContains(call, ref columnSchema); + + object value = EvaluateExpression(expression); + return ParseConstant(value, Parameters, columnSchema); + } + + private string ParseTypedContains(MethodCallExpression call, ref DynamicSchemaColumn? columnSchema) + { + // Supports: list.Contains(x.Property) and Enumerable.Contains(list, x.Property) + Expression collection; + Expression candidate; + + if (call.Object != null) + { + collection = call.Object; + candidate = call.Arguments[0]; + } + else + { + collection = call.Arguments[0]; + candidate = call.Arguments[1]; + } + + candidate = UnwrapConvert(candidate); + if (!IsMemberFromTypedParameter(candidate)) + throw new NotSupportedException(string.Format("Typed Contains() must target a mapped member: {0}", call)); + + string left = ParseTypedMemberAccess(candidate); + columnSchema = GetColumnFromSchema(left); + + var values = EvaluateExpression(collection) as IEnumerable; + if (values == null && collection is MethodCallExpression implicitCall && + string.Equals(implicitCall.Method.Name, "op_Implicit", StringComparison.Ordinal) && + implicitCall.Arguments.Count > 0) + { + values = EvaluateExpression(implicitCall.Arguments[0]) as IEnumerable; + } + + if (values == null) + throw new NotSupportedException(string.Format("Typed Contains() source is not enumerable: {0}", call)); + + var inList = new List(); + foreach (var item in values.Cast()) + inList.Add(ParseConstant(item, Parameters, columnSchema)); + + if (!inList.Any()) + return "(1 = 0)"; + + return string.Format("({0} IN({1}))", left, string.Join(", ", inList)); + } + + private string ParseTypedMemberAccess(Expression expression) + { + expression = UnwrapConvert(expression); + if (!(expression is MemberExpression member) || !IsMemberFromTypedParameter(member)) + throw new NotSupportedException(string.Format("Typed fluent member access is not supported: {0}", expression)); + + string mappedColumn = null; + var property = member.Member as PropertyInfo; + if (property != null) + { + var attrs = property.GetCustomAttributes(typeof(ColumnAttribute), true); + var colAttr = attrs == null ? null : attrs.Cast().FirstOrDefault(); + if (colAttr != null && !string.IsNullOrEmpty(colAttr.Name)) + mappedColumn = colAttr.Name; + } + + if (string.IsNullOrEmpty(mappedColumn)) + { + mappedColumn = _mapper.PropertyMap.TryGetValue(member.Member.Name) + ?? _mapper.PropertyMap + .Where(x => string.Equals(x.Key, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Value) + .FirstOrDefault() + ?? _mapper.ColumnsMap + .Where(x => string.Equals(x.Value.Name, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Key) + .FirstOrDefault() + ?? member.Member.Name; + } + string tablePrefix = GetRootAliasOrTableName(); + + string qualified = string.IsNullOrEmpty(tablePrefix) + ? mappedColumn + : string.Format("{0}.{1}", tablePrefix, mappedColumn); + + return FixObjectName(qualified); + } + + private string ParseTypedSelectExpression(Expression expression) + { + expression = UnwrapConvert(expression); + + if (expression is MethodCallExpression call && IsAsCall(call)) + { + string left = ParseTypedMemberAccess(call.Object ?? call.Arguments.FirstOrDefault()); + var alias = EvaluateExpression(call.Arguments.Last()) == null ? null : EvaluateExpression(call.Arguments.Last()).ToString(); + alias = alias.Validated("Alias"); + + return string.Format("{0} AS {1}", left, Database.DecorateName(alias)); + } + + return ParseTypedMemberAccess(expression); + } + + private string GetRootAliasOrTableName() + { + var mappedTable = _mapper.Table == null || string.IsNullOrEmpty(_mapper.Table.Name) + ? _mapper.Type.Name + : _mapper.Table.Name; + + var table = Tables.FirstOrDefault(t => t.Name == mappedTable || t.Name == Database.StripName(mappedTable)); + if (table == null) + table = Tables.FirstOrDefault(); + + if (table == null) + return null; + + return string.IsNullOrEmpty(table.Alias) ? table.Name : table.Alias; + } + + private TypedTableContext GetRootContext() + { + return new TypedTableContext(GetRootAliasOrTableName()); + } + + private TypedTableContext GetJoinedContext(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(join.Alias); + } + + private void RegisterTypedJoin(Type modelType, string alias) + { + _typedJoins.Add(new TypedJoinInfo + { + ModelType = modelType, + Alias = alias + }); + } + + internal 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) + { + var member = expression as MemberExpression; + if (member == null) + return false; + + var parameter = member.Expression as ParameterExpression; + return parameter != null && parameter.Type == typeof(T); + } + + private static string GetJoinKeyword(DynamicJoinType joinType) + { + switch (joinType) + { + case DynamicJoinType.Join: + return "JOIN"; + case DynamicJoinType.Left: + return "LEFT JOIN"; + case DynamicJoinType.Right: + return "RIGHT JOIN"; + case DynamicJoinType.Full: + return "FULL JOIN"; + case DynamicJoinType.LeftOuter: + return "LEFT OUTER JOIN"; + case DynamicJoinType.RightOuter: + return "RIGHT OUTER JOIN"; + case DynamicJoinType.FullOuter: + return "FULL OUTER JOIN"; + default: + return "INNER JOIN"; + } + } + + private void AppendJoinClause(string joinClause) + { + _join = string.IsNullOrEmpty(_join) + ? joinClause + : string.Format("{0} {1}", _join, joinClause); + } + + private string ParseTypedJoinCondition(Expression expression, string leftPrefix, string rightPrefix, DynamicTypeMap leftMapper, DynamicTypeMap rightMapper, ParameterExpression leftParameter, ParameterExpression rightParameter) + { + expression = UnwrapConvert(expression); + + if (expression is BinaryExpression binary) + { + switch (binary.NodeType) + { + case ExpressionType.AndAlso: + case ExpressionType.And: + return string.Format("({0} AND {1})", + ParseTypedJoinCondition(binary.Left, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter), + ParseTypedJoinCondition(binary.Right, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter)); + case ExpressionType.OrElse: + case ExpressionType.Or: + return string.Format("({0} OR {1})", + ParseTypedJoinCondition(binary.Left, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter), + ParseTypedJoinCondition(binary.Right, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter)); + case ExpressionType.Equal: + case ExpressionType.NotEqual: + case ExpressionType.GreaterThan: + case ExpressionType.GreaterThanOrEqual: + case ExpressionType.LessThan: + case ExpressionType.LessThanOrEqual: + { + string left = ParseTypedJoinValue(binary.Left, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter); + string right = ParseTypedJoinValue(binary.Right, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter); + string op = GetBinaryOperator(binary.NodeType, IsNullConstant(binary.Right)); + return string.Format("({0} {1} {2})", left, op, right); + } + } + } + + if (expression is UnaryExpression unary && unary.NodeType == ExpressionType.Not) + return string.Format("(NOT {0})", ParseTypedJoinCondition(unary.Operand, leftPrefix, rightPrefix, leftMapper, rightMapper, leftParameter, rightParameter)); + + throw new NotSupportedException(string.Format("Typed join condition is not supported: {0}", expression)); + } + + private string ParseTypedJoinValue(Expression expression, string leftPrefix, string rightPrefix, DynamicTypeMap leftMapper, DynamicTypeMap rightMapper, ParameterExpression leftParameter, ParameterExpression rightParameter) + { + expression = UnwrapConvert(expression); + MemberExpression member = expression as MemberExpression; + if (member != null && member.Expression is ParameterExpression parameter) + { + if (parameter == leftParameter) + return ParseTypedJoinMemberByMapper(member, leftPrefix, leftMapper); + if (parameter == rightParameter) + return ParseTypedJoinMemberByMapper(member, rightPrefix, rightMapper); + } + + DynamicSchemaColumn? col = null; + object value = EvaluateExpression(expression); + return ParseConstant(value, Parameters, col); + } + + private string ParseTypedJoinMember(Expression expression, string tablePrefix, DynamicTypeMap mapper) + { + expression = UnwrapConvert(expression); + MemberExpression member = expression as MemberExpression; + if (member == null || !(member.Expression is ParameterExpression) || ((ParameterExpression)member.Expression).Type != typeof(TModel)) + throw new NotSupportedException(string.Format("Typed join member access is not supported: {0}", expression)); + + string mappedColumn = null; + PropertyInfo property = member.Member as PropertyInfo; + if (property != null) + { + var attrs = property.GetCustomAttributes(typeof(ColumnAttribute), true); + ColumnAttribute colAttr = attrs == null ? null : attrs.Cast().FirstOrDefault(); + if (colAttr != null && !string.IsNullOrEmpty(colAttr.Name)) + mappedColumn = colAttr.Name; + } + + if (string.IsNullOrEmpty(mappedColumn)) + mappedColumn = mapper.PropertyMap.TryGetValue(member.Member.Name) + ?? mapper.PropertyMap + .Where(x => string.Equals(x.Key, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Value) + .FirstOrDefault() + ?? member.Member.Name; + + return string.Format("{0}.{1}", tablePrefix, Database.DecorateName(mappedColumn)); + } + + private string ParseTypedJoinMemberByMapper(MemberExpression member, string tablePrefix, DynamicTypeMap mapper) + { + string mappedColumn = null; + PropertyInfo property = member.Member as PropertyInfo; + if (property != null) + { + var attrs = property.GetCustomAttributes(typeof(ColumnAttribute), true); + ColumnAttribute colAttr = attrs == null ? null : attrs.Cast().FirstOrDefault(); + if (colAttr != null && !string.IsNullOrEmpty(colAttr.Name)) + mappedColumn = colAttr.Name; + } + + if (string.IsNullOrEmpty(mappedColumn)) + mappedColumn = mapper.PropertyMap.TryGetValue(member.Member.Name) + ?? mapper.PropertyMap + .Where(x => string.Equals(x.Key, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Value) + .FirstOrDefault() + ?? member.Member.Name; + + return string.Format("{0}.{1}", tablePrefix, Database.DecorateName(mappedColumn)); + } + + private static Expression UnwrapConvert(Expression expression) + { + while (expression is UnaryExpression unary && + (unary.NodeType == ExpressionType.Convert || unary.NodeType == ExpressionType.ConvertChecked)) + expression = unary.Operand; + + return expression; + } + + private static bool IsNullConstant(Expression expression) + { + expression = UnwrapConvert(expression); + return expression is ConstantExpression constant && constant.Value == null; + } + + private static string GetBinaryOperator(ExpressionType type, bool rightIsNull) + { + switch (type) + { + case ExpressionType.Equal: return rightIsNull ? "IS" : "="; + case ExpressionType.NotEqual: return rightIsNull ? "IS NOT" : "<>"; + case ExpressionType.GreaterThan: return ">"; + case ExpressionType.GreaterThanOrEqual: return ">="; + case ExpressionType.LessThan: return "<"; + case ExpressionType.LessThanOrEqual: return "<="; + default: throw new NotSupportedException(string.Format("Expression operation is not supported: {0}", type)); + } + } + + private static bool IsEnumerableContains(MethodCallExpression call) + { + if (!string.Equals(call.Method.Name, "Contains", StringComparison.Ordinal)) + return false; + + if (call.Object != null && call.Arguments.Count == 1) + return true; + + return call.Object == null && call.Arguments.Count == 2; + } + + private static bool IsAsCall(MethodCallExpression call) + { + return string.Equals(call.Method.Name, "As", StringComparison.Ordinal) + && (call.Arguments.Count == 1 || call.Arguments.Count == 2); + } + + private static bool IsAscOrDesc(MethodCallExpression call) + { + string name = call.Method.Name.ToUpper(); + return (name == "ASC" || name == "DESC") + && (call.Arguments.Count == 0 || call.Arguments.Count == 1); + } + + private static object EvaluateExpression(Expression expression) + { + var objectMember = Expression.Convert(expression, typeof(object)); + var getter = Expression.Lambda>(objectMember).Compile(); + return getter(); + } + } +} diff --git a/DynamORM/Builders/Implementation/DynamicTypedSelectScopeQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicTypedSelectScopeQueryBuilder.cs new file mode 100644 index 0000000..cf8f8ae --- /dev/null +++ b/DynamORM/Builders/Implementation/DynamicTypedSelectScopeQueryBuilder.cs @@ -0,0 +1,1360 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using DynamORM.Helpers; +using DynamORM.TypedSql; + +namespace DynamORM.Builders.Implementation +{ + internal abstract class DynamicTypedSelectScopeQueryBuilderBase : IDynamicSelectQueryBuilder + { + protected readonly DynamicTypedSelectQueryBuilder Builder; + protected DynamicTypedSelectScopeQueryBuilderBase(DynamicTypedSelectQueryBuilder builder) { Builder = builder; } + public DynamicDatabase Database { get { return Builder.Database; } } + public IList Tables { get { return Builder.Tables; } } + public IDictionary Parameters { get { return Builder.Parameters; } } + public bool VirtualMode { get { return Builder.VirtualMode; } set { Builder.VirtualMode = value; } } + public bool SupportSchema { get { return Builder.SupportSchema; } } + public List> OnCreateTemporaryParameter { get { return Builder.OnCreateTemporaryParameter; } set { Builder.OnCreateTemporaryParameter = value; } } + public List> OnCreateParameter { get { return Builder.OnCreateParameter; } set { Builder.OnCreateParameter = value; } } + public bool IsDisposed { get { return Builder.IsDisposed; } } + public void Dispose() { Builder.Dispose(); } + public IDbCommand FillCommand(IDbCommand command) { return Builder.FillCommand(command); } + public string CommandText() { return Builder.CommandText(); } + public IEnumerable Execute() { return Builder.Execute(); } + public IEnumerable Execute() where T : class { return Builder.Execute(); } + public void ExecuteDataReader(Action reader) { Builder.ExecuteDataReader(reader); } + public object Scalar() { return Builder.Scalar(); } +#if !DYNAMORM_OMMIT_GENERICEXECUTION && !DYNAMORM_OMMIT_TRYPARSE + public TResult ScalarAs(TResult defaultValue = default(TResult)) { return Builder.ScalarAs(defaultValue); } +#endif + public IDynamicSelectQueryBuilder From(Func fn, params Func[] func) { Builder.From(fn, func); return this; } + public IDynamicSelectQueryBuilder Join(params Func[] func) { Builder.Join(func); return this; } + public IDynamicSelectQueryBuilder Where(Func func) { Builder.Where(func); return this; } + public IDynamicSelectQueryBuilder Where(DynamicColumn column) { Builder.Where(column); return this; } + public IDynamicSelectQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value) { Builder.Where(column, op, value); return this; } + public IDynamicSelectQueryBuilder Where(string column, object value) { Builder.Where(column, value); return this; } + public IDynamicSelectQueryBuilder Where(object conditions, bool schema = false) { Builder.Where(conditions, schema); return this; } + public IDynamicSelectQueryBuilder Select(Func fn, params Func[] func) { Builder.Select(fn, func); return this; } + public IDynamicSelectQueryBuilder SelectColumn(params DynamicColumn[] columns) { Builder.SelectColumn(columns); return this; } + public IDynamicSelectQueryBuilder SelectColumn(params string[] columns) { Builder.SelectColumn(columns); return this; } + public IDynamicSelectQueryBuilder GroupBy(Func fn, params Func[] func) { Builder.GroupBy(fn, func); return this; } + public IDynamicSelectQueryBuilder GroupByColumn(params DynamicColumn[] columns) { Builder.GroupByColumn(columns); return this; } + public IDynamicSelectQueryBuilder GroupByColumn(params string[] columns) { Builder.GroupByColumn(columns); return this; } + public IDynamicSelectQueryBuilder Having(Func func) { Builder.Having(func); return this; } + public IDynamicSelectQueryBuilder Having(DynamicColumn column) { Builder.Having(column); return this; } + public IDynamicSelectQueryBuilder Having(string column, DynamicColumn.CompareOperator op, object value) { Builder.Having(column, op, value); return this; } + public IDynamicSelectQueryBuilder Having(string column, object value) { Builder.Having(column, value); return this; } + public IDynamicSelectQueryBuilder Having(object conditions, bool schema = false) { Builder.Having(conditions, schema); return this; } + public IDynamicSelectQueryBuilder OrderBy(Func fn, params Func[] func) { Builder.OrderBy(fn, func); return this; } + public IDynamicSelectQueryBuilder OrderByColumn(params DynamicColumn[] columns) { Builder.OrderByColumn(columns); return this; } + public IDynamicSelectQueryBuilder OrderByColumn(params string[] columns) { Builder.OrderByColumn(columns); return this; } + public IDynamicSelectQueryBuilder Top(int? top) { Builder.Top(top); return this; } + public IDynamicSelectQueryBuilder Limit(int? limit) { Builder.Limit(limit); return this; } + public IDynamicSelectQueryBuilder Offset(int? offset) { Builder.Offset(offset); return this; } + public IDynamicSelectQueryBuilder Distinct(bool distinct = true) { Builder.Distinct(distinct); return this; } + protected TypedJoinBuilder ApplyJoinSpec(TypedJoinBuilder builder, string alias, string customJoinType, DynamicJoinType joinType, bool noLock, string condition) + { + if (!string.IsNullOrEmpty(alias)) builder.As(alias); + if (!string.IsNullOrEmpty(customJoinType)) builder.Type(customJoinType); + else + { + switch (joinType) + { + case DynamicJoinType.Join: builder.Join(); break; + case DynamicJoinType.Left: builder.Left(); break; + case DynamicJoinType.Right: builder.Right(); break; + case DynamicJoinType.Full: builder.Full(); break; + case DynamicJoinType.LeftOuter: builder.LeftOuter(); break; + case DynamicJoinType.RightOuter: builder.RightOuter(); break; + case DynamicJoinType.FullOuter: builder.FullOuter(); break; + default: builder.Inner(); break; + } + } + if (noLock) builder.NoLock(); + if (!string.IsNullOrEmpty(condition)) builder.OnRaw(condition); + return builder; + } + protected void AddSelect(TypedSqlSelectable item) { Builder.AddSelectSqlSelector(item); } + protected void AddGroupBy(TypedSqlExpression item) { Builder.AddGroupBySqlSelector(item); } + protected void AddOrderBy(TypedSqlOrderExpression item) { Builder.AddOrderBySqlSelector(item); } + protected void AddWhere(TypedSqlPredicate predicate) { Builder.AppendSqlCondition(Builder.RenderScopeSqlPredicate(predicate), false); } + protected void AddHaving(TypedSqlPredicate predicate) { Builder.AppendSqlCondition(Builder.RenderScopeSqlPredicate(predicate), true); } + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1) : base(builder) + { + _alias1 = alias1; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t2" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedSqlSelectable> selector, params Func, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedSqlExpression> selector, params Func, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedSqlOrderExpression> selector, params Func, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t3" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t4" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t5" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t6" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t7" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t8" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t9" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t10" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t11" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t12" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t13" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, _alias12, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + private readonly string _alias13; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12, string alias13) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + _alias13 = alias13; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t14" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, _alias12, _alias13, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + private readonly string _alias13; + private readonly string _alias14; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12, string alias13, string alias14) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + _alias13 = alias13; + _alias14 = alias14; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t15" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, _alias12, _alias13, _alias14, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + private readonly string _alias13; + private readonly string _alias14; + private readonly string _alias15; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12, string alias13, string alias14, string alias15) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + _alias13 = alias13; + _alias14 = alias14; + _alias15 = alias15; + } + + public IDynamicTypedSelectScopeQueryBuilder Join(Func, TypedScopeJoinBuilder> specification) + { + if (specification == null) throw new ArgumentNullException("specification"); + TypedScopeJoinBuilder spec = specification(new TypedScopeJoinBuilder()); + if (spec == null) throw new ArgumentException("Join specification cannot resolve to null.", "specification"); + string alias = string.IsNullOrEmpty(spec.Alias) ? "t16" : spec.Alias; + string condition = spec.OnSqlPredicate == null ? spec.OnRawCondition : Builder.RenderScopeSqlPredicate(spec.OnSqlPredicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(alias))); + Builder.Join(j => ApplyJoinSpec(j, alias, spec.CustomJoinType, spec.JoinType, spec.UseNoLock, condition)); + return new DynamicTypedSelectScopeQueryBuilder(Builder, _alias1, _alias2, _alias3, _alias4, _alias5, _alias6, _alias7, _alias8, _alias9, _alias10, _alias11, _alias12, _alias13, _alias14, _alias15, alias); + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15))); + return this; + } + + } + + internal sealed class DynamicTypedSelectScopeQueryBuilder : DynamicTypedSelectScopeQueryBuilderBase, IDynamicTypedSelectScopeQueryBuilder + { + private readonly string _alias1; + private readonly string _alias2; + private readonly string _alias3; + private readonly string _alias4; + private readonly string _alias5; + private readonly string _alias6; + private readonly string _alias7; + private readonly string _alias8; + private readonly string _alias9; + private readonly string _alias10; + private readonly string _alias11; + private readonly string _alias12; + private readonly string _alias13; + private readonly string _alias14; + private readonly string _alias15; + private readonly string _alias16; + internal DynamicTypedSelectScopeQueryBuilder(DynamicTypedSelectQueryBuilder builder, string alias1, string alias2, string alias3, string alias4, string alias5, string alias6, string alias7, string alias8, string alias9, string alias10, string alias11, string alias12, string alias13, string alias14, string alias15, string alias16) : base(builder) + { + _alias1 = alias1; + _alias2 = alias2; + _alias3 = alias3; + _alias4 = alias4; + _alias5 = alias5; + _alias6 = alias6; + _alias7 = alias7; + _alias8 = alias8; + _alias9 = alias9; + _alias10 = alias10; + _alias11 = alias11; + _alias12 = alias12; + _alias13 = alias13; + _alias14 = alias14; + _alias15 = alias15; + _alias16 = alias16; + } + + public IDynamicTypedSelectScopeQueryBuilder SelectSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlSelectable>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddSelect(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + if (selectors != null) + foreach (var item in selectors) + AddSelect(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder WhereSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddWhere(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder HavingSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + AddHaving(predicate(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder GroupBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddGroupBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + if (selectors != null) + foreach (var item in selectors) + AddGroupBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + + public IDynamicTypedSelectScopeQueryBuilder OrderBySql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression> selector, params Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlOrderExpression>[] selectors) + { + if (selector == null) throw new ArgumentNullException("selector"); + AddOrderBy(selector(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + if (selectors != null) + foreach (var item in selectors) + AddOrderBy(item(new TypedTableContext(_alias1), new TypedTableContext(_alias2), new TypedTableContext(_alias3), new TypedTableContext(_alias4), new TypedTableContext(_alias5), new TypedTableContext(_alias6), new TypedTableContext(_alias7), new TypedTableContext(_alias8), new TypedTableContext(_alias9), new TypedTableContext(_alias10), new TypedTableContext(_alias11), new TypedTableContext(_alias12), new TypedTableContext(_alias13), new TypedTableContext(_alias14), new TypedTableContext(_alias15), new TypedTableContext(_alias16))); + return this; + } + + } + +} \ No newline at end of file diff --git a/DynamORM/Builders/Implementation/DynamicTypedUpdateQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicTypedUpdateQueryBuilder.cs new file mode 100644 index 0000000..d636544 --- /dev/null +++ b/DynamORM/Builders/Implementation/DynamicTypedUpdateQueryBuilder.cs @@ -0,0 +1,170 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using DynamORM.Builders.Extensions; +using DynamORM.Helpers.Dynamics; +using DynamORM.TypedSql; + +namespace DynamORM.Builders.Implementation +{ + /// Typed wrapper over with property-to-column translation. + /// Mapped entity type. + internal class DynamicTypedUpdateQueryBuilder : DynamicUpdateQueryBuilder, IDynamicTypedUpdateQueryBuilder + { + internal DynamicTypedUpdateQueryBuilder(DynamicDatabase db) + : this(db, false) + { + } + + internal DynamicTypedUpdateQueryBuilder(DynamicDatabase db, bool mapType) + : base(db) + { + if (mapType) + this.Table(typeof(T)); + else + this.Table(typeof(T).Name); + } + + public IDynamicTypedUpdateQueryBuilder Where(Expression> predicate) + { + TypedModifyHelper.ApplyWhere((c, o, v) => base.Where(c, o, v), predicate); + return this; + } + + public IDynamicTypedUpdateQueryBuilder Set(Expression> selector, object value) + { + base.Values(TypedModifyHelper.GetMappedColumn(selector), value); + return this; + } + + public IDynamicTypedUpdateQueryBuilder Values(T value) + { + base.Values(value); + return this; + } + + public IDynamicTypedUpdateQueryBuilder WhereSql(Func, TypedSqlPredicate> predicate) + { + string condition = TypedModifyHelper.RenderPredicate(predicate, null, RenderValue, Database.DecorateName, RenderSubQuery); + if (string.IsNullOrEmpty(WhereCondition)) + WhereCondition = condition; + else + WhereCondition = string.Format("{0} AND {1}", WhereCondition, condition); + + return this; + } + + public IDynamicTypedUpdateQueryBuilder SetSql(Expression> selector, Func, TypedSqlExpression> valueFactory) + { + string column = FixObjectName(TypedModifyHelper.GetMappedColumn(selector), onlyColumn: true); + string value = TypedModifyHelper.RenderExpression(valueFactory, null, RenderValue, Database.DecorateName, RenderSubQuery); + string assignment = string.Format("{0} = {1}", column, value); + _columns = _columns == null ? assignment : string.Format("{0}, {1}", _columns, assignment); + return this; + } + + public IDynamicTypedUpdateQueryBuilder SetSql(Func, object> values) + { + if (values == null) + throw new ArgumentNullException("values"); + + object data = values(new TypedTableContext(null)); + foreach (KeyValuePair item in data.ToDictionary()) + { + string column = FixObjectName(TypedModifyHelper.GetMappedColumnByName(typeof(T), item.Key), onlyColumn: true); + string value = (item.Value as TypedSqlExpression) != null + ? TypedModifyHelper.RenderExpression(u => (TypedSqlExpression)item.Value, null, RenderValue, Database.DecorateName, RenderSubQuery) + : RenderValue(item.Value); + + string assignment = string.Format("{0} = {1}", column, value); + _columns = _columns == null ? assignment : string.Format("{0}, {1}", _columns, assignment); + } + + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Update(string column, object value) + { + base.Update(column, value); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Update(object conditions) + { + base.Update(conditions); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Set(params Func[] func) + { + base.Set(func); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Values(string column, object value) + { + base.Values(column, value); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Values(object o) + { + base.Values(o); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Where(Func func) + { + base.Where(func); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Where(DynamicColumn column) + { + base.Where(column); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Where(string column, DynamicColumn.CompareOperator op, object value) + { + base.Where(column, op, value); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Where(string column, object value) + { + base.Where(column, value); + return this; + } + + public new IDynamicTypedUpdateQueryBuilder Where(object conditions, bool schema = false) + { + base.Where(conditions, schema); + return this; + } + + private string RenderValue(object value) + { + if (value == null) + return "NULL"; + + DynamicSchemaColumn? columnSchema = null; + return ParseConstant(value, Parameters, columnSchema); + } + + private string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query) + { + foreach (KeyValuePair item in query.Parameters) + if (!Parameters.ContainsKey(item.Key)) + Parameters.Add(item.Key, item.Value); + + return query.CommandText(); + } + } +} diff --git a/DynamORM/Builders/Implementation/DynamicUpdateQueryBuilder.cs b/DynamORM/Builders/Implementation/DynamicUpdateQueryBuilder.cs index 030382c..f329755 100644 --- a/DynamORM/Builders/Implementation/DynamicUpdateQueryBuilder.cs +++ b/DynamORM/Builders/Implementation/DynamicUpdateQueryBuilder.cs @@ -41,7 +41,7 @@ namespace DynamORM.Builders.Implementation /// Update query builder. internal class DynamicUpdateQueryBuilder : DynamicModifyBuilder, IDynamicUpdateQueryBuilder, DynamicQueryBuilder.IQueryWithWhere { - private string _columns; + protected string _columns; internal DynamicUpdateQueryBuilder(DynamicDatabase db) : base(db) @@ -339,4 +339,4 @@ namespace DynamORM.Builders.Implementation #endregion IExtendedDisposable } -} \ No newline at end of file +} diff --git a/DynamORM/Builders/Implementation/TypedModifyHelper.cs b/DynamORM/Builders/Implementation/TypedModifyHelper.cs new file mode 100644 index 0000000..421ae80 --- /dev/null +++ b/DynamORM/Builders/Implementation/TypedModifyHelper.cs @@ -0,0 +1,200 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using DynamORM.Builders; +using DynamORM.Mapper; +using DynamORM.TypedSql; + +namespace DynamORM.Builders.Implementation +{ + /// Helper methods for typed modify builders. + internal static class TypedModifyHelper + { + private sealed class ModifyRenderContext : ITypedSqlRenderContext + { + private readonly Func, string> _resolveColumn; + private readonly Func _renderValue; + private readonly Func _decorateName; + private readonly Func _renderSubQuery; + + public ModifyRenderContext(Func, string> resolveColumn, Func renderValue, Func decorateName, Func renderSubQuery) + { + _resolveColumn = resolveColumn; + _renderValue = renderValue; + _decorateName = decorateName; + _renderSubQuery = renderSubQuery; + } + + public string ResolveColumn(Type modelType, string memberName, string alias) + { + return _resolveColumn(modelType, memberName, alias, _decorateName); + } + + public string RenderValue(object value) + { + return _renderValue(value); + } + + public string DecorateName(string name) + { + return _decorateName(name); + } + + public string RenderSubQuery(IDynamicSelectQueryBuilder query) + { + return _renderSubQuery(query); + } + } + + public static string GetMappedColumn(Expression> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + return GetMappedColumn(typeof(T), selector.Body); + } + + public static void ApplyWhere(Action addCondition, Expression> predicate) + { + if (addCondition == null) + throw new ArgumentNullException("addCondition"); + if (predicate == null) + throw new ArgumentNullException("predicate"); + + ApplyWhereInternal(typeof(T), addCondition, predicate.Body); + } + + public static string RenderPredicate( + Func, TypedSqlPredicate> predicate, + string alias, + Func renderValue, + Func decorateName, + Func renderSubQuery) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + ModifyRenderContext context = new ModifyRenderContext(ResolveColumn, renderValue, decorateName, renderSubQuery); + return predicate(new TypedTableContext(alias)).Render(context); + } + + public static string RenderExpression( + Func, TypedSqlExpression> expression, + string alias, + Func renderValue, + Func decorateName, + Func renderSubQuery) + { + if (expression == null) + throw new ArgumentNullException("expression"); + + ModifyRenderContext context = new ModifyRenderContext(ResolveColumn, renderValue, decorateName, renderSubQuery); + return expression(new TypedTableContext(alias)).Render(context); + } + + private static void ApplyWhereInternal(Type modelType, Action addCondition, Expression expression) + { + expression = UnwrapConvert(expression); + BinaryExpression be = expression as BinaryExpression; + if (be == null) + throw new NotSupportedException(string.Format("Typed where expression is currently limited to AND-composed binary comparisons: {0}", expression)); + + if (be.NodeType == ExpressionType.AndAlso || be.NodeType == ExpressionType.And) + { + ApplyWhereInternal(modelType, addCondition, be.Left); + ApplyWhereInternal(modelType, addCondition, be.Right); + return; + } + + string col = GetMappedColumn(modelType, be.Left); + object val = EvaluateExpression(be.Right); + + switch (be.NodeType) + { + case ExpressionType.Equal: + addCondition(col, DynamicColumn.CompareOperator.Eq, val); + return; + case ExpressionType.NotEqual: + addCondition(col, DynamicColumn.CompareOperator.Not, val); + return; + case ExpressionType.GreaterThan: + addCondition(col, DynamicColumn.CompareOperator.Gt, val); + return; + case ExpressionType.GreaterThanOrEqual: + addCondition(col, DynamicColumn.CompareOperator.Gte, val); + return; + case ExpressionType.LessThan: + addCondition(col, DynamicColumn.CompareOperator.Lt, val); + return; + case ExpressionType.LessThanOrEqual: + addCondition(col, DynamicColumn.CompareOperator.Lte, val); + return; + } + + throw new NotSupportedException(string.Format("Typed where expression is currently limited to AND-composed binary comparisons: {0}", expression)); + } + + private static string GetMappedColumn(Type modelType, Expression expression) + { + expression = UnwrapConvert(expression); + MemberExpression member = expression as MemberExpression; + if (member == null) + throw new NotSupportedException(string.Format("Selector must target a mapped property: {0}", expression)); + + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(modelType); + if (mapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", modelType.FullName)); + + return mapper.PropertyMap.TryGetValue(member.Member.Name) + ?? mapper.PropertyMap + .Where(x => string.Equals(x.Key, member.Member.Name, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Value) + .FirstOrDefault() + ?? member.Member.Name; + } + + private static string ResolveColumn(Type modelType, string memberName, string alias, Func decorateName) + { + string mapped = GetMappedColumnByName(modelType, memberName); + return string.IsNullOrEmpty(alias) + ? decorateName(mapped) + : string.Format("{0}.{1}", alias, decorateName(mapped)); + } + + internal static string GetMappedColumnByName(Type modelType, string memberName) + { + DynamicTypeMap mapper = DynamicMapperCache.GetMapper(modelType); + if (mapper == null) + throw new InvalidOperationException(string.Format("Cant assign unmapable type as a table ({0}).", modelType.FullName)); + + return mapper.PropertyMap.TryGetValue(memberName) + ?? mapper.PropertyMap.Where(x => string.Equals(x.Key, memberName, StringComparison.OrdinalIgnoreCase)).Select(x => x.Value).FirstOrDefault() + ?? memberName; + } + + private static Expression UnwrapConvert(Expression expression) + { + while (expression is UnaryExpression && + (((UnaryExpression)expression).NodeType == ExpressionType.Convert || + ((UnaryExpression)expression).NodeType == ExpressionType.ConvertChecked)) + expression = ((UnaryExpression)expression).Operand; + + return expression; + } + + private static object EvaluateExpression(Expression expression) + { + expression = UnwrapConvert(expression); + var objectMember = Expression.Convert(expression, typeof(object)); + var getter = Expression.Lambda>(objectMember).Compile(); + return getter(); + } + } +} diff --git a/DynamORM/Builders/TypedFluentExtensions.cs b/DynamORM/Builders/TypedFluentExtensions.cs new file mode 100644 index 0000000..b29d4bb --- /dev/null +++ b/DynamORM/Builders/TypedFluentExtensions.cs @@ -0,0 +1,52 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +*/ + +namespace DynamORM.Builders +{ + /// Marker extensions for typed fluent builder expressions. + public static class TypedFluentExtensions + { + /// Marks select projection alias in typed expressions. + public static T As(this T source, string alias) + { + return source; + } + + /// Marks ascending order in typed order expressions. + public static T Asc(this T source) + { + return source; + } + + /// Marks descending order in typed order expressions. + public static T Desc(this T source) + { + return source; + } + } +} diff --git a/DynamORM/Builders/TypedJoinBuilder.cs b/DynamORM/Builders/TypedJoinBuilder.cs new file mode 100644 index 0000000..a0ae403 --- /dev/null +++ b/DynamORM/Builders/TypedJoinBuilder.cs @@ -0,0 +1,168 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Linq.Expressions; +using DynamORM.TypedSql; + +namespace DynamORM.Builders +{ + /// Typed join specification builder used by typed fluent select queries. + /// Left side mapped type. + /// Right side mapped type. + public class TypedJoinBuilder + { + internal TypedJoinBuilder() + { + JoinType = DynamicJoinType.Join; + } + + /// Gets join alias. + public string Alias { get; private set; } + + /// Gets join type. + public DynamicJoinType JoinType { get; private set; } + + /// Gets custom join type text. + public string CustomJoinType { get; private set; } + + /// Gets a value indicating whether joined source should use NOLOCK. + public bool UseNoLock { get; private set; } + + /// Gets ON predicate. + public Expression> OnPredicate { get; private set; } + + /// Gets raw ON condition. + public string OnRawCondition { get; private set; } + + /// Gets typed SQL DSL ON specification. + public Func, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + + /// Sets join alias. + public TypedJoinBuilder As(string alias) + { + Alias = alias; + return this; + } + + /// Sets INNER JOIN. + public TypedJoinBuilder Inner() + { + JoinType = DynamicJoinType.Inner; + CustomJoinType = null; + return this; + } + + /// Sets plain JOIN. + public TypedJoinBuilder Join() + { + JoinType = DynamicJoinType.Join; + CustomJoinType = null; + return this; + } + + /// Sets LEFT JOIN. + public TypedJoinBuilder Left() + { + JoinType = DynamicJoinType.Left; + CustomJoinType = null; + return this; + } + + /// Sets RIGHT JOIN. + public TypedJoinBuilder Right() + { + JoinType = DynamicJoinType.Right; + CustomJoinType = null; + return this; + } + + /// Sets FULL JOIN. + public TypedJoinBuilder Full() + { + JoinType = DynamicJoinType.Full; + CustomJoinType = null; + return this; + } + + /// Sets LEFT OUTER JOIN. + public TypedJoinBuilder LeftOuter() + { + JoinType = DynamicJoinType.LeftOuter; + CustomJoinType = null; + return this; + } + + /// Sets RIGHT OUTER JOIN. + public TypedJoinBuilder RightOuter() + { + JoinType = DynamicJoinType.RightOuter; + CustomJoinType = null; + return this; + } + + /// Sets FULL OUTER JOIN. + public TypedJoinBuilder FullOuter() + { + JoinType = DynamicJoinType.FullOuter; + CustomJoinType = null; + return this; + } + + /// Sets custom join type text (for example: CROSS APPLY). + public TypedJoinBuilder Type(string joinType) + { + if (string.IsNullOrEmpty(joinType)) + throw new ArgumentNullException("joinType"); + + CustomJoinType = joinType.Trim(); + return this; + } + + /// Marks joined source with NOLOCK hint. + public TypedJoinBuilder NoLock(bool use = true) + { + UseNoLock = use; + return this; + } + + /// Sets ON predicate. + public TypedJoinBuilder On(Expression> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + OnPredicate = predicate; + OnRawCondition = null; + OnSqlPredicate = null; + return this; + } + + /// Sets raw ON clause (without the ON keyword). + public TypedJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + + OnRawCondition = condition.Trim(); + OnPredicate = null; + OnSqlPredicate = null; + return this; + } + + /// Sets typed SQL DSL ON predicate. + public TypedJoinBuilder OnSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + + OnSqlPredicate = predicate; + OnPredicate = null; + OnRawCondition = null; + return this; + } + } +} diff --git a/DynamORM/Builders/TypedJoinExtensions.cs b/DynamORM/Builders/TypedJoinExtensions.cs new file mode 100644 index 0000000..1c8e7ce --- /dev/null +++ b/DynamORM/Builders/TypedJoinExtensions.cs @@ -0,0 +1,86 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Linq.Expressions; + +namespace DynamORM.Builders +{ + /// Compatibility and convenience extensions for typed joins. + public static class TypedJoinExtensions + { + /// + /// Legacy compatibility helper. Prefer . + /// + public static IDynamicTypedSelectQueryBuilder JoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + string alias, + Expression> on, + string joinType = "INNER JOIN") + { + if (builder == null) throw new ArgumentNullException("builder"); + if (on == null) throw new ArgumentNullException("on"); + + DynamicJoinType jt = DynamicJoinType.Inner; + string normalized = (joinType ?? string.Empty).Trim().ToUpperInvariant(); + + if (normalized == "JOIN") + jt = DynamicJoinType.Join; + else if (normalized == "LEFT OUTER JOIN" || normalized == "LEFT OUTER") + jt = DynamicJoinType.LeftOuter; + else if (normalized == "RIGHT OUTER JOIN" || normalized == "RIGHT OUTER") + jt = DynamicJoinType.RightOuter; + else if (normalized == "FULL OUTER JOIN" || normalized == "FULL OUTER") + jt = DynamicJoinType.FullOuter; + else if (normalized == "LEFT JOIN" || normalized == "LEFT") + jt = DynamicJoinType.Left; + else if (normalized == "RIGHT JOIN" || normalized == "RIGHT") + jt = DynamicJoinType.Right; + else if (normalized == "FULL JOIN" || normalized == "FULL") + jt = DynamicJoinType.Full; + else if (normalized != "INNER JOIN" && normalized != "INNER" && normalized != "JOIN") + return builder.Join(on, alias, joinType); + + return builder.Join(on, alias, jt); + } + + /// Convenience typed INNER JOIN extension. + public static IDynamicTypedSelectQueryBuilder InnerJoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + Expression> on, + string alias = null) + { + return builder.Join(on, alias, DynamicJoinType.Inner); + } + + /// Convenience typed LEFT JOIN extension. + public static IDynamicTypedSelectQueryBuilder LeftJoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + Expression> on, + string alias = null) + { + return builder.Join(on, alias, DynamicJoinType.Left); + } + + /// Convenience typed RIGHT JOIN extension. + public static IDynamicTypedSelectQueryBuilder RightJoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + Expression> on, + string alias = null) + { + return builder.Join(on, alias, DynamicJoinType.Right); + } + + /// Convenience typed FULL JOIN extension. + public static IDynamicTypedSelectQueryBuilder FullJoinTyped( + this IDynamicTypedSelectQueryBuilder builder, + Expression> on, + string alias = null) + { + return builder.Join(on, alias, DynamicJoinType.Full); + } + } +} diff --git a/DynamORM/Builders/TypedScopeJoinBuilder.cs b/DynamORM/Builders/TypedScopeJoinBuilder.cs new file mode 100644 index 0000000..2d1df52 --- /dev/null +++ b/DynamORM/Builders/TypedScopeJoinBuilder.cs @@ -0,0 +1,398 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using DynamORM.TypedSql; + +namespace DynamORM.Builders +{ + public abstract class TypedScopeJoinBuilderBase + where TSelf : TypedScopeJoinBuilderBase + { + public string Alias { get; private set; } + public DynamicJoinType JoinType { get; private set; } + public string CustomJoinType { get; private set; } + public bool UseNoLock { get; private set; } + + protected TypedScopeJoinBuilderBase() + { + JoinType = DynamicJoinType.Join; + } + + public TSelf As(string alias) { Alias = alias; return (TSelf)this; } + public TSelf Inner() { JoinType = DynamicJoinType.Inner; CustomJoinType = null; return (TSelf)this; } + public TSelf Join() { JoinType = DynamicJoinType.Join; CustomJoinType = null; return (TSelf)this; } + public TSelf Left() { JoinType = DynamicJoinType.Left; CustomJoinType = null; return (TSelf)this; } + public TSelf Right() { JoinType = DynamicJoinType.Right; CustomJoinType = null; return (TSelf)this; } + public TSelf Full() { JoinType = DynamicJoinType.Full; CustomJoinType = null; return (TSelf)this; } + public TSelf LeftOuter() { JoinType = DynamicJoinType.LeftOuter; CustomJoinType = null; return (TSelf)this; } + public TSelf RightOuter() { JoinType = DynamicJoinType.RightOuter; CustomJoinType = null; return (TSelf)this; } + public TSelf FullOuter() { JoinType = DynamicJoinType.FullOuter; CustomJoinType = null; return (TSelf)this; } + public TSelf Type(string joinType) { if (string.IsNullOrEmpty(joinType)) throw new ArgumentNullException("joinType"); CustomJoinType = joinType.Trim(); return (TSelf)this; } + public TSelf NoLock(bool use = true) { UseNoLock = use; return (TSelf)this; } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + + public sealed class TypedScopeJoinBuilder : TypedScopeJoinBuilderBase> + { + internal Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> OnSqlPredicate { get; private set; } + internal string OnRawCondition { get; private set; } + + public TypedScopeJoinBuilder OnSql(Func, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedTableContext, TypedSqlPredicate> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + OnSqlPredicate = predicate; + OnRawCondition = null; + return this; + } + + public TypedScopeJoinBuilder OnRaw(string condition) + { + if (string.IsNullOrEmpty(condition)) + throw new ArgumentNullException("condition"); + OnRawCondition = condition.Trim(); + OnSqlPredicate = null; + return this; + } + } + +} \ No newline at end of file diff --git a/DynamORM/DynamORM.csproj b/DynamORM/DynamORM.csproj index 103f8ef..1a8738a 100644 --- a/DynamORM/DynamORM.csproj +++ b/DynamORM/DynamORM.csproj @@ -6,7 +6,7 @@ Copyright © RUSSEK Software 2012-2026 RUSSEK Software Grzegorz Russek - 1.9 + 2.0 https://git.dr4cul4.pl/RUSSEK-Software/DynamORM https://dr4cul4.pl DynamORM diff --git a/DynamORM/DynamicDatabase.cs b/DynamORM/DynamicDatabase.cs index f627e4e..0735cc5 100644 --- a/DynamORM/DynamicDatabase.cs +++ b/DynamORM/DynamicDatabase.cs @@ -471,6 +471,46 @@ namespace DynamORM return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).As(alias)); } } + + /// Adds to the FROM clause using . + /// Type which can be represented in database. + /// Table alias. + /// use no lock. + /// This instance to permit chaining. + public virtual IDynamicTypedSelectQueryBuilder FromTyped(string alias = null, bool noLock = false) + { + // TODO: Make it more readable and maitainable + DynamicTypedSelectQueryBuilder builder = new DynamicTypedSelectQueryBuilder(this); + + if (noLock) + { + if (string.IsNullOrEmpty(alias)) + builder.From(x => x(typeof(T)).NoLock()); + else + builder.From(x => x(typeof(T)).As(alias).NoLock()); + } + else + { + if (string.IsNullOrEmpty(alias)) + builder.From(x => x(typeof(T))); + else + builder.From(x => x(typeof(T)).As(alias)); + } + + return builder; + } + + /// Adds to the FROM clause using a typed scope builder with evolving join arity. + /// Type which can be represented in database. + /// Table alias. + /// use no lock. + /// Scope builder instance. + public virtual IDynamicTypedSelectScopeQueryBuilder FromTypedScope(string alias = null, bool noLock = false) + { + DynamicTypedSelectQueryBuilder builder = (DynamicTypedSelectQueryBuilder)FromTyped(alias, noLock); + string resolvedAlias = string.IsNullOrEmpty(alias) ? builder.Tables[0].Alias ?? builder.Tables[0].Name : alias; + return new DynamicTypedSelectScopeQueryBuilder(builder, resolvedAlias); + } /// Adds to the FROM clause using . /// Type which can be represented in database. @@ -503,6 +543,14 @@ namespace DynamORM { return new DynamicInsertQueryBuilder(this).Table(typeof(T)); } + + /// Adds to the INSERT INTO clause using . + /// Type which can be represented in database. + /// This instance to permit chaining. + public virtual IDynamicTypedInsertQueryBuilder InsertTyped() + { + return new DynamicTypedInsertQueryBuilder(this, true); + } /// Adds to the INSERT INTO clause using . /// Type which can be represented in database. @@ -611,6 +659,14 @@ namespace DynamORM return new DynamicUpdateQueryBuilder(this).Table(typeof(T)); } + /// Adds to the UPDATE clause using . + /// Type which can be represented in database. + /// This instance to permit chaining. + public virtual IDynamicTypedUpdateQueryBuilder UpdateTyped() + { + return new DynamicTypedUpdateQueryBuilder(this, true); + } + /// Adds to the UPDATE clause using . /// Type which can be represented in database. /// This instance to permit chaining. @@ -832,6 +888,14 @@ namespace DynamORM return new DynamicDeleteQueryBuilder(this).Table(typeof(T)); } + /// Adds to the DELETE FROM clause using . + /// Type which can be represented in database. + /// This instance to permit chaining. + public virtual IDynamicTypedDeleteQueryBuilder DeleteTyped() + { + return new DynamicTypedDeleteQueryBuilder(this, true); + } + /// Adds to the DELETE FROM clause using . /// Type which can be represented in database. /// This instance to permit chaining. @@ -2006,16 +2070,16 @@ namespace DynamORM #region IExtendedDisposable Members - /// Performs application-defined tasks associated with freeing, - /// releasing, or resetting unmanaged resources. - public void Dispose() - { - if (IsDisposed) - return; - -#if !DYNAMORM_OMMIT_OLDSYNTAX - List tables = TablesCache.Values.ToList(); - TablesCache.Clear(); + /// Performs application-defined tasks associated with freeing, + /// releasing, or resetting unmanaged resources. + public void Dispose() + { + if (IsDisposed) + return; + +#if !DYNAMORM_OMMIT_OLDSYNTAX + List tables = TablesCache.Values.ToList(); + TablesCache.Clear(); tables.ForEach(t => t.Dispose()); tables.Clear(); @@ -2066,18 +2130,18 @@ namespace DynamORM RemainingBuilders = null; } - ClearSchema(); - if (_proc != null) - _proc.Dispose(); - - _proc = null; - _tempConn = null; - IsDisposed = true; - } + ClearSchema(); + if (_proc != null) + _proc.Dispose(); + + _proc = null; + _tempConn = null; + IsDisposed = true; + } /// Gets a value indicating whether this instance is disposed. public bool IsDisposed { get; private set; } #endregion IExtendedDisposable Members } -} +} diff --git a/DynamORM/TypedSql/ITypedSqlRenderContext.cs b/DynamORM/TypedSql/ITypedSqlRenderContext.cs new file mode 100644 index 0000000..203b3e0 --- /dev/null +++ b/DynamORM/TypedSql/ITypedSqlRenderContext.cs @@ -0,0 +1,26 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; + +namespace DynamORM.TypedSql +{ + /// Render context used by typed SQL DSL nodes. + public interface ITypedSqlRenderContext + { + /// Resolve mapped column for given model member. + string ResolveColumn(Type modelType, string memberName, string alias); + + /// Render value as SQL parameter or literal fragment. + string RenderValue(object value); + + /// Decorate SQL identifier. + string DecorateName(string name); + + /// Render subquery SQL and merge any parameters into current context. + string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query); + } +} diff --git a/DynamORM/TypedSql/Sql.cs b/DynamORM/TypedSql/Sql.cs new file mode 100644 index 0000000..06a2132 --- /dev/null +++ b/DynamORM/TypedSql/Sql.cs @@ -0,0 +1,226 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Collections.Generic; +using DynamORM.Builders; + +namespace DynamORM.TypedSql +{ + /// Entry point for the typed SQL DSL. + public static class Sql + { + /// Create parameterized value expression. + public static TypedSqlExpression Val(T value) + { + return new TypedSqlValueExpression(value); + } + + /// Create parameterized value expression. + public static TypedSqlExpression Val(object value) + { + return new TypedSqlValueExpression(value); + } + + /// Create typed table context for an explicitly named alias, including joined aliases. + public static TypedTableContext Table(string alias) + { + return new TypedTableContext(alias); + } + + /// Create raw SQL expression. + public static TypedSqlExpression Raw(string sql) + { + return new TypedSqlRawExpression(sql); + } + + /// Create raw ORDER BY fragment. + public static TypedSqlOrderExpression RawOrder(string sql) + { + return new TypedSqlRawOrderExpression(Raw(sql)); + } + + /// Create generic function call. + public static TypedSqlExpression Func(string name, params TypedSqlExpression[] arguments) + { + return new TypedSqlFunctionExpression(name, arguments); + } + + /// Create COUNT(*) expression. + public static TypedSqlExpression Count() + { + return Raw("COUNT(*)"); + } + + /// Create COUNT(expr) expression. + public static TypedSqlExpression Count(TypedSqlExpression expression) + { + return Func("COUNT", expression); + } + + /// Create COALESCE expression. + public static TypedSqlExpression Coalesce(params TypedSqlExpression[] expressions) + { + return Func("COALESCE", expressions); + } + + /// Create SUM expression. + public static TypedSqlExpression Sum(TypedSqlExpression expression) + { + return Func("SUM", expression); + } + + /// Create AVG expression. + public static TypedSqlExpression Avg(TypedSqlExpression expression) + { + return Func("AVG", expression); + } + + /// Create MIN expression. + public static TypedSqlExpression Min(TypedSqlExpression expression) + { + return Func("MIN", expression); + } + + /// Create MAX expression. + public static TypedSqlExpression Max(TypedSqlExpression expression) + { + return Func("MAX", expression); + } + + /// Create ABS expression. + public static TypedSqlExpression Abs(TypedSqlExpression expression) + { + return Func("ABS", expression); + } + + /// Create UPPER expression. + public static TypedSqlExpression Upper(TypedSqlExpression expression) + { + return Func("UPPER", expression); + } + + /// Create LOWER expression. + public static TypedSqlExpression Lower(TypedSqlExpression expression) + { + return Func("LOWER", expression); + } + + /// Create TRIM expression. + public static TypedSqlExpression Trim(TypedSqlExpression expression) + { + return Func("TRIM", expression); + } + + /// Create LENGTH expression. + public static TypedSqlExpression Length(TypedSqlExpression expression) + { + return Func("LENGTH", expression); + } + + /// Create NULLIF expression. + public static TypedSqlExpression NullIf(TypedSqlExpression left, TypedSqlExpression right) + { + return Func("NULLIF", left, right); + } + + /// Create CURRENT_TIMESTAMP expression. + public static TypedSqlExpression CurrentTimestamp() + { + return Raw("CURRENT_TIMESTAMP"); + } + + /// Create scalar subquery expression. + public static TypedSqlExpression SubQuery(IDynamicSelectQueryBuilder query) + { + return new TypedSqlSubQueryExpression(query); + } + + /// Create scalar typed subquery expression without manually constructing the builder. + public static TypedSqlExpression SubQuery(DynamicDatabase db, Func, IDynamicSelectQueryBuilder> configure, string alias = null, bool noLock = false) + { + if (db == null) + throw new ArgumentNullException("db"); + if (configure == null) + throw new ArgumentNullException("configure"); + + return new TypedSqlSubQueryExpression(configure(db.FromTyped(alias, noLock))); + } + + /// Create scalar typed subquery expression using the scoped typed builder API. + public static TypedSqlExpression SubQueryScope(DynamicDatabase db, Func, IDynamicSelectQueryBuilder> configure, string alias = null, bool noLock = false) + { + if (db == null) + throw new ArgumentNullException("db"); + if (configure == null) + throw new ArgumentNullException("configure"); + + return new TypedSqlSubQueryExpression(configure(db.FromTypedScope(alias, noLock))); + } + + /// Create EXISTS predicate. + public static TypedSqlPredicate Exists(IDynamicSelectQueryBuilder query) + { + return new TypedSqlExistsPredicate(query); + } + + /// Create EXISTS predicate from typed subquery factory. + public static TypedSqlPredicate Exists(DynamicDatabase db, Func, IDynamicSelectQueryBuilder> configure, string alias = null, bool noLock = false) + { + if (db == null) + throw new ArgumentNullException("db"); + if (configure == null) + throw new ArgumentNullException("configure"); + + return new TypedSqlExistsPredicate(configure(db.FromTyped(alias, noLock))); + } + + /// Create EXISTS predicate from scoped typed subquery factory. + public static TypedSqlPredicate ExistsScope(DynamicDatabase db, Func, IDynamicSelectQueryBuilder> configure, string alias = null, bool noLock = false) + { + if (db == null) + throw new ArgumentNullException("db"); + if (configure == null) + throw new ArgumentNullException("configure"); + + return new TypedSqlExistsPredicate(configure(db.FromTypedScope(alias, noLock))); + } + + /// Create CASE expression builder. + public static TypedSqlCaseBuilder Case() + { + return new TypedSqlCaseBuilder(); + } + } + + /// Builder for CASE expressions. + /// Result type. + public sealed class TypedSqlCaseBuilder + { + private readonly IList> _cases = new List>(); + + /// Add WHEN ... THEN ... clause. + public TypedSqlCaseBuilder When(TypedSqlPredicate predicate, object value) + { + _cases.Add(new KeyValuePair( + predicate, + value as TypedSqlExpression ?? Sql.Val(value))); + return this; + } + + /// Finalize CASE expression with ELSE clause. + public TypedSqlExpression Else(object value) + { + return new TypedSqlCaseExpression(_cases, value as TypedSqlExpression ?? Sql.Val(value)); + } + + /// Finalize CASE expression without ELSE clause. + public TypedSqlExpression End() + { + return new TypedSqlCaseExpression(_cases, null); + } + } +} diff --git a/DynamORM/TypedSql/TypedSqlExpression.cs b/DynamORM/TypedSql/TypedSqlExpression.cs new file mode 100644 index 0000000..a13c7d0 --- /dev/null +++ b/DynamORM/TypedSql/TypedSqlExpression.cs @@ -0,0 +1,572 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using DynamORM.Builders; + +namespace DynamORM.TypedSql +{ + /// Base selectable SQL fragment for the typed DSL. + public abstract class TypedSqlSelectable + { + internal abstract string Render(ITypedSqlRenderContext context); + } + + /// Base SQL expression for the typed DSL. + public abstract class TypedSqlExpression : TypedSqlSelectable + { + /// Add arithmetic expression. + public static TypedSqlExpression operator +(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "+", right); + } + + /// Subtract arithmetic expression. + public static TypedSqlExpression operator -(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "-", right); + } + + /// Multiply arithmetic expression. + public static TypedSqlExpression operator *(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "*", right); + } + + /// Divide arithmetic expression. + public static TypedSqlExpression operator /(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "/", right); + } + + /// Modulo arithmetic expression. + public static TypedSqlExpression operator %(TypedSqlExpression left, TypedSqlExpression right) + { + return new TypedSqlBinaryExpression(left, "%", right); + } + + /// Alias this expression in SELECT clause. + public TypedSqlAliasedExpression As(string alias) + { + return new TypedSqlAliasedExpression(this, alias); + } + + /// Order ascending. + public TypedSqlOrderExpression Asc() + { + return new TypedSqlOrderExpression(this, true); + } + + /// Order descending. + public TypedSqlOrderExpression Desc() + { + return new TypedSqlOrderExpression(this, false); + } + + /// Add expression to another value. + public TypedSqlExpression Add(object value) + { + return new TypedSqlBinaryExpression(this, "+", value as TypedSqlExpression ?? Sql.Val(value)); + } + + /// Subtract another value. + public TypedSqlExpression Sub(object value) + { + return new TypedSqlBinaryExpression(this, "-", value as TypedSqlExpression ?? Sql.Val(value)); + } + + /// Multiply by another value. + public TypedSqlExpression Mul(object value) + { + return new TypedSqlBinaryExpression(this, "*", value as TypedSqlExpression ?? Sql.Val(value)); + } + + /// Divide by another value. + public TypedSqlExpression Div(object value) + { + return new TypedSqlBinaryExpression(this, "/", value as TypedSqlExpression ?? Sql.Val(value)); + } + + /// Modulo by another value. + public TypedSqlExpression Mod(object value) + { + return new TypedSqlBinaryExpression(this, "%", value as TypedSqlExpression ?? Sql.Val(value)); + } + + /// Equality predicate. + public TypedSqlPredicate Eq(object value) + { + return new TypedSqlBinaryPredicate(this, "=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + + /// Inequality predicate. + public TypedSqlPredicate NotEq(object value) + { + return new TypedSqlBinaryPredicate(this, "<>", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + + /// Greater-than predicate. + public TypedSqlPredicate Gt(object value) + { + return new TypedSqlBinaryPredicate(this, ">", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + + /// Greater-than-or-equal predicate. + public TypedSqlPredicate Gte(object value) + { + return new TypedSqlBinaryPredicate(this, ">=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + + /// Less-than predicate. + public TypedSqlPredicate Lt(object value) + { + return new TypedSqlBinaryPredicate(this, "<", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + + /// Less-than-or-equal predicate. + public TypedSqlPredicate Lte(object value) + { + return new TypedSqlBinaryPredicate(this, "<=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value)); + } + + /// IS NULL predicate. + public TypedSqlPredicate IsNull() + { + return new TypedSqlUnaryPredicate(this, "IS NULL"); + } + + /// IS NOT NULL predicate. + public TypedSqlPredicate IsNotNull() + { + return new TypedSqlUnaryPredicate(this, "IS NOT NULL"); + } + + /// LIKE predicate. + public TypedSqlPredicate Like(string pattern) + { + return new TypedSqlBinaryPredicate(this, "LIKE", Sql.Val(pattern)); + } + + /// IN predicate. + public TypedSqlPredicate In(params object[] values) + { + return new TypedSqlInPredicate(this, values); + } + + /// IN predicate. + public TypedSqlPredicate In(IEnumerable values) + { + return new TypedSqlInPredicate(this, values); + } + + /// NOT IN predicate. + public TypedSqlPredicate NotIn(params object[] values) + { + return new TypedSqlInPredicate(this, values, true); + } + + /// NOT IN predicate. + public TypedSqlPredicate NotIn(IEnumerable values) + { + return new TypedSqlInPredicate(this, values, true); + } + + /// BETWEEN predicate. + public TypedSqlPredicate Between(object lower, object upper) + { + return new TypedSqlBetweenPredicate(this, lower is TypedSqlExpression ? (TypedSqlExpression)lower : Sql.Val(lower), upper is TypedSqlExpression ? (TypedSqlExpression)upper : Sql.Val(upper)); + } + + /// Starts-with LIKE predicate. + public TypedSqlPredicate StartsWith(string value) + { + return Like((value ?? string.Empty) + "%"); + } + + /// Ends-with LIKE predicate. + public TypedSqlPredicate EndsWith(string value) + { + return Like("%" + (value ?? string.Empty)); + } + + /// Contains LIKE predicate. + public TypedSqlPredicate Contains(string value) + { + return Like("%" + (value ?? string.Empty) + "%"); + } + } + + /// Typed SQL expression. + public abstract class TypedSqlExpression : TypedSqlExpression + { + } + + /// Typed SQL predicate expression. + public abstract class TypedSqlPredicate : TypedSqlExpression + { + /// Combine with AND. + public TypedSqlPredicate And(TypedSqlPredicate right) + { + return new TypedSqlCombinedPredicate(this, "AND", right); + } + + /// Combine with OR. + public TypedSqlPredicate Or(TypedSqlPredicate right) + { + return new TypedSqlCombinedPredicate(this, "OR", right); + } + + /// Negate predicate. + public TypedSqlPredicate Not() + { + return new TypedSqlNegatedPredicate(this); + } + } + + /// Aliased SQL expression. + public sealed class TypedSqlAliasedExpression : TypedSqlSelectable + { + private readonly TypedSqlExpression _expression; + private readonly string _alias; + + internal TypedSqlAliasedExpression(TypedSqlExpression expression, string alias) + { + _expression = expression; + _alias = alias; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("{0} AS {1}", _expression.Render(context), context.DecorateName(_alias)); + } + } + + /// Ordered SQL expression. + public class TypedSqlOrderExpression : TypedSqlSelectable + { + private readonly TypedSqlExpression _expression; + private readonly bool _ascending; + private readonly string _nullOrdering; + private readonly bool _raw; + + internal TypedSqlOrderExpression(TypedSqlExpression expression, bool ascending, string nullOrdering = null, bool raw = false) + { + _expression = expression; + _ascending = ascending; + _nullOrdering = nullOrdering; + _raw = raw; + } + + /// Append NULLS FIRST ordering. + public TypedSqlOrderExpression NullsFirst() + { + return new TypedSqlOrderExpression(_expression, _ascending, "NULLS FIRST", _raw); + } + + /// Append NULLS LAST ordering. + public TypedSqlOrderExpression NullsLast() + { + return new TypedSqlOrderExpression(_expression, _ascending, "NULLS LAST", _raw); + } + + internal override string Render(ITypedSqlRenderContext context) + { + string rendered = _raw + ? _expression.Render(context) + : string.Format("{0} {1}", _expression.Render(context), _ascending ? "ASC" : "DESC"); + if (!string.IsNullOrEmpty(_nullOrdering)) + rendered = string.Format("{0} {1}", rendered, _nullOrdering); + + return rendered; + } + } + + internal sealed class TypedSqlRawOrderExpression : TypedSqlOrderExpression + { + internal TypedSqlRawOrderExpression(TypedSqlExpression expression) + : base(expression, true, null, true) + { + } + } + + internal sealed class TypedSqlBinaryExpression : TypedSqlExpression + { + private readonly TypedSqlExpression _left; + private readonly string _operator; + private readonly TypedSqlExpression _right; + + internal TypedSqlBinaryExpression(TypedSqlExpression left, string op, TypedSqlExpression right) + { + _left = left; + _operator = op; + _right = right; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0} {1} {2})", _left.Render(context), _operator, _right.Render(context)); + } + } + + internal sealed class TypedSqlColumnExpression : TypedSqlExpression + { + private readonly Type _modelType; + private readonly string _memberName; + private readonly string _alias; + + internal TypedSqlColumnExpression(Type modelType, string memberName, string alias) + { + _modelType = modelType; + _memberName = memberName; + _alias = alias; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return context.ResolveColumn(_modelType, _memberName, _alias); + } + } + + internal sealed class TypedSqlValueExpression : TypedSqlExpression, ITypedSqlNullValue + { + private readonly object _value; + + internal TypedSqlValueExpression(object value) + { + _value = value; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return context.RenderValue(_value); + } + + public bool IsNullValue + { + get { return _value == null; } + } + } + + internal sealed class TypedSqlRawExpression : TypedSqlExpression + { + private readonly string _sql; + + internal TypedSqlRawExpression(string sql) + { + _sql = sql; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return _sql; + } + } + + internal sealed class TypedSqlFunctionExpression : TypedSqlExpression + { + private readonly string _name; + private readonly IList _arguments; + + internal TypedSqlFunctionExpression(string name, params TypedSqlExpression[] arguments) + { + _name = name; + _arguments = arguments ?? new TypedSqlExpression[0]; + } + + internal override string Render(ITypedSqlRenderContext context) + { + List rendered = new List(); + foreach (TypedSqlExpression argument in _arguments) + rendered.Add(argument.Render(context)); + + return string.Format("{0}({1})", _name, string.Join(", ", rendered.ToArray())); + } + } + + internal sealed class TypedSqlUnaryPredicate : TypedSqlPredicate + { + private readonly TypedSqlExpression _expression; + private readonly string _operator; + + internal TypedSqlUnaryPredicate(TypedSqlExpression expression, string op) + { + _expression = expression; + _operator = op; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0} {1})", _expression.Render(context), _operator); + } + } + + internal sealed class TypedSqlBinaryPredicate : TypedSqlPredicate + { + private readonly TypedSqlExpression _left; + private readonly string _operator; + private readonly TypedSqlExpression _right; + + internal TypedSqlBinaryPredicate(TypedSqlExpression left, string op, TypedSqlExpression right) + { + _left = left; + _operator = op; + _right = right; + } + + internal override string Render(ITypedSqlRenderContext context) + { + string op = _operator; + TypedSqlValueExpression objRight = _right as TypedSqlValueExpression; + if ((objRight != null && objRight.IsNullValue) || (_right is ITypedSqlNullValue && ((ITypedSqlNullValue)_right).IsNullValue)) + op = _operator == "=" ? "IS" : _operator == "<>" ? "IS NOT" : _operator; + + return string.Format("({0} {1} {2})", _left.Render(context), op, _right.Render(context)); + } + } + + internal interface ITypedSqlNullValue + { + bool IsNullValue { get; } + } + + internal sealed class TypedSqlInPredicate : TypedSqlPredicate + { + private readonly TypedSqlExpression _left; + private readonly IEnumerable _values; + private readonly bool _negated; + + internal TypedSqlInPredicate(TypedSqlExpression left, IEnumerable values, bool negated = false) + { + _left = left; + _values = values; + _negated = negated; + } + + internal override string Render(ITypedSqlRenderContext context) + { + List rendered = new List(); + foreach (object value in _values) + rendered.Add((value as TypedSqlExpression ?? Sql.Val(value)).Render(context)); + + if (rendered.Count == 0) + return _negated ? "(1 = 1)" : "(1 = 0)"; + + return string.Format("({0} {1}({2}))", _left.Render(context), _negated ? "NOT IN" : "IN", string.Join(", ", rendered.ToArray())); + } + } + + internal sealed class TypedSqlBetweenPredicate : TypedSqlPredicate + { + private readonly TypedSqlExpression _left; + private readonly TypedSqlExpression _lower; + private readonly TypedSqlExpression _upper; + + internal TypedSqlBetweenPredicate(TypedSqlExpression left, TypedSqlExpression lower, TypedSqlExpression upper) + { + _left = left; + _lower = lower; + _upper = upper; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0} BETWEEN {1} AND {2})", _left.Render(context), _lower.Render(context), _upper.Render(context)); + } + } + + internal sealed class TypedSqlCombinedPredicate : TypedSqlPredicate + { + private readonly TypedSqlPredicate _left; + private readonly string _operator; + private readonly TypedSqlPredicate _right; + + internal TypedSqlCombinedPredicate(TypedSqlPredicate left, string op, TypedSqlPredicate right) + { + _left = left; + _operator = op; + _right = right; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0} {1} {2})", _left.Render(context), _operator, _right.Render(context)); + } + } + + internal sealed class TypedSqlNegatedPredicate : TypedSqlPredicate + { + private readonly TypedSqlPredicate _predicate; + + internal TypedSqlNegatedPredicate(TypedSqlPredicate predicate) + { + _predicate = predicate; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("(NOT {0})", _predicate.Render(context)); + } + } + + internal sealed class TypedSqlCaseExpression : TypedSqlExpression + { + private readonly IList> _cases; + private readonly TypedSqlExpression _elseExpression; + + internal TypedSqlCaseExpression(IList> cases, TypedSqlExpression elseExpression) + { + _cases = cases; + _elseExpression = elseExpression; + } + + internal override string Render(ITypedSqlRenderContext context) + { + List items = new List(); + items.Add("CASE"); + + foreach (KeyValuePair item in _cases) + items.Add(string.Format("WHEN {0} THEN {1}", item.Key.Render(context), item.Value.Render(context))); + + if (_elseExpression != null) + items.Add(string.Format("ELSE {0}", _elseExpression.Render(context))); + + items.Add("END"); + return string.Join(" ", items.ToArray()); + } + } + + internal sealed class TypedSqlSubQueryExpression : TypedSqlExpression + { + private readonly IDynamicSelectQueryBuilder _query; + + internal TypedSqlSubQueryExpression(IDynamicSelectQueryBuilder query) + { + _query = query; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("({0})", context.RenderSubQuery(_query)); + } + } + + internal sealed class TypedSqlExistsPredicate : TypedSqlPredicate + { + private readonly IDynamicSelectQueryBuilder _query; + + internal TypedSqlExistsPredicate(IDynamicSelectQueryBuilder query) + { + _query = query; + } + + internal override string Render(ITypedSqlRenderContext context) + { + return string.Format("(EXISTS ({0}))", context.RenderSubQuery(_query)); + } + } +} diff --git a/DynamORM/TypedSql/TypedTableContext.cs b/DynamORM/TypedSql/TypedTableContext.cs new file mode 100644 index 0000000..4240141 --- /dev/null +++ b/DynamORM/TypedSql/TypedTableContext.cs @@ -0,0 +1,46 @@ +/* + * DynamORM - Dynamic Object-Relational Mapping library. + * Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com) + * All rights reserved. + */ + +using System; +using System.Linq.Expressions; + +namespace DynamORM.TypedSql +{ + /// Typed table context used by the typed SQL DSL. + /// Mapped entity type. + public sealed class TypedTableContext + { + internal TypedTableContext(string alias) + { + Alias = alias; + } + + /// Gets table alias used by the current query. + public string Alias { get; private set; } + + /// Creates a mapped column expression. + public TypedSqlExpression Col(Expression> selector) + { + if (selector == null) + throw new ArgumentNullException("selector"); + + MemberExpression member = selector.Body as MemberExpression; + if (member == null && selector.Body is UnaryExpression) + member = ((UnaryExpression)selector.Body).Operand as MemberExpression; + + if (member == null) + throw new NotSupportedException(string.Format("Column selector must target a mapped property: {0}", selector)); + + return new TypedSqlColumnExpression(typeof(T), member.Member.Name, Alias); + } + + /// Select all columns from this typed table context. + public TypedSqlExpression All() + { + return Sql.Raw(string.IsNullOrEmpty(Alias) ? "*" : Alias + ".*"); + } + } +} diff --git a/docs/README.md b/docs/README.md index 025deea..fd7fe6c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ This documentation is based on: - [Quick Start](quick-start.md) - [Dynamic Table API](dynamic-table-api.md) - [Fluent Builder API](fluent-builder-api.md) +- [Typed Fluent Syntax](typed-fluent-syntax.md) - [Mapping and Entities](mapping-and-entities.md) - [Transactions and Disposal](transactions-and-disposal.md) - [Stored Procedures](stored-procedures.md) @@ -36,3 +37,5 @@ DynamORM provides two major usage styles: - `db.Insert() / db.Update() / db.Delete()` The dynamic API is concise and fast to use. The fluent builder API gives stronger composition and explicit SQL control. + +For the newer property-mapped typed fluent syntax, see [Typed Fluent Syntax](typed-fluent-syntax.md). diff --git a/docs/fluent-builder-api.md b/docs/fluent-builder-api.md index 55449eb..c84aba1 100644 --- a/docs/fluent-builder-api.md +++ b/docs/fluent-builder-api.md @@ -1,5 +1,7 @@ # Fluent Builder API +For the newer property-mapped typed fluent API, see [Typed Fluent Syntax](typed-fluent-syntax.md). This page focuses on the original dynamic fluent builder semantics and parser behavior. + The fluent API is built around: - `IDynamicSelectQueryBuilder` diff --git a/docs/quick-start.md b/docs/quick-start.md index 4a24707..9f3b3d4 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -52,6 +52,22 @@ using (var query = db.From("users").Where("id", 19).SelectColumn("first")) } ``` +## First Query (Typed Fluent Syntax) + +```csharp +using (var db = new DynamicDatabase(SQLiteFactory.Instance, "Data Source=app.db;", options)) +{ + var cmd = db.FromTyped("u") + .SelectSql(u => u.Col(x => x.Code)) + .WhereSql(u => u.Col(x => x.Id).Eq(19)); + + var value = cmd.ScalarAs(); + Console.WriteLine(value); +} +``` + +For multi-join typed queries, prefer `FromTypedScope(...)`. Full details are documented in [Typed Fluent Syntax](typed-fluent-syntax.md). + ## Insert, Update, Delete ```csharp diff --git a/docs/typed-fluent-syntax.md b/docs/typed-fluent-syntax.md new file mode 100644 index 0000000..e8b4968 --- /dev/null +++ b/docs/typed-fluent-syntax.md @@ -0,0 +1,367 @@ +# Typed Fluent Syntax + +This page documents the new typed fluent syntax added alongside the original dynamic fluent builder API. + +It is intended for cases where: + +- you want property-based IntelliSense instead of raw column names +- you want mapped property validation in fluent SQL construction +- you still want explicit SQL composition instead of LINQ translation + +The old dynamic fluent API remains unchanged. This typed API is additive. + +## Two Typed Styles + +There are currently two typed select styles: + +- positional typed builder: + - `db.FromTyped("alias")` +- scoped typed builder: + - `db.FromTypedScope("alias")` + +Recommendation: + +- use `FromTypedScope(...)` for multi-join queries +- use `FromTyped(...)` for simple root-table typed queries or when you want direct positional generic overloads + +## Root Typed Builder + +Basic example: + +```csharp +var cmd = db.FromTyped("u") + .SelectSql(u => u.Col(x => x.Code)) + .WhereSql(u => u.Col(x => x.Id).Eq(1)); +``` + +Mapped properties are resolved through entity metadata: + +```csharp +[Table(Name = "sample_users")] +public class User +{ + [Column("id_user", true)] + public long Id { get; set; } + + [Column("user_code")] + public string Code { get; set; } +} +``` + +So: + +- `u.Col(x => x.Id)` renders mapped column `u."id_user"` +- `u.Col(x => x.Code)` renders mapped column `u."user_code"` + +## Core Building Blocks + +The typed DSL is built around: + +- `TypedTableContext` +- `TypedSqlExpression` +- `TypedSqlPredicate` +- `TypedSqlOrderExpression` +- `Sql.*` helpers + +Common building blocks: + +```csharp +u.Col(x => x.Id) +Sql.Val(1) +Sql.Count() +Sql.Coalesce(u.Col(x => x.Code), Sql.Val("N/A")) +Sql.Case().When(...).Else(...) +``` + +## Positional Typed Builder + +`FromTyped(...)` supports typed joins and then exposes joined tables by position. + +Example: + +```csharp +var cmd = db.FromTyped("u") + .Join(j => j.Left().As("c").OnSql((u, c) => + u.Col(x => x.Id).Eq(c.Col(x => x.UserId)))) + .SelectSql( + (u, c) => u.Col(x => x.Id).As("user_id"), + (u, c) => c.Col(x => x.ClientCode).As("client_code")) + .WhereSql((u, c) => + c.Col(x => x.IsDeleted).Eq(0)); +``` + +This style is explicit, but becomes noisy as join count grows because join types must be repeated in generic parameters. + +## Scoped Typed Builder + +`FromTypedScope(...)` solves the repeated-generic problem by changing builder type after each join. + +Example: + +```csharp +var cmd = db.FromTypedScope("u") + .Join(j => j.Left().As("c").OnSql((u, c) => + u.Col(x => x.Id).Eq(c.Col(x => x.UserId)))) + .Join(j => j.Left().As("r").OnSql((u, c, r) => + c.Col(x => x.UserId).Eq(r.Col(x => x.UserId)))) + .SelectSql( + (u, c, r) => u.Col(x => x.Id), + (u, c, r) => r.Col(x => x.RoleName).As("role_name")) + .WhereSql((u, c, r) => + r.Col(x => x.RoleId).Gt(0)); +``` + +Important behavior: + +- each `Join(...)` extends the available typed lambda parameters +- later joins can reference previously joined tables inside `OnSql(...)` +- this is the preferred typed syntax for larger join graphs + +Current implementation supports up to `16` typed tables in one scoped chain. + +## Join Syntax + +Typed joins support: + +- `Inner()` +- `Join()` +- `Left()` +- `Right()` +- `Full()` +- `LeftOuter()` +- `RightOuter()` +- `FullOuter()` +- `Type("...")` for custom join keywords +- `NoLock()` +- `OnSql(...)` +- `OnRaw(...)` + +Examples: + +```csharp +.Join(j => j.Left().As("c").OnSql((u, c) => + u.Col(x => x.Id).Eq(c.Col(x => x.UserId)))) + +.Join(j => j.Type("CROSS APPLY").As("c").NoLock()) + +.Join(j => j.Left().As("r").OnRaw("c.\"User_Id\" = r.\"User_Id\"")) +``` + +`OnSql(...)` is usually the best option because it stays mapped and typed. + +## Selecting Columns + +Single-column select: + +```csharp +.SelectSql(u => u.Col(x => x.Code)) +``` + +Aliased select: + +```csharp +.SelectSql(u => u.Col(x => x.Code).As("user_code")) +``` + +Wildcard: + +```csharp +.SelectSql(u => u.All()) +``` + +Multi-table scoped select: + +```csharp +.SelectSql( + (u, c, r) => u.Col(x => x.Id).As("user_id"), + (u, c, r) => c.Col(x => x.ClientCode).As("client_code"), + (u, c, r) => r.Col(x => x.RoleName).As("role_name")) +``` + +## Predicates + +Available predicate patterns include: + +- `Eq` +- `NotEq` +- `Gt` +- `Gte` +- `Lt` +- `Lte` +- `IsNull` +- `IsNotNull` +- `Like` +- `StartsWith` +- `EndsWith` +- `Contains` +- `In` +- `NotIn` +- `Between` +- `And` +- `Or` +- `Not` + +Example: + +```csharp +.WhereSql((u, c) => + u.Col(x => x.Code).StartsWith("ADM") + .And(c.Col(x => x.IsDeleted).Eq(0)) + .And(c.Col(x => x.ClientCode).IsNotNull())) +``` + +## Functions and Expressions + +Standard helpers: + +- `Sql.Count()` +- `Sql.Count(expr)` +- `Sql.Sum(...)` +- `Sql.Avg(...)` +- `Sql.Min(...)` +- `Sql.Max(...)` +- `Sql.Abs(...)` +- `Sql.Upper(...)` +- `Sql.Lower(...)` +- `Sql.Trim(...)` +- `Sql.Length(...)` +- `Sql.NullIf(...)` +- `Sql.Coalesce(...)` +- `Sql.CurrentTimestamp()` + +Examples: + +```csharp +.SelectSql( + u => Sql.Count().As("cnt"), + u => Sql.Coalesce(u.Col(x => x.Code), Sql.Val("N/A")).As("code_value")) + +.HavingSql((u, c) => Sql.Count(c.Col(x => x.UserId)).Gt(0)) +``` + +Arithmetic is also supported: + +```csharp +.SelectSql(u => (u.Col(x => x.Id) + Sql.Val(1)).As("plus_one")) +``` + +## CASE Expressions + +```csharp +.SelectSql(u => Sql.Case() + .When(u.Col(x => x.Code).Eq("A"), "Alpha") + .When(u.Col(x => x.Code).Eq("B"), "Beta") + .Else("Other") + .As("category")) +``` + +Use `CASE` when expression logic becomes too awkward for simple `COALESCE` or comparison predicates. + +## Grouping and Ordering + +Grouping: + +```csharp +.GroupBySql((u, c) => u.Col(x => x.Id)) +``` + +Ordering: + +```csharp +.OrderBySql( + (u, c) => c.Col(x => x.ClientCode).Asc(), + (u, c) => Sql.Count(c.Col(x => x.UserId)).Desc()) +``` + +Null ordering helpers are also available: + +- `NullsFirst()` +- `NullsLast()` + +Raw order fragments: + +```csharp +.OrderBySql(u => Sql.RawOrder("2 DESC")) +``` + +## Custom SQL Escape Hatches + +For cases not covered by built-in helpers: + +- `Sql.Raw(...)` +- `Sql.Func(...)` +- `OnRaw(...)` + +Examples: + +```csharp +Sql.Raw("ROW_NUMBER() OVER(ORDER BY u.\"id_user\")") +Sql.Func("CUSTOM_FUNC", u.Col(x => x.Code), Sql.Val(5)) +``` + +Use these when you need provider-specific or advanced SQL fragments, but keep normal query construction on typed helpers where possible. + +## Scoped Subqueries + +Two subquery helper families exist: + +- classic typed helper: + - `Sql.SubQuery(...)` + - `Sql.Exists(...)` +- scoped typed helper: + - `Sql.SubQueryScope(...)` + - `Sql.ExistsScope(...)` + +Use the scoped helpers when the subquery itself benefits from `FromTypedScope(...)`. + +Example: + +```csharp +.SelectSql(u => Sql.SubQueryScope( + db, + sq => sq + .Join(j => j.Left().As("c").OnSql((x, c) => + x.Col(a => a.Id).Eq(c.Col(a => a.UserId)))) + .Join(j => j.Left().As("r").OnSql((x, c, r) => + c.Col(a => a.UserId).Eq(r.Col(a => a.UserId)))) + .SelectSql((x, c, r) => r.Col(a => a.RoleName)), + "x").As("role_name")) +``` + +`ExistsScope(...)` works the same way, but returns a predicate. + +## Modify Builders + +Typed SQL DSL also exists for modify builders: + +- `InsertTyped()` +- `UpdateTyped()` +- `DeleteTyped()` + +Examples: + +```csharp +db.UpdateTyped() + .SetSql(u => u.Code, u => Sql.Coalesce(Sql.Val("900"), u.Col(x => x.Code))) + .WhereSql(u => u.Col(x => x.Id).Eq(1)); + +db.InsertTyped() + .InsertSql(u => u.Code, u => Sql.Val("901")); + +db.DeleteTyped() + .WhereSql(u => u.Col(x => x.Id).Eq(2)); +``` + +## Practical Guidance + +- prefer `FromTypedScope(...)` once a query has more than one or two joins +- use `OnSql(...)` instead of `OnRaw(...)` whenever mappings exist +- use `Sql.Func(...)` and `Sql.Raw(...)` sparingly as escape hatches +- use `SubQueryScope(...)` / `ExistsScope(...)` when the subquery itself is multi-join and typed +- keep the original dynamic fluent builder for cases where fully dynamic alias/member construction is still the better fit + +## Related Pages + +- [Fluent Builder API](fluent-builder-api.md) +- [Mapping and Entities](mapping-and-entities.md) +- [Test-Driven Examples](test-driven-examples.md)