Merge branch 'feature/typed-multitable-scope'
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
<Copyright>Copyright © RUSSEK Software 2012-2026</Copyright>
|
||||
<Company>RUSSEK Software</Company>
|
||||
<Authors>Grzegorz Russek</Authors>
|
||||
<VersionPrefix>1.9</VersionPrefix>
|
||||
<VersionPrefix>2.0</VersionPrefix>
|
||||
<Product>DynamORM</Product>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<Copyright>Copyright © RUSSEK Software 2012-2026</Copyright>
|
||||
<Company>RUSSEK Software</Company>
|
||||
<Authors>Grzegorz Russek</Authors>
|
||||
<VersionPrefix>1.8</VersionPrefix>
|
||||
<VersionPrefix>2.0</VersionPrefix>
|
||||
<RepositoryUrl>https://git.dr4cul4.pl/RUSSEK-Software/DynamORM</RepositoryUrl>
|
||||
<PackageProjectUrl>https://dr4cul4.pl</PackageProjectUrl>
|
||||
<Product>DynamORM</Product>
|
||||
|
||||
42
DynamORM.Tests/Helpers/TypedFluentUser.cs
Normal file
42
DynamORM.Tests/Helpers/TypedFluentUser.cs
Normal file
@@ -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; }
|
||||
}
|
||||
}
|
||||
33
DynamORM.Tests/Helpers/TypedJoinModels.cs
Normal file
33
DynamORM.Tests/Helpers/TypedJoinModels.cs
Normal file
@@ -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; }
|
||||
}
|
||||
}
|
||||
49
DynamORM.Tests/Helpers/TypedMultiJoinModels.cs
Normal file
49
DynamORM.Tests/Helpers/TypedMultiJoinModels.cs
Normal file
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ namespace DynamORM.Tests.Modify
|
||||
/// Tests the basic insert.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInsertBasic()
|
||||
public void TestTypedInsertBasic()
|
||||
{
|
||||
IDynamicInsertQueryBuilder cmd = new DynamicInsertQueryBuilder(Database, "Users");
|
||||
|
||||
|
||||
73
DynamORM.Tests/Modify/TypedModifyExtensionsTests.cs
Normal file
73
DynamORM.Tests/Modify/TypedModifyExtensionsTests.cs
Normal file
@@ -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<Users>()
|
||||
.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<Users>()
|
||||
.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<Users>()
|
||||
.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());
|
||||
}
|
||||
}
|
||||
}
|
||||
224
DynamORM.Tests/Modify/TypedParserTests.cs
Normal file
224
DynamORM.Tests/Modify/TypedParserTests.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>New parser tests.</summary>
|
||||
[TestFixture]
|
||||
public class TypedParserTests : TestsBase
|
||||
{
|
||||
/// <summary>Setup test parameters.</summary>
|
||||
[SetUp]
|
||||
public virtual void SetUp()
|
||||
{
|
||||
CreateTestDatabase();
|
||||
CreateDynamicDatabase(
|
||||
DynamicDatabaseOptions.SingleConnection |
|
||||
DynamicDatabaseOptions.SingleTransaction |
|
||||
DynamicDatabaseOptions.SupportLimitOffset);
|
||||
}
|
||||
|
||||
/// <summary>Tear down test objects.</summary>
|
||||
[TearDown]
|
||||
public virtual void TearDown()
|
||||
{
|
||||
DestroyDynamicDatabase();
|
||||
DestroyTestDatabase();
|
||||
}
|
||||
|
||||
#region Insert
|
||||
|
||||
/// <summary>
|
||||
/// Tests the basic insert.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTypedInsertBasic()
|
||||
{
|
||||
var cmd = new DynamicTypedInsertQueryBuilder<Users>(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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the insert with sub query.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInsertSubQuery()
|
||||
{
|
||||
var cmd = new DynamicTypedInsertQueryBuilder<Users>(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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the basic insert using object.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInsertBasicObject()
|
||||
{
|
||||
var cmd = new DynamicTypedInsertQueryBuilder<Users>(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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the insert using object with sub query.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInsertSubQueryObject()
|
||||
{
|
||||
var cmd = new DynamicTypedInsertQueryBuilder<Users>(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
|
||||
|
||||
/// <summary>
|
||||
/// Tests the basic update.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestUpdateBasicSet()
|
||||
{
|
||||
var cmd = new DynamicTypedUpdateQueryBuilder<Users>(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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the basic update.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestUpdateBasicValues()
|
||||
{
|
||||
var cmd = new DynamicTypedUpdateQueryBuilder<Users>(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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the insert with sub query.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestUpdateSubQuery()
|
||||
{
|
||||
var cmd = new DynamicTypedUpdateQueryBuilder<Users>(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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the basic insert using object.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestUpdateBasicObject()
|
||||
{
|
||||
var cmd = new DynamicTypedUpdateQueryBuilder<Users>(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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the basic insert using object.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestUpdateSubQueryObject()
|
||||
{
|
||||
var cmd = new DynamicTypedUpdateQueryBuilder<Users>(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
|
||||
}
|
||||
}
|
||||
142
DynamORM.Tests/Select/TypedFluentBuilderTests.cs
Normal file
142
DynamORM.Tests/Select/TypedFluentBuilderTests.cs
Normal file
@@ -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<TypedFluentUser>("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<TypedFluentUser>("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<TypedFluentUser>("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<TypedFluentUser>("u")
|
||||
.Join<TypedFluentUser>(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<TypedFluentUser>("u")
|
||||
.Join<TypedFluentUser>(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<TypedFluentUser>("u")
|
||||
.Join<TypedFluentUser>(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<TypedFluentUser>("u")
|
||||
.Join<TypedFluentUser>(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
102
DynamORM.Tests/Select/TypedFluentJoinSyntaxTests.cs
Normal file
102
DynamORM.Tests/Select/TypedFluentJoinSyntaxTests.cs
Normal file
@@ -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<TypedJoinUser>("usr")
|
||||
.Join<TypedJoinUserClient>(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<TypedJoinUser>("usr")
|
||||
.Join<TypedJoinUserClient>(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<TypedJoinUser>("usr", noLock: true)
|
||||
.Join<TypedJoinUserClient>(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<TypedJoinUser>("usr")
|
||||
.Join<TypedJoinUserClient>(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<TypedJoinUser>("usr")
|
||||
.Join<TypedJoinUserClient>(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<TypedJoinUser>("usr")
|
||||
.Join<TypedJoinUserClient>(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<TypedJoinUser>("usr")
|
||||
.Join<TypedJoinUserClient>(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
860
DynamORM.Tests/Select/TypedParserTests.cs
Normal file
860
DynamORM.Tests/Select/TypedParserTests.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// New parser tests.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class TypedParserTests : TestsBase
|
||||
{
|
||||
/// <summary>Setup test parameters.</summary>
|
||||
[SetUp]
|
||||
public virtual void SetUp()
|
||||
{
|
||||
CreateTestDatabase();
|
||||
CreateDynamicDatabase(
|
||||
DynamicDatabaseOptions.SingleConnection |
|
||||
DynamicDatabaseOptions.SingleTransaction |
|
||||
DynamicDatabaseOptions.SupportLimitOffset |
|
||||
DynamicDatabaseOptions.SupportNoLock);
|
||||
}
|
||||
|
||||
/// <summary>Tear down test objects.</summary>
|
||||
[TearDown]
|
||||
public virtual void TearDown()
|
||||
{
|
||||
try
|
||||
{
|
||||
DestroyDynamicDatabase();
|
||||
DestroyTestDatabase();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests from typed method.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestFromGetTyped()
|
||||
{
|
||||
var cmd = Database.From<Users>();
|
||||
|
||||
Assert.AreEqual("SELECT * FROM \"sample_users\"", cmd.CommandText());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests from typed method.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestFromGetTypedAs()
|
||||
{
|
||||
var cmd = Database.From<Users>("u");
|
||||
|
||||
Assert.AreEqual("SELECT * FROM \"sample_users\" AS u", cmd.CommandText());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests from method using invoke with sub query.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests where method with alias.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests where method with alias.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests complex where method with alias.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests where method with alias using in.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests where method with alias using between.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests where method with alias using between.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests where method without alias.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests where method with full column name.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests simple join method.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests inner join method.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests inner join method with aliases mix.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests from method using invoke with sub query.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests from method using invoke with sub query.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests from method using invoke with sub query an no lock.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests inner join method with no lock.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests left outer join method.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests left join method.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests right outer join method.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests right join method.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests complex join with parameters.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select all.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select all.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select field.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select field.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select field with alias.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select field with alias.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select field with alias.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select field with alias.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select aggregate field with alias (Sum).
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select aggregate field with alias (Coalesce).
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select aggregate field with alias (Sum).
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select aggregate field with alias (Sum).
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select aggregate field with alias (Sum).
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select from anonymous type.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select escaped case.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select escaped case.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select escaped case.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select escaped case.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select escaped case.
|
||||
/// </summary>
|
||||
[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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select escaped case.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests select escaped case with sub query.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests group by.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests order by.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests order by using string with number.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests order by using member with number.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests order by using member with field.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests sub query select.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests sub query where.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests sub query in.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests sub query join.
|
||||
/// </summary>
|
||||
[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());
|
||||
}
|
||||
}
|
||||
}
|
||||
502
DynamORM.Tests/TypedSql/TypedSqlDslTests.cs
Normal file
502
DynamORM.Tests/TypedSql/TypedSqlDslTests.cs
Normal file
@@ -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<TypedFluentUser>("u")
|
||||
.SelectSql(
|
||||
u => Sql.Count().As("cnt"),
|
||||
u => Sql.Coalesce<string>(u.Col(x => x.Code), Sql.Val("N/A")).As("code_value"))
|
||||
.GroupBySql(u => Sql.Coalesce<string>(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<TypedFluentUser>("u")
|
||||
.SelectSql(u => Sql.Case<string>()
|
||||
.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<TypedFluentUser>("u")
|
||||
.Join<TypedFluentUser>(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<Users>()
|
||||
.SetSql(u => u.Code, u => Sql.Coalesce<string>(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<Users>()
|
||||
.InsertSql(u => u.Code, u => Sql.Coalesce<string>(Sql.Val("901"), Sql.Val("fallback")))
|
||||
.InsertSql(u => u.First, u => Sql.Case<string>().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<Users>()
|
||||
.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<TypedFluentUser>("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<TypedFluentUser>("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<TypedFluentUser>("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<TypedFluentUser>("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<TypedFluentUser>("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<TypedFluentUser>("u")
|
||||
.SelectSql(
|
||||
u => Sql.Sum<int>(u.Col(x => x.Id)).As("sum_id"),
|
||||
u => Sql.Avg<int>(u.Col(x => x.Id)).As("avg_id"),
|
||||
u => Sql.Min<int>(u.Col(x => x.Id)).As("min_id"),
|
||||
u => Sql.Max<int>(u.Col(x => x.Id)).As("max_id"),
|
||||
u => Sql.Abs<int>(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<string>(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<TypedFluentUser>("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<TypedFluentUser>("u")
|
||||
.SelectSql(u => Sql.Func<string>("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<TypedFluentUser>("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<TypedFluentUser>("x");
|
||||
var cmd = Database.FromTyped<TypedFluentUser>("u")
|
||||
.Join<TypedFluentUser>(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<TypedFluentUser>("x");
|
||||
var cmd = Database.FromTyped<TypedFluentUser>("u")
|
||||
.Join<TypedFluentUser>(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<TypedFluentUser>("u")
|
||||
.SelectSql(u => Sql.SubQuery<long>(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<TypedFluentUser>("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<TypedFluentUser>("u")
|
||||
.SelectSql(u => Sql.SubQuery<TypedFluentUser, long>(
|
||||
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<TypedFluentUser>("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<TypedFluentUser>("u")
|
||||
.WhereSql(u => Sql.Exists<TypedFluentUser>(
|
||||
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<Users>()
|
||||
.InsertSql(u => new
|
||||
{
|
||||
Code = Sql.SubQuery<string>(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<Users>()
|
||||
.SetSql(u => new
|
||||
{
|
||||
Code = Sql.SubQuery<string>(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<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
|
||||
.SelectSql<TypedJoinUserClient>(
|
||||
(u, c) => u.Col(x => x.IdUser).As("user_id"),
|
||||
(u, c) => c.Col(x => x.Users).As("client_users"));
|
||||
|
||||
Assert.AreEqual(
|
||||
"SELECT u.\"Id_User\" AS \"user_id\", c.\"Users\" AS \"client_users\" FROM \"dbo\".\"Users\" AS u LEFT JOIN \"dbo\".\"UserClients\" AS c ON (u.\"Id_User\" = c.\"User_Id\")",
|
||||
NormalizeSql(cmd.CommandText()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestWhereGroupHavingAndOrderBySupportPositionalJoinedContexts()
|
||||
{
|
||||
var cmd = Database.FromTyped<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(j => j.Inner().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
|
||||
.SelectSql<TypedJoinUserClient>(
|
||||
(u, c) => u.Col(x => x.IdUser),
|
||||
(u, c) => Sql.Count(c.Col(x => x.UserId)).As("cnt"))
|
||||
.WhereSql<TypedJoinUserClient>((u, c) => u.Col(x => x.Active).Eq(1).And(c.Col(x => x.Deleted).Eq(0)))
|
||||
.GroupBySql<TypedJoinUserClient>(
|
||||
(u, c) => u.Col(x => x.IdUser),
|
||||
(u, c) => c.Col(x => x.Users))
|
||||
.HavingSql<TypedJoinUserClient>((u, c) => Sql.Count(c.Col(x => x.UserId)).Gt(0))
|
||||
.OrderBySql<TypedJoinUserClient>(
|
||||
(u, c) => c.Col(x => x.Users).Asc(),
|
||||
(u, c) => Sql.Count(c.Col(x => x.UserId)).Desc());
|
||||
|
||||
Assert.AreEqual(
|
||||
"SELECT u.\"Id_User\", COUNT(c.\"User_Id\") AS \"cnt\" FROM \"dbo\".\"Users\" AS u INNER JOIN \"dbo\".\"UserClients\" AS c ON (u.\"Id_User\" = c.\"User_Id\") WHERE ((u.\"Active\" = [$0]) AND (c.\"Deleted\" = [$1])) GROUP BY u.\"Id_User\", c.\"Users\" HAVING (COUNT(c.\"User_Id\") > [$2]) ORDER BY c.\"Users\" ASC, COUNT(c.\"User_Id\") DESC",
|
||||
NormalizeSql(cmd.CommandText()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPositionalJoinedContextsSupportThreeJoins()
|
||||
{
|
||||
var cmd = Database.FromTyped<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
|
||||
.Join<TypedJoinUserRole>(j => j.Left().As("r").OnSql((u, r) => u.Col(x => x.IdUser).Eq(r.Col(x => x.UserId))))
|
||||
.Join<TypedJoinUserRegion>(j => j.Left().As("g").OnSql((u, g) => u.Col(x => x.IdUser).Eq(g.Col(x => x.UserId))))
|
||||
.SelectSql<TypedJoinUserClient, TypedJoinUserRole, TypedJoinUserRegion>(
|
||||
(u, c, r, g) => u.Col(x => x.IdUser),
|
||||
(u, c, r, g) => c.Col(x => x.Users).As("client_users"),
|
||||
(u, c, r, g) => r.Col(x => x.RoleName).As("role_name"),
|
||||
(u, c, r, g) => g.Col(x => x.RegionCode).As("region_code"))
|
||||
.WhereSql<TypedJoinUserClient, TypedJoinUserRole, TypedJoinUserRegion>(
|
||||
(u, c, r, g) => c.Col(x => x.Deleted).Eq(0).And(r.Col(x => x.RoleId).Gt(0)).And(g.Col(x => x.RegionId).Gt(0)))
|
||||
.OrderBySql<TypedJoinUserClient, TypedJoinUserRole, TypedJoinUserRegion>(
|
||||
(u, c, r, g) => r.Col(x => x.RoleName).Asc(),
|
||||
(u, c, r, g) => g.Col(x => x.RegionCode).Desc());
|
||||
|
||||
Assert.AreEqual(
|
||||
"SELECT u.\"Id_User\", c.\"Users\" AS \"client_users\", r.\"Role_Name\" AS \"role_name\", g.\"Region_Code\" AS \"region_code\" FROM \"dbo\".\"Users\" AS u LEFT JOIN \"dbo\".\"UserClients\" AS c ON (u.\"Id_User\" = c.\"User_Id\") LEFT JOIN \"dbo\".\"UserRoles\" AS r ON (u.\"Id_User\" = r.\"User_Id\") LEFT JOIN \"dbo\".\"UserRegions\" AS g ON (u.\"Id_User\" = g.\"User_Id\") WHERE (((c.\"Deleted\" = [$0]) AND (r.\"Role_Id\" > [$1])) AND (g.\"Region_Id\" > [$2])) ORDER BY r.\"Role_Name\" ASC, g.\"Region_Code\" DESC",
|
||||
NormalizeSql(cmd.CommandText()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPositionalJoinedContextsSupportFourJoinedTables()
|
||||
{
|
||||
var cmd = Database.FromTyped<TypedFluentUser>("u")
|
||||
.Join<TypedFluentUser>(j => j.Left().As("b").OnSql((u, b) => u.Col(x => x.Id).Eq(b.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.Id).Eq(c.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("d").OnSql((u, d) => u.Col(x => x.Id).Eq(d.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("e").OnSql((u, e) => u.Col(x => x.Id).Eq(e.Col(x => x.Id))))
|
||||
.SelectSql<TypedFluentUser, TypedFluentUser, TypedFluentUser, TypedFluentUser>(
|
||||
(u, b, c, d, e) => u.Col(x => x.Id).As("root_id"),
|
||||
(u, b, c, d, e) => b.Col(x => x.Code).As("b_code"),
|
||||
(u, b, c, d, e) => c.Col(x => x.Code).As("c_code"),
|
||||
(u, b, c, d, e) => d.Col(x => x.Code).As("d_code"),
|
||||
(u, b, c, d, e) => e.Col(x => x.Code).As("e_code"))
|
||||
.WhereSql<TypedFluentUser, TypedFluentUser, TypedFluentUser, TypedFluentUser>(
|
||||
(u, b, c, d, e) => b.Col(x => x.Code).IsNotNull()
|
||||
.And(c.Col(x => x.Code).IsNotNull())
|
||||
.And(d.Col(x => x.Code).IsNotNull())
|
||||
.And(e.Col(x => x.Code).IsNotNull()));
|
||||
|
||||
Assert.AreEqual(
|
||||
"SELECT u.\"id_user\" AS \"root_id\", b.\"user_code\" AS \"b_code\", c.\"user_code\" AS \"c_code\", d.\"user_code\" AS \"d_code\", e.\"user_code\" AS \"e_code\" FROM \"sample_users\" AS u LEFT JOIN \"sample_users\" AS b ON (u.\"id_user\" = b.\"id_user\") LEFT JOIN \"sample_users\" AS c ON (u.\"id_user\" = c.\"id_user\") LEFT JOIN \"sample_users\" AS d ON (u.\"id_user\" = d.\"id_user\") LEFT JOIN \"sample_users\" AS e ON (u.\"id_user\" = e.\"id_user\") WHERE ((((b.\"user_code\" IS NOT NULL) AND (c.\"user_code\" IS NOT NULL)) AND (d.\"user_code\" IS NOT NULL)) AND (e.\"user_code\" IS NOT NULL))",
|
||||
NormalizeSql(cmd.CommandText()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPositionalJoinedContextsValidateRequestedType()
|
||||
{
|
||||
var builder = Database.FromTyped<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))));
|
||||
|
||||
var ex = Assert.Throws<System.InvalidOperationException>(() =>
|
||||
builder.SelectSql<TypedJoinUserRole>((u, r) => r.Col(x => x.RoleId).As("role_id")));
|
||||
|
||||
Assert.AreEqual(
|
||||
"Typed join context at position 1 is DynamORM.Tests.Helpers.TypedJoinUserClient, not DynamORM.Tests.Helpers.TypedJoinUserRole.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPositionalJoinedContextsValidateRequestedPosition()
|
||||
{
|
||||
var builder = Database.FromTyped<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))));
|
||||
|
||||
var ex = Assert.Throws<System.InvalidOperationException>(() =>
|
||||
builder.SelectSql<TypedJoinUserClient, TypedJoinUserRole>((u, c, r) => r.Col(x => x.RoleId).As("role_id")));
|
||||
|
||||
Assert.AreEqual(
|
||||
"Typed join context at position 2 is not available.",
|
||||
ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
214
DynamORM.Tests/TypedSql/TypedSqlScopeDslTests.cs
Normal file
214
DynamORM.Tests/TypedSql/TypedSqlScopeDslTests.cs
Normal file
@@ -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<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(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<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
|
||||
.Join<TypedJoinUserRole>(j => j.Left().As("r").OnSql((u, 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<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(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<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
|
||||
.Join<TypedJoinUserRole>(j => j.Left().As("r").OnSql((u, c, r) => u.Col(x => x.IdUser).Eq(r.Col(x => x.UserId))))
|
||||
.Join<TypedJoinUserRegion>(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<TypedJoinUser>("u")
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((u, c) => u.Col(x => x.IdUser).Eq(c.Col(x => x.UserId))))
|
||||
.Join<TypedJoinUserRole>(j => j.Left().As("r").OnSql((u, c, r) => c.Col(x => x.UserId).Eq(r.Col(x => x.UserId))))
|
||||
.Join<TypedJoinUserRegion>(j => j.Left().As("g").OnSql((u, c, r, g) => r.Col(x => x.UserId).Eq(g.Col(x => x.UserId))))
|
||||
.Join<TypedJoinUserDepartment>(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<TypedFluentUser>("a")
|
||||
.Join<TypedFluentUser>(j => j.Left().As("b").OnSql((a, b) => a.Col(x => x.Id).Eq(b.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("c").OnSql((a, b, c) => b.Col(x => x.Id).Eq(c.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("d").OnSql((a, b, c, d) => c.Col(x => x.Id).Eq(d.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("e").OnSql((a, b, c, d, e) => d.Col(x => x.Id).Eq(e.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("f").OnSql((a, b, c, d, e, f) => e.Col(x => x.Id).Eq(f.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>("a")
|
||||
.Join<TypedFluentUser>(j => j.Left().As("b").OnSql((a, b) => a.Col(x => x.Id).Eq(b.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("c").OnSql((a, b, c) => b.Col(x => x.Id).Eq(c.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("d").OnSql((a, b, c, d) => c.Col(x => x.Id).Eq(d.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("e").OnSql((a, b, c, d, e) => d.Col(x => x.Id).Eq(e.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(j => j.Left().As("f").OnSql((a, b, c, d, e, f) => e.Col(x => x.Id).Eq(f.Col(x => x.Id))))
|
||||
.Join<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>(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<TypedFluentUser>("u")
|
||||
.SelectSql(u => Sql.SubQueryScope<TypedJoinUser, string>(
|
||||
Database,
|
||||
sq => sq
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((x, c) => x.Col(a => a.IdUser).Eq(c.Col(a => a.UserId))))
|
||||
.Join<TypedJoinUserRole>(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<TypedFluentUser>("u")
|
||||
.WhereSql(u => Sql.ExistsScope<TypedJoinUser>(
|
||||
Database,
|
||||
sq => sq
|
||||
.Join<TypedJoinUserClient>(j => j.Left().As("c").OnSql((x, c) => x.Col(a => a.IdUser).Eq(c.Col(a => a.UserId))))
|
||||
.Join<TypedJoinUserRole>(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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
21
DynamORM/Builders/DynamicJoinType.cs
Normal file
21
DynamORM/Builders/DynamicJoinType.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Typed join kind used by typed fluent builder APIs.</summary>
|
||||
public enum DynamicJoinType
|
||||
{
|
||||
Inner = 0,
|
||||
Join,
|
||||
Left,
|
||||
Right,
|
||||
Full,
|
||||
LeftOuter,
|
||||
RightOuter,
|
||||
FullOuter
|
||||
}
|
||||
}
|
||||
25
DynamORM/Builders/IDynamicTypedDeleteQueryBuilder.cs
Normal file
25
DynamORM/Builders/IDynamicTypedDeleteQueryBuilder.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Typed delete query builder for mapped entities.</summary>
|
||||
/// <typeparam name="T">Mapped entity type.</typeparam>
|
||||
public interface IDynamicTypedDeleteQueryBuilder<T> : IDynamicDeleteQueryBuilder
|
||||
{
|
||||
/// <summary>Add typed where predicate using mapped properties.</summary>
|
||||
/// <param name="predicate">Predicate to parse.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedDeleteQueryBuilder<T> Where(Expression<Func<T, bool>> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL where predicate.</summary>
|
||||
IDynamicTypedDeleteQueryBuilder<T> WhereSql(Func<TypedTableContext<T>, TypedSqlPredicate> predicate);
|
||||
}
|
||||
}
|
||||
35
DynamORM/Builders/IDynamicTypedInsertQueryBuilder.cs
Normal file
35
DynamORM/Builders/IDynamicTypedInsertQueryBuilder.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Typed insert query builder for mapped entities.</summary>
|
||||
/// <typeparam name="T">Mapped entity type.</typeparam>
|
||||
public interface IDynamicTypedInsertQueryBuilder<T> : IDynamicInsertQueryBuilder
|
||||
{
|
||||
/// <summary>Add typed insert assignment using mapped property selector.</summary>
|
||||
/// <typeparam name="TValue">Property type.</typeparam>
|
||||
/// <param name="selector">Property selector.</param>
|
||||
/// <param name="value">Value to insert.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedInsertQueryBuilder<T> Insert<TValue>(Expression<Func<T, TValue>> selector, object value);
|
||||
|
||||
/// <summary>Add values from mapped object.</summary>
|
||||
/// <param name="value">Mapped object value.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedInsertQueryBuilder<T> Insert(T value);
|
||||
|
||||
/// <summary>Add typed SQL DSL insert assignment.</summary>
|
||||
IDynamicTypedInsertQueryBuilder<T> InsertSql<TValue>(Expression<Func<T, TValue>> selector, Func<TypedTableContext<T>, TypedSqlExpression> valueFactory);
|
||||
|
||||
/// <summary>Add typed SQL DSL insert assignments from object projection.</summary>
|
||||
IDynamicTypedInsertQueryBuilder<T> InsertSql(Func<TypedTableContext<T>, object> values);
|
||||
}
|
||||
}
|
||||
169
DynamORM/Builders/IDynamicTypedSelectQueryBuilder.cs
Normal file
169
DynamORM/Builders/IDynamicTypedSelectQueryBuilder.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Typed select query builder for mapped entities.</summary>
|
||||
/// <typeparam name="T">Mapped entity type.</typeparam>
|
||||
public interface IDynamicTypedSelectQueryBuilder<T> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
/// <summary>Add typed join to mapped table.</summary>
|
||||
/// <typeparam name="TRight">Joined mapped entity type.</typeparam>
|
||||
/// <param name="on">Join ON predicate.</param>
|
||||
/// <param name="alias">Optional alias for joined table.</param>
|
||||
/// <param name="joinType">Join type.</param>
|
||||
/// <param name="noLock">Adds NOLOCK hint to joined source when supported by provider options.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedSelectQueryBuilder<T> Join<TRight>(Expression<Func<T, TRight, bool>> on, string alias = null, DynamicJoinType joinType = DynamicJoinType.Inner, bool noLock = false);
|
||||
|
||||
/// <summary>Add typed join with custom join type text (for example: CROSS APPLY).</summary>
|
||||
/// <typeparam name="TRight">Joined mapped entity type.</typeparam>
|
||||
/// <param name="on">Optional join ON predicate.</param>
|
||||
/// <param name="alias">Optional alias for joined table.</param>
|
||||
/// <param name="joinType">Join type text.</param>
|
||||
/// <param name="noLock">Adds NOLOCK hint to joined source when supported by provider options.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedSelectQueryBuilder<T> Join<TRight>(Expression<Func<T, TRight, bool>> on, string alias, string joinType, bool noLock = false);
|
||||
|
||||
/// <summary>Add typed join using join-spec builder syntax (<c>As()</c>, join kind and <c>On()</c>).</summary>
|
||||
/// <typeparam name="TRight">Joined mapped entity type.</typeparam>
|
||||
/// <param name="specification">Join specification builder callback.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedSelectQueryBuilder<T> Join<TRight>(Func<TypedJoinBuilder<T, TRight>, TypedJoinBuilder<T, TRight>> specification);
|
||||
|
||||
/// <summary>Add typed where predicate using mapped properties.</summary>
|
||||
/// <param name="predicate">Predicate to parse.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedSelectQueryBuilder<T> Where(Expression<Func<T, bool>> predicate);
|
||||
|
||||
/// <summary>Add typed having predicate using mapped properties.</summary>
|
||||
/// <param name="predicate">Predicate to parse.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedSelectQueryBuilder<T> Having(Expression<Func<T, bool>> predicate);
|
||||
|
||||
/// <summary>Add typed selected columns using mapped properties.</summary>
|
||||
/// <typeparam name="TResult">Projection type.</typeparam>
|
||||
/// <param name="selector">Selector to parse.</param>
|
||||
/// <param name="selectors">Additional selectors to parse.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedSelectQueryBuilder<T> Select<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors);
|
||||
|
||||
/// <summary>Add typed group by columns using mapped properties.</summary>
|
||||
/// <typeparam name="TResult">Projection type.</typeparam>
|
||||
/// <param name="selector">Selector to parse.</param>
|
||||
/// <param name="selectors">Additional selectors to parse.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedSelectQueryBuilder<T> GroupBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors);
|
||||
|
||||
/// <summary>Add typed order by columns using mapped properties. Supports <c>Asc()</c>/<c>Desc()</c>.</summary>
|
||||
/// <typeparam name="TResult">Projection type.</typeparam>
|
||||
/// <param name="selector">Selector to parse.</param>
|
||||
/// <param name="selectors">Additional selectors to parse.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedSelectQueryBuilder<T> OrderBy<TResult>(Expression<Func<T, TResult>> selector, params Expression<Func<T, TResult>>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL select items.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> SelectSql(Func<TypedTableContext<T>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedSqlSelectable>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL where predicate.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> WhereSql(Func<TypedTableContext<T>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL having predicate.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> HavingSql(Func<TypedTableContext<T>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL group by expressions.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> GroupBySql(Func<TypedTableContext<T>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedSqlExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL order by expressions.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> OrderBySql(Func<TypedTableContext<T>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedSqlOrderExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL select items using root and first joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlSelectable>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL select items using root and first two joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlSelectable>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL select items using root and first three joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlSelectable>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL select items using root and first four joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> SelectSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlSelectable>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL where predicate using root and first joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL where predicate using root and first two joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL where predicate using root and first three joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL where predicate using root and first four joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> WhereSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL having predicate using root and first joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL having predicate using root and first two joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL having predicate using root and first three joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL having predicate using root and first four joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> HavingSql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL group-by expression using root and first joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL group-by expression using root and first two joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL group-by expression using root and first three joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL group-by expression using root and first four joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> GroupBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL order-by expression using root and first joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedSqlOrderExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL order-by expression using root and first two joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedSqlOrderExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL order-by expression using root and first three joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedSqlOrderExpression>[] selectors);
|
||||
|
||||
/// <summary>Add typed SQL DSL order-by expression using root and first four joined table contexts.</summary>
|
||||
IDynamicTypedSelectQueryBuilder<T> OrderBySql<TJoin1, TJoin2, TJoin3, TJoin4>(Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T>, TypedTableContext<TJoin1>, TypedTableContext<TJoin2>, TypedTableContext<TJoin3>, TypedTableContext<TJoin4>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
}
|
||||
171
DynamORM/Builders/IDynamicTypedSelectScopeQueryBuilder.cs
Normal file
171
DynamORM/Builders/IDynamicTypedSelectScopeQueryBuilder.cs
Normal file
@@ -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<T1> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, TJoin2> Join<TJoin2>(Func<TypedScopeJoinBuilder<T1, TJoin2>, TypedScopeJoinBuilder<T1, TJoin2>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1> SelectSql(Func<TypedTableContext<T1>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1> WhereSql(Func<TypedTableContext<T1>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1> HavingSql(Func<TypedTableContext<T1>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1> GroupBySql(Func<TypedTableContext<T1>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1> OrderBySql(Func<TypedTableContext<T1>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, TJoin3> Join<TJoin3>(Func<TypedScopeJoinBuilder<T1, T2, TJoin3>, TypedScopeJoinBuilder<T1, T2, TJoin3>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, TJoin4> Join<TJoin4>(Func<TypedScopeJoinBuilder<T1, T2, T3, TJoin4>, TypedScopeJoinBuilder<T1, T2, T3, TJoin4>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, TJoin5> Join<TJoin5>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, TJoin5>, TypedScopeJoinBuilder<T1, T2, T3, T4, TJoin5>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, TJoin6> Join<TJoin6>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, TJoin6>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, TJoin6>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, TJoin7> Join<TJoin7>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, TJoin7>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, TJoin7>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, TJoin8> Join<TJoin8>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, TJoin8>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, TJoin8>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, TJoin9> Join<TJoin9>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, TJoin9>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, TJoin9>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, TJoin10> Join<TJoin10>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, TJoin10>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, TJoin10>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TJoin11> Join<TJoin11>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TJoin11>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TJoin11>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TJoin12> Join<TJoin12>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TJoin12>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TJoin12>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TJoin13> Join<TJoin13>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TJoin13>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TJoin13>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TJoin14> Join<TJoin14>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TJoin14>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TJoin14>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TJoin15> Join<TJoin15>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TJoin15>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TJoin15>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TJoin16> Join<TJoin16>(Func<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TJoin16>, TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TJoin16>> specification);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
public interface IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> : IDynamicSelectQueryBuilder
|
||||
{
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> SelectSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<T16>, TypedSqlSelectable> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<T16>, TypedSqlSelectable>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> WhereSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<T16>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> HavingSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<T16>, TypedSqlPredicate> predicate);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> GroupBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<T16>, TypedSqlExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<T16>, TypedSqlExpression>[] selectors);
|
||||
IDynamicTypedSelectScopeQueryBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> OrderBySql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<T16>, TypedSqlOrderExpression> selector, params Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<T16>, TypedSqlOrderExpression>[] selectors);
|
||||
}
|
||||
|
||||
}
|
||||
43
DynamORM/Builders/IDynamicTypedUpdateQueryBuilder.cs
Normal file
43
DynamORM/Builders/IDynamicTypedUpdateQueryBuilder.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Typed update query builder for mapped entities.</summary>
|
||||
/// <typeparam name="T">Mapped entity type.</typeparam>
|
||||
public interface IDynamicTypedUpdateQueryBuilder<T> : IDynamicUpdateQueryBuilder
|
||||
{
|
||||
/// <summary>Add typed where predicate using mapped properties.</summary>
|
||||
/// <param name="predicate">Predicate to parse.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedUpdateQueryBuilder<T> Where(Expression<Func<T, bool>> predicate);
|
||||
|
||||
/// <summary>Add typed assignment using mapped property selector.</summary>
|
||||
/// <typeparam name="TValue">Property type.</typeparam>
|
||||
/// <param name="selector">Property selector.</param>
|
||||
/// <param name="value">Assigned value.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedUpdateQueryBuilder<T> Set<TValue>(Expression<Func<T, TValue>> selector, object value);
|
||||
|
||||
/// <summary>Add update values from mapped object.</summary>
|
||||
/// <param name="value">Mapped object value.</param>
|
||||
/// <returns>Builder instance.</returns>
|
||||
IDynamicTypedUpdateQueryBuilder<T> Values(T value);
|
||||
|
||||
/// <summary>Add typed SQL DSL where predicate.</summary>
|
||||
IDynamicTypedUpdateQueryBuilder<T> WhereSql(Func<TypedTableContext<T>, TypedSqlPredicate> predicate);
|
||||
|
||||
/// <summary>Add typed SQL DSL assignment.</summary>
|
||||
IDynamicTypedUpdateQueryBuilder<T> SetSql<TValue>(Expression<Func<T, TValue>> selector, Func<TypedTableContext<T>, TypedSqlExpression> valueFactory);
|
||||
|
||||
/// <summary>Add typed SQL DSL assignments from object projection.</summary>
|
||||
IDynamicTypedUpdateQueryBuilder<T> SetSql(Func<TypedTableContext<T>, object> values);
|
||||
}
|
||||
}
|
||||
@@ -40,8 +40,8 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <summary>Implementation of dynamic insert query builder.</summary>
|
||||
internal class DynamicInsertQueryBuilder : DynamicModifyBuilder, IDynamicInsertQueryBuilder
|
||||
{
|
||||
private string _columns;
|
||||
private string _values;
|
||||
protected string _columns;
|
||||
protected string _values;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DynamicInsertQueryBuilder"/> class.
|
||||
@@ -221,4 +221,4 @@ namespace DynamORM.Builders.Implementation
|
||||
|
||||
#endregion IExtendedDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,17 +42,17 @@ using DynamORM.Mapper;
|
||||
namespace DynamORM.Builders.Implementation
|
||||
{
|
||||
/// <summary>Implementation of dynamic select query builder.</summary>
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>Typed wrapper over <see cref="DynamicDeleteQueryBuilder"/> with property-to-column translation.</summary>
|
||||
/// <typeparam name="T">Mapped entity type.</typeparam>
|
||||
internal class DynamicTypedDeleteQueryBuilder<T> : DynamicDeleteQueryBuilder, IDynamicTypedDeleteQueryBuilder<T>
|
||||
{
|
||||
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<T> Where(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
TypedModifyHelper.ApplyWhere<T>((c, o, v) => base.Where(c, o, v), predicate);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IDynamicTypedDeleteQueryBuilder<T> WhereSql(Func<TypedTableContext<T>, 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<T> Where(Func<dynamic, object> func)
|
||||
{
|
||||
base.Where(func);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedDeleteQueryBuilder<T> Where(DynamicColumn column)
|
||||
{
|
||||
base.Where(column);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedDeleteQueryBuilder<T> Where(string column, DynamicColumn.CompareOperator op, object value)
|
||||
{
|
||||
base.Where(column, op, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedDeleteQueryBuilder<T> Where(string column, object value)
|
||||
{
|
||||
base.Where(column, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedDeleteQueryBuilder<T> 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<string, IParameter> item in query.Parameters)
|
||||
if (!Parameters.ContainsKey(item.Key))
|
||||
Parameters.Add(item.Key, item.Value);
|
||||
|
||||
return query.CommandText();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>Typed wrapper over <see cref="DynamicInsertQueryBuilder"/> with property-to-column translation.</summary>
|
||||
/// <typeparam name="T">Mapped entity type.</typeparam>
|
||||
internal class DynamicTypedInsertQueryBuilder<T> : DynamicInsertQueryBuilder, IDynamicTypedInsertQueryBuilder<T>
|
||||
{
|
||||
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<T> Insert<TValue>(Expression<Func<T, TValue>> selector, object value)
|
||||
{
|
||||
base.Insert(TypedModifyHelper.GetMappedColumn(selector), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IDynamicTypedInsertQueryBuilder<T> Insert(T value)
|
||||
{
|
||||
base.Insert(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IDynamicTypedInsertQueryBuilder<T> InsertSql<TValue>(Expression<Func<T, TValue>> selector, Func<TypedTableContext<T>, 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<T> InsertSql(Func<TypedTableContext<T>, object> values)
|
||||
{
|
||||
if (values == null)
|
||||
throw new ArgumentNullException("values");
|
||||
|
||||
object data = values(new TypedTableContext<T>(null));
|
||||
foreach (KeyValuePair<string, object> item in data.ToDictionary())
|
||||
{
|
||||
string column = FixObjectName(TypedModifyHelper.GetMappedColumnByName(typeof(T), item.Key), onlyColumn: true);
|
||||
string value = (item.Value as TypedSqlExpression) != null
|
||||
? TypedModifyHelper.RenderExpression<T>(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<T> Values(Func<dynamic, object> fn, params Func<dynamic, object>[] func)
|
||||
{
|
||||
base.Values(fn, func);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedInsertQueryBuilder<T> Insert(string column, object value)
|
||||
{
|
||||
base.Insert(column, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedInsertQueryBuilder<T> 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<string, IParameter> item in query.Parameters)
|
||||
if (!Parameters.ContainsKey(item.Key))
|
||||
Parameters.Add(item.Key, item.Value);
|
||||
|
||||
return query.CommandText();
|
||||
}
|
||||
}
|
||||
}
|
||||
1204
DynamORM/Builders/Implementation/DynamicTypedSelectQueryBuilder.cs
Normal file
1204
DynamORM/Builders/Implementation/DynamicTypedSelectQueryBuilder.cs
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
{
|
||||
/// <summary>Typed wrapper over <see cref="DynamicUpdateQueryBuilder"/> with property-to-column translation.</summary>
|
||||
/// <typeparam name="T">Mapped entity type.</typeparam>
|
||||
internal class DynamicTypedUpdateQueryBuilder<T> : DynamicUpdateQueryBuilder, IDynamicTypedUpdateQueryBuilder<T>
|
||||
{
|
||||
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<T> Where(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
TypedModifyHelper.ApplyWhere<T>((c, o, v) => base.Where(c, o, v), predicate);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IDynamicTypedUpdateQueryBuilder<T> Set<TValue>(Expression<Func<T, TValue>> selector, object value)
|
||||
{
|
||||
base.Values(TypedModifyHelper.GetMappedColumn(selector), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IDynamicTypedUpdateQueryBuilder<T> Values(T value)
|
||||
{
|
||||
base.Values(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IDynamicTypedUpdateQueryBuilder<T> WhereSql(Func<TypedTableContext<T>, 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<T> SetSql<TValue>(Expression<Func<T, TValue>> selector, Func<TypedTableContext<T>, 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<T> SetSql(Func<TypedTableContext<T>, object> values)
|
||||
{
|
||||
if (values == null)
|
||||
throw new ArgumentNullException("values");
|
||||
|
||||
object data = values(new TypedTableContext<T>(null));
|
||||
foreach (KeyValuePair<string, object> item in data.ToDictionary())
|
||||
{
|
||||
string column = FixObjectName(TypedModifyHelper.GetMappedColumnByName(typeof(T), item.Key), onlyColumn: true);
|
||||
string value = (item.Value as TypedSqlExpression) != null
|
||||
? TypedModifyHelper.RenderExpression<T>(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<T> Update(string column, object value)
|
||||
{
|
||||
base.Update(column, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> Update(object conditions)
|
||||
{
|
||||
base.Update(conditions);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> Set(params Func<dynamic, object>[] func)
|
||||
{
|
||||
base.Set(func);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> Values(string column, object value)
|
||||
{
|
||||
base.Values(column, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> Values(object o)
|
||||
{
|
||||
base.Values(o);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> Where(Func<dynamic, object> func)
|
||||
{
|
||||
base.Where(func);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> Where(DynamicColumn column)
|
||||
{
|
||||
base.Where(column);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> Where(string column, DynamicColumn.CompareOperator op, object value)
|
||||
{
|
||||
base.Where(column, op, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> Where(string column, object value)
|
||||
{
|
||||
base.Where(column, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public new IDynamicTypedUpdateQueryBuilder<T> 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<string, IParameter> item in query.Parameters)
|
||||
if (!Parameters.ContainsKey(item.Key))
|
||||
Parameters.Add(item.Key, item.Value);
|
||||
|
||||
return query.CommandText();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace DynamORM.Builders.Implementation
|
||||
/// <summary>Update query builder.</summary>
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
200
DynamORM/Builders/Implementation/TypedModifyHelper.cs
Normal file
200
DynamORM/Builders/Implementation/TypedModifyHelper.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Helper methods for typed modify builders.</summary>
|
||||
internal static class TypedModifyHelper
|
||||
{
|
||||
private sealed class ModifyRenderContext : ITypedSqlRenderContext
|
||||
{
|
||||
private readonly Func<Type, string, string, Func<string, string>, string> _resolveColumn;
|
||||
private readonly Func<object, string> _renderValue;
|
||||
private readonly Func<string, string> _decorateName;
|
||||
private readonly Func<IDynamicSelectQueryBuilder, string> _renderSubQuery;
|
||||
|
||||
public ModifyRenderContext(Func<Type, string, string, Func<string, string>, string> resolveColumn, Func<object, string> renderValue, Func<string, string> decorateName, Func<IDynamicSelectQueryBuilder, string> 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<T, TValue>(Expression<Func<T, TValue>> selector)
|
||||
{
|
||||
if (selector == null)
|
||||
throw new ArgumentNullException("selector");
|
||||
|
||||
return GetMappedColumn(typeof(T), selector.Body);
|
||||
}
|
||||
|
||||
public static void ApplyWhere<T>(Action<string, DynamicColumn.CompareOperator, object> addCondition, Expression<Func<T, bool>> 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<T>(
|
||||
Func<TypedTableContext<T>, TypedSqlPredicate> predicate,
|
||||
string alias,
|
||||
Func<object, string> renderValue,
|
||||
Func<string, string> decorateName,
|
||||
Func<IDynamicSelectQueryBuilder, string> renderSubQuery)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
ModifyRenderContext context = new ModifyRenderContext(ResolveColumn, renderValue, decorateName, renderSubQuery);
|
||||
return predicate(new TypedTableContext<T>(alias)).Render(context);
|
||||
}
|
||||
|
||||
public static string RenderExpression<T>(
|
||||
Func<TypedTableContext<T>, TypedSqlExpression> expression,
|
||||
string alias,
|
||||
Func<object, string> renderValue,
|
||||
Func<string, string> decorateName,
|
||||
Func<IDynamicSelectQueryBuilder, string> renderSubQuery)
|
||||
{
|
||||
if (expression == null)
|
||||
throw new ArgumentNullException("expression");
|
||||
|
||||
ModifyRenderContext context = new ModifyRenderContext(ResolveColumn, renderValue, decorateName, renderSubQuery);
|
||||
return expression(new TypedTableContext<T>(alias)).Render(context);
|
||||
}
|
||||
|
||||
private static void ApplyWhereInternal(Type modelType, Action<string, DynamicColumn.CompareOperator, object> 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<string, string> 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<Func<object>>(objectMember).Compile();
|
||||
return getter();
|
||||
}
|
||||
}
|
||||
}
|
||||
52
DynamORM/Builders/TypedFluentExtensions.cs
Normal file
52
DynamORM/Builders/TypedFluentExtensions.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Marker extensions for typed fluent builder expressions.</summary>
|
||||
public static class TypedFluentExtensions
|
||||
{
|
||||
/// <summary>Marks select projection alias in typed expressions.</summary>
|
||||
public static T As<T>(this T source, string alias)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
/// <summary>Marks ascending order in typed order expressions.</summary>
|
||||
public static T Asc<T>(this T source)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
/// <summary>Marks descending order in typed order expressions.</summary>
|
||||
public static T Desc<T>(this T source)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
168
DynamORM/Builders/TypedJoinBuilder.cs
Normal file
168
DynamORM/Builders/TypedJoinBuilder.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Typed join specification builder used by typed fluent select queries.</summary>
|
||||
/// <typeparam name="TLeft">Left side mapped type.</typeparam>
|
||||
/// <typeparam name="TRight">Right side mapped type.</typeparam>
|
||||
public class TypedJoinBuilder<TLeft, TRight>
|
||||
{
|
||||
internal TypedJoinBuilder()
|
||||
{
|
||||
JoinType = DynamicJoinType.Join;
|
||||
}
|
||||
|
||||
/// <summary>Gets join alias.</summary>
|
||||
public string Alias { get; private set; }
|
||||
|
||||
/// <summary>Gets join type.</summary>
|
||||
public DynamicJoinType JoinType { get; private set; }
|
||||
|
||||
/// <summary>Gets custom join type text.</summary>
|
||||
public string CustomJoinType { get; private set; }
|
||||
|
||||
/// <summary>Gets a value indicating whether joined source should use NOLOCK.</summary>
|
||||
public bool UseNoLock { get; private set; }
|
||||
|
||||
/// <summary>Gets ON predicate.</summary>
|
||||
public Expression<Func<TLeft, TRight, bool>> OnPredicate { get; private set; }
|
||||
|
||||
/// <summary>Gets raw ON condition.</summary>
|
||||
public string OnRawCondition { get; private set; }
|
||||
|
||||
/// <summary>Gets typed SQL DSL ON specification.</summary>
|
||||
public Func<TypedTableContext<TLeft>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
|
||||
/// <summary>Sets join alias.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> As(string alias)
|
||||
{
|
||||
Alias = alias;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets INNER JOIN.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> Inner()
|
||||
{
|
||||
JoinType = DynamicJoinType.Inner;
|
||||
CustomJoinType = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets plain JOIN.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> Join()
|
||||
{
|
||||
JoinType = DynamicJoinType.Join;
|
||||
CustomJoinType = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets LEFT JOIN.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> Left()
|
||||
{
|
||||
JoinType = DynamicJoinType.Left;
|
||||
CustomJoinType = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets RIGHT JOIN.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> Right()
|
||||
{
|
||||
JoinType = DynamicJoinType.Right;
|
||||
CustomJoinType = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets FULL JOIN.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> Full()
|
||||
{
|
||||
JoinType = DynamicJoinType.Full;
|
||||
CustomJoinType = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets LEFT OUTER JOIN.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> LeftOuter()
|
||||
{
|
||||
JoinType = DynamicJoinType.LeftOuter;
|
||||
CustomJoinType = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets RIGHT OUTER JOIN.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> RightOuter()
|
||||
{
|
||||
JoinType = DynamicJoinType.RightOuter;
|
||||
CustomJoinType = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets FULL OUTER JOIN.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> FullOuter()
|
||||
{
|
||||
JoinType = DynamicJoinType.FullOuter;
|
||||
CustomJoinType = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets custom join type text (for example: CROSS APPLY).</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> Type(string joinType)
|
||||
{
|
||||
if (string.IsNullOrEmpty(joinType))
|
||||
throw new ArgumentNullException("joinType");
|
||||
|
||||
CustomJoinType = joinType.Trim();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Marks joined source with NOLOCK hint.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> NoLock(bool use = true)
|
||||
{
|
||||
UseNoLock = use;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets ON predicate.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> On(Expression<Func<TLeft, TRight, bool>> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
OnPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets raw ON clause (without the ON keyword).</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
|
||||
OnRawCondition = condition.Trim();
|
||||
OnPredicate = null;
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Sets typed SQL DSL ON predicate.</summary>
|
||||
public TypedJoinBuilder<TLeft, TRight> OnSql(Func<TypedTableContext<TLeft>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
OnSqlPredicate = predicate;
|
||||
OnPredicate = null;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
86
DynamORM/Builders/TypedJoinExtensions.cs
Normal file
86
DynamORM/Builders/TypedJoinExtensions.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Compatibility and convenience extensions for typed joins.</summary>
|
||||
public static class TypedJoinExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Legacy compatibility helper. Prefer <see cref="IDynamicTypedSelectQueryBuilder{T}.Join{TRight}"/>.
|
||||
/// </summary>
|
||||
public static IDynamicTypedSelectQueryBuilder<TLeft> JoinTyped<TLeft, TRight>(
|
||||
this IDynamicTypedSelectQueryBuilder<TLeft> builder,
|
||||
string alias,
|
||||
Expression<Func<TLeft, TRight, bool>> 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);
|
||||
}
|
||||
|
||||
/// <summary>Convenience typed INNER JOIN extension.</summary>
|
||||
public static IDynamicTypedSelectQueryBuilder<TLeft> InnerJoinTyped<TLeft, TRight>(
|
||||
this IDynamicTypedSelectQueryBuilder<TLeft> builder,
|
||||
Expression<Func<TLeft, TRight, bool>> on,
|
||||
string alias = null)
|
||||
{
|
||||
return builder.Join(on, alias, DynamicJoinType.Inner);
|
||||
}
|
||||
|
||||
/// <summary>Convenience typed LEFT JOIN extension.</summary>
|
||||
public static IDynamicTypedSelectQueryBuilder<TLeft> LeftJoinTyped<TLeft, TRight>(
|
||||
this IDynamicTypedSelectQueryBuilder<TLeft> builder,
|
||||
Expression<Func<TLeft, TRight, bool>> on,
|
||||
string alias = null)
|
||||
{
|
||||
return builder.Join(on, alias, DynamicJoinType.Left);
|
||||
}
|
||||
|
||||
/// <summary>Convenience typed RIGHT JOIN extension.</summary>
|
||||
public static IDynamicTypedSelectQueryBuilder<TLeft> RightJoinTyped<TLeft, TRight>(
|
||||
this IDynamicTypedSelectQueryBuilder<TLeft> builder,
|
||||
Expression<Func<TLeft, TRight, bool>> on,
|
||||
string alias = null)
|
||||
{
|
||||
return builder.Join(on, alias, DynamicJoinType.Right);
|
||||
}
|
||||
|
||||
/// <summary>Convenience typed FULL JOIN extension.</summary>
|
||||
public static IDynamicTypedSelectQueryBuilder<TLeft> FullJoinTyped<TLeft, TRight>(
|
||||
this IDynamicTypedSelectQueryBuilder<TLeft> builder,
|
||||
Expression<Func<TLeft, TRight, bool>> on,
|
||||
string alias = null)
|
||||
{
|
||||
return builder.Join(on, alias, DynamicJoinType.Full);
|
||||
}
|
||||
}
|
||||
}
|
||||
398
DynamORM/Builders/TypedScopeJoinBuilder.cs
Normal file
398
DynamORM/Builders/TypedScopeJoinBuilder.cs
Normal file
@@ -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<TSelf>
|
||||
where TSelf : TypedScopeJoinBuilderBase<TSelf>
|
||||
{
|
||||
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<T1, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRight> : TypedScopeJoinBuilderBase<TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRight>>
|
||||
{
|
||||
internal Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<TRight>, TypedSqlPredicate> OnSqlPredicate { get; private set; }
|
||||
internal string OnRawCondition { get; private set; }
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRight> OnSql(Func<TypedTableContext<T1>, TypedTableContext<T2>, TypedTableContext<T3>, TypedTableContext<T4>, TypedTableContext<T5>, TypedTableContext<T6>, TypedTableContext<T7>, TypedTableContext<T8>, TypedTableContext<T9>, TypedTableContext<T10>, TypedTableContext<T11>, TypedTableContext<T12>, TypedTableContext<T13>, TypedTableContext<T14>, TypedTableContext<T15>, TypedTableContext<TRight>, TypedSqlPredicate> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
OnSqlPredicate = predicate;
|
||||
OnRawCondition = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedScopeJoinBuilder<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRight> OnRaw(string condition)
|
||||
{
|
||||
if (string.IsNullOrEmpty(condition))
|
||||
throw new ArgumentNullException("condition");
|
||||
OnRawCondition = condition.Trim();
|
||||
OnSqlPredicate = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<Copyright>Copyright © RUSSEK Software 2012-2026</Copyright>
|
||||
<Company>RUSSEK Software</Company>
|
||||
<Authors>Grzegorz Russek</Authors>
|
||||
<VersionPrefix>1.9</VersionPrefix>
|
||||
<VersionPrefix>2.0</VersionPrefix>
|
||||
<RepositoryUrl>https://git.dr4cul4.pl/RUSSEK-Software/DynamORM</RepositoryUrl>
|
||||
<PackageProjectUrl>https://dr4cul4.pl</PackageProjectUrl>
|
||||
<Product>DynamORM</Product>
|
||||
|
||||
@@ -471,6 +471,46 @@ namespace DynamORM
|
||||
return new DynamicSelectQueryBuilder(this).From(x => x(typeof(T)).As(alias));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>FROM</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <typeparam name="T">Type which can be represented in database.</typeparam>
|
||||
/// <param name="alias">Table alias.</param>
|
||||
/// <param name="noLock">use no lock.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicTypedSelectQueryBuilder<T> FromTyped<T>(string alias = null, bool noLock = false)
|
||||
{
|
||||
// TODO: Make it more readable and maitainable
|
||||
DynamicTypedSelectQueryBuilder<T> builder = new DynamicTypedSelectQueryBuilder<T>(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;
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>FROM</code> clause using a typed scope builder with evolving join arity.</summary>
|
||||
/// <typeparam name="T">Type which can be represented in database.</typeparam>
|
||||
/// <param name="alias">Table alias.</param>
|
||||
/// <param name="noLock">use no lock.</param>
|
||||
/// <returns>Scope builder instance.</returns>
|
||||
public virtual IDynamicTypedSelectScopeQueryBuilder<T> FromTypedScope<T>(string alias = null, bool noLock = false)
|
||||
{
|
||||
DynamicTypedSelectQueryBuilder<T> builder = (DynamicTypedSelectQueryBuilder<T>)FromTyped<T>(alias, noLock);
|
||||
string resolvedAlias = string.IsNullOrEmpty(alias) ? builder.Tables[0].Alias ?? builder.Tables[0].Name : alias;
|
||||
return new DynamicTypedSelectScopeQueryBuilder<T>(builder, resolvedAlias);
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>FROM</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <param name="t">Type which can be represented in database.</param>
|
||||
@@ -503,6 +543,14 @@ namespace DynamORM
|
||||
{
|
||||
return new DynamicInsertQueryBuilder(this).Table(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>INSERT INTO</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <typeparam name="T">Type which can be represented in database.</typeparam>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicTypedInsertQueryBuilder<T> InsertTyped<T>()
|
||||
{
|
||||
return new DynamicTypedInsertQueryBuilder<T>(this, true);
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>INSERT INTO</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <param name="t">Type which can be represented in database.</param>
|
||||
@@ -611,6 +659,14 @@ namespace DynamORM
|
||||
return new DynamicUpdateQueryBuilder(this).Table(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>UPDATE</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <typeparam name="T">Type which can be represented in database.</typeparam>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicTypedUpdateQueryBuilder<T> UpdateTyped<T>()
|
||||
{
|
||||
return new DynamicTypedUpdateQueryBuilder<T>(this, true);
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>UPDATE</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <param name="t">Type which can be represented in database.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
@@ -832,6 +888,14 @@ namespace DynamORM
|
||||
return new DynamicDeleteQueryBuilder(this).Table(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>DELETE FROM</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <typeparam name="T">Type which can be represented in database.</typeparam>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
public virtual IDynamicTypedDeleteQueryBuilder<T> DeleteTyped<T>()
|
||||
{
|
||||
return new DynamicTypedDeleteQueryBuilder<T>(this, true);
|
||||
}
|
||||
|
||||
/// <summary>Adds to the <code>DELETE FROM</code> clause using <see cref="Type"/>.</summary>
|
||||
/// <param name="t">Type which can be represented in database.</param>
|
||||
/// <returns>This instance to permit chaining.</returns>
|
||||
@@ -2006,16 +2070,16 @@ namespace DynamORM
|
||||
|
||||
#region IExtendedDisposable Members
|
||||
|
||||
/// <summary>Performs application-defined tasks associated with freeing,
|
||||
/// releasing, or resetting unmanaged resources.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
return;
|
||||
|
||||
#if !DYNAMORM_OMMIT_OLDSYNTAX
|
||||
List<DynamicTable> tables = TablesCache.Values.ToList();
|
||||
TablesCache.Clear();
|
||||
/// <summary>Performs application-defined tasks associated with freeing,
|
||||
/// releasing, or resetting unmanaged resources.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
return;
|
||||
|
||||
#if !DYNAMORM_OMMIT_OLDSYNTAX
|
||||
List<DynamicTable> 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;
|
||||
}
|
||||
|
||||
/// <summary>Gets a value indicating whether this instance is disposed.</summary>
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
#endregion IExtendedDisposable Members
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
DynamORM/TypedSql/ITypedSqlRenderContext.cs
Normal file
26
DynamORM/TypedSql/ITypedSqlRenderContext.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Render context used by typed SQL DSL nodes.</summary>
|
||||
public interface ITypedSqlRenderContext
|
||||
{
|
||||
/// <summary>Resolve mapped column for given model member.</summary>
|
||||
string ResolveColumn(Type modelType, string memberName, string alias);
|
||||
|
||||
/// <summary>Render value as SQL parameter or literal fragment.</summary>
|
||||
string RenderValue(object value);
|
||||
|
||||
/// <summary>Decorate SQL identifier.</summary>
|
||||
string DecorateName(string name);
|
||||
|
||||
/// <summary>Render subquery SQL and merge any parameters into current context.</summary>
|
||||
string RenderSubQuery(Builders.IDynamicSelectQueryBuilder query);
|
||||
}
|
||||
}
|
||||
226
DynamORM/TypedSql/Sql.cs
Normal file
226
DynamORM/TypedSql/Sql.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Entry point for the typed SQL DSL.</summary>
|
||||
public static class Sql
|
||||
{
|
||||
/// <summary>Create parameterized value expression.</summary>
|
||||
public static TypedSqlExpression<T> Val<T>(T value)
|
||||
{
|
||||
return new TypedSqlValueExpression<T>(value);
|
||||
}
|
||||
|
||||
/// <summary>Create parameterized value expression.</summary>
|
||||
public static TypedSqlExpression<object> Val(object value)
|
||||
{
|
||||
return new TypedSqlValueExpression<object>(value);
|
||||
}
|
||||
|
||||
/// <summary>Create typed table context for an explicitly named alias, including joined aliases.</summary>
|
||||
public static TypedTableContext<T> Table<T>(string alias)
|
||||
{
|
||||
return new TypedTableContext<T>(alias);
|
||||
}
|
||||
|
||||
/// <summary>Create raw SQL expression.</summary>
|
||||
public static TypedSqlExpression<T> Raw<T>(string sql)
|
||||
{
|
||||
return new TypedSqlRawExpression<T>(sql);
|
||||
}
|
||||
|
||||
/// <summary>Create raw ORDER BY fragment.</summary>
|
||||
public static TypedSqlOrderExpression RawOrder(string sql)
|
||||
{
|
||||
return new TypedSqlRawOrderExpression(Raw<object>(sql));
|
||||
}
|
||||
|
||||
/// <summary>Create generic function call.</summary>
|
||||
public static TypedSqlExpression<T> Func<T>(string name, params TypedSqlExpression[] arguments)
|
||||
{
|
||||
return new TypedSqlFunctionExpression<T>(name, arguments);
|
||||
}
|
||||
|
||||
/// <summary>Create COUNT(*) expression.</summary>
|
||||
public static TypedSqlExpression<int> Count()
|
||||
{
|
||||
return Raw<int>("COUNT(*)");
|
||||
}
|
||||
|
||||
/// <summary>Create COUNT(expr) expression.</summary>
|
||||
public static TypedSqlExpression<int> Count(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<int>("COUNT", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create COALESCE expression.</summary>
|
||||
public static TypedSqlExpression<T> Coalesce<T>(params TypedSqlExpression[] expressions)
|
||||
{
|
||||
return Func<T>("COALESCE", expressions);
|
||||
}
|
||||
|
||||
/// <summary>Create SUM expression.</summary>
|
||||
public static TypedSqlExpression<T> Sum<T>(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<T>("SUM", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create AVG expression.</summary>
|
||||
public static TypedSqlExpression<T> Avg<T>(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<T>("AVG", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create MIN expression.</summary>
|
||||
public static TypedSqlExpression<T> Min<T>(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<T>("MIN", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create MAX expression.</summary>
|
||||
public static TypedSqlExpression<T> Max<T>(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<T>("MAX", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create ABS expression.</summary>
|
||||
public static TypedSqlExpression<T> Abs<T>(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<T>("ABS", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create UPPER expression.</summary>
|
||||
public static TypedSqlExpression<string> Upper(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<string>("UPPER", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create LOWER expression.</summary>
|
||||
public static TypedSqlExpression<string> Lower(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<string>("LOWER", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create TRIM expression.</summary>
|
||||
public static TypedSqlExpression<string> Trim(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<string>("TRIM", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create LENGTH expression.</summary>
|
||||
public static TypedSqlExpression<int> Length(TypedSqlExpression expression)
|
||||
{
|
||||
return Func<int>("LENGTH", expression);
|
||||
}
|
||||
|
||||
/// <summary>Create NULLIF expression.</summary>
|
||||
public static TypedSqlExpression<T> NullIf<T>(TypedSqlExpression left, TypedSqlExpression right)
|
||||
{
|
||||
return Func<T>("NULLIF", left, right);
|
||||
}
|
||||
|
||||
/// <summary>Create CURRENT_TIMESTAMP expression.</summary>
|
||||
public static TypedSqlExpression<DateTime> CurrentTimestamp()
|
||||
{
|
||||
return Raw<DateTime>("CURRENT_TIMESTAMP");
|
||||
}
|
||||
|
||||
/// <summary>Create scalar subquery expression.</summary>
|
||||
public static TypedSqlExpression<T> SubQuery<T>(IDynamicSelectQueryBuilder query)
|
||||
{
|
||||
return new TypedSqlSubQueryExpression<T>(query);
|
||||
}
|
||||
|
||||
/// <summary>Create scalar typed subquery expression without manually constructing the builder.</summary>
|
||||
public static TypedSqlExpression<TResult> SubQuery<TModel, TResult>(DynamicDatabase db, Func<IDynamicTypedSelectQueryBuilder<TModel>, 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<TResult>(configure(db.FromTyped<TModel>(alias, noLock)));
|
||||
}
|
||||
|
||||
/// <summary>Create scalar typed subquery expression using the scoped typed builder API.</summary>
|
||||
public static TypedSqlExpression<TResult> SubQueryScope<TModel, TResult>(DynamicDatabase db, Func<IDynamicTypedSelectScopeQueryBuilder<TModel>, 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<TResult>(configure(db.FromTypedScope<TModel>(alias, noLock)));
|
||||
}
|
||||
|
||||
/// <summary>Create EXISTS predicate.</summary>
|
||||
public static TypedSqlPredicate Exists(IDynamicSelectQueryBuilder query)
|
||||
{
|
||||
return new TypedSqlExistsPredicate(query);
|
||||
}
|
||||
|
||||
/// <summary>Create EXISTS predicate from typed subquery factory.</summary>
|
||||
public static TypedSqlPredicate Exists<TModel>(DynamicDatabase db, Func<IDynamicTypedSelectQueryBuilder<TModel>, 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<TModel>(alias, noLock)));
|
||||
}
|
||||
|
||||
/// <summary>Create EXISTS predicate from scoped typed subquery factory.</summary>
|
||||
public static TypedSqlPredicate ExistsScope<TModel>(DynamicDatabase db, Func<IDynamicTypedSelectScopeQueryBuilder<TModel>, 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<TModel>(alias, noLock)));
|
||||
}
|
||||
|
||||
/// <summary>Create CASE expression builder.</summary>
|
||||
public static TypedSqlCaseBuilder<T> Case<T>()
|
||||
{
|
||||
return new TypedSqlCaseBuilder<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Builder for CASE expressions.</summary>
|
||||
/// <typeparam name="T">Result type.</typeparam>
|
||||
public sealed class TypedSqlCaseBuilder<T>
|
||||
{
|
||||
private readonly IList<KeyValuePair<TypedSqlPredicate, TypedSqlExpression>> _cases = new List<KeyValuePair<TypedSqlPredicate, TypedSqlExpression>>();
|
||||
|
||||
/// <summary>Add WHEN ... THEN ... clause.</summary>
|
||||
public TypedSqlCaseBuilder<T> When(TypedSqlPredicate predicate, object value)
|
||||
{
|
||||
_cases.Add(new KeyValuePair<TypedSqlPredicate, TypedSqlExpression>(
|
||||
predicate,
|
||||
value as TypedSqlExpression ?? Sql.Val(value)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Finalize CASE expression with ELSE clause.</summary>
|
||||
public TypedSqlExpression<T> Else(object value)
|
||||
{
|
||||
return new TypedSqlCaseExpression<T>(_cases, value as TypedSqlExpression ?? Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Finalize CASE expression without ELSE clause.</summary>
|
||||
public TypedSqlExpression<T> End()
|
||||
{
|
||||
return new TypedSqlCaseExpression<T>(_cases, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
572
DynamORM/TypedSql/TypedSqlExpression.cs
Normal file
572
DynamORM/TypedSql/TypedSqlExpression.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Base selectable SQL fragment for the typed DSL.</summary>
|
||||
public abstract class TypedSqlSelectable
|
||||
{
|
||||
internal abstract string Render(ITypedSqlRenderContext context);
|
||||
}
|
||||
|
||||
/// <summary>Base SQL expression for the typed DSL.</summary>
|
||||
public abstract class TypedSqlExpression : TypedSqlSelectable
|
||||
{
|
||||
/// <summary>Add arithmetic expression.</summary>
|
||||
public static TypedSqlExpression<object> operator +(TypedSqlExpression left, TypedSqlExpression right)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(left, "+", right);
|
||||
}
|
||||
|
||||
/// <summary>Subtract arithmetic expression.</summary>
|
||||
public static TypedSqlExpression<object> operator -(TypedSqlExpression left, TypedSqlExpression right)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(left, "-", right);
|
||||
}
|
||||
|
||||
/// <summary>Multiply arithmetic expression.</summary>
|
||||
public static TypedSqlExpression<object> operator *(TypedSqlExpression left, TypedSqlExpression right)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(left, "*", right);
|
||||
}
|
||||
|
||||
/// <summary>Divide arithmetic expression.</summary>
|
||||
public static TypedSqlExpression<object> operator /(TypedSqlExpression left, TypedSqlExpression right)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(left, "/", right);
|
||||
}
|
||||
|
||||
/// <summary>Modulo arithmetic expression.</summary>
|
||||
public static TypedSqlExpression<object> operator %(TypedSqlExpression left, TypedSqlExpression right)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(left, "%", right);
|
||||
}
|
||||
|
||||
/// <summary>Alias this expression in SELECT clause.</summary>
|
||||
public TypedSqlAliasedExpression As(string alias)
|
||||
{
|
||||
return new TypedSqlAliasedExpression(this, alias);
|
||||
}
|
||||
|
||||
/// <summary>Order ascending.</summary>
|
||||
public TypedSqlOrderExpression Asc()
|
||||
{
|
||||
return new TypedSqlOrderExpression(this, true);
|
||||
}
|
||||
|
||||
/// <summary>Order descending.</summary>
|
||||
public TypedSqlOrderExpression Desc()
|
||||
{
|
||||
return new TypedSqlOrderExpression(this, false);
|
||||
}
|
||||
|
||||
/// <summary>Add expression to another value.</summary>
|
||||
public TypedSqlExpression<object> Add(object value)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(this, "+", value as TypedSqlExpression ?? Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Subtract another value.</summary>
|
||||
public TypedSqlExpression<object> Sub(object value)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(this, "-", value as TypedSqlExpression ?? Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Multiply by another value.</summary>
|
||||
public TypedSqlExpression<object> Mul(object value)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(this, "*", value as TypedSqlExpression ?? Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Divide by another value.</summary>
|
||||
public TypedSqlExpression<object> Div(object value)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(this, "/", value as TypedSqlExpression ?? Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Modulo by another value.</summary>
|
||||
public TypedSqlExpression<object> Mod(object value)
|
||||
{
|
||||
return new TypedSqlBinaryExpression(this, "%", value as TypedSqlExpression ?? Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Equality predicate.</summary>
|
||||
public TypedSqlPredicate Eq(object value)
|
||||
{
|
||||
return new TypedSqlBinaryPredicate(this, "=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Inequality predicate.</summary>
|
||||
public TypedSqlPredicate NotEq(object value)
|
||||
{
|
||||
return new TypedSqlBinaryPredicate(this, "<>", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Greater-than predicate.</summary>
|
||||
public TypedSqlPredicate Gt(object value)
|
||||
{
|
||||
return new TypedSqlBinaryPredicate(this, ">", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Greater-than-or-equal predicate.</summary>
|
||||
public TypedSqlPredicate Gte(object value)
|
||||
{
|
||||
return new TypedSqlBinaryPredicate(this, ">=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Less-than predicate.</summary>
|
||||
public TypedSqlPredicate Lt(object value)
|
||||
{
|
||||
return new TypedSqlBinaryPredicate(this, "<", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>Less-than-or-equal predicate.</summary>
|
||||
public TypedSqlPredicate Lte(object value)
|
||||
{
|
||||
return new TypedSqlBinaryPredicate(this, "<=", value is TypedSqlExpression ? (TypedSqlExpression)value : Sql.Val(value));
|
||||
}
|
||||
|
||||
/// <summary>IS NULL predicate.</summary>
|
||||
public TypedSqlPredicate IsNull()
|
||||
{
|
||||
return new TypedSqlUnaryPredicate(this, "IS NULL");
|
||||
}
|
||||
|
||||
/// <summary>IS NOT NULL predicate.</summary>
|
||||
public TypedSqlPredicate IsNotNull()
|
||||
{
|
||||
return new TypedSqlUnaryPredicate(this, "IS NOT NULL");
|
||||
}
|
||||
|
||||
/// <summary>LIKE predicate.</summary>
|
||||
public TypedSqlPredicate Like(string pattern)
|
||||
{
|
||||
return new TypedSqlBinaryPredicate(this, "LIKE", Sql.Val(pattern));
|
||||
}
|
||||
|
||||
/// <summary>IN predicate.</summary>
|
||||
public TypedSqlPredicate In(params object[] values)
|
||||
{
|
||||
return new TypedSqlInPredicate(this, values);
|
||||
}
|
||||
|
||||
/// <summary>IN predicate.</summary>
|
||||
public TypedSqlPredicate In(IEnumerable values)
|
||||
{
|
||||
return new TypedSqlInPredicate(this, values);
|
||||
}
|
||||
|
||||
/// <summary>NOT IN predicate.</summary>
|
||||
public TypedSqlPredicate NotIn(params object[] values)
|
||||
{
|
||||
return new TypedSqlInPredicate(this, values, true);
|
||||
}
|
||||
|
||||
/// <summary>NOT IN predicate.</summary>
|
||||
public TypedSqlPredicate NotIn(IEnumerable values)
|
||||
{
|
||||
return new TypedSqlInPredicate(this, values, true);
|
||||
}
|
||||
|
||||
/// <summary>BETWEEN predicate.</summary>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>Starts-with LIKE predicate.</summary>
|
||||
public TypedSqlPredicate StartsWith(string value)
|
||||
{
|
||||
return Like((value ?? string.Empty) + "%");
|
||||
}
|
||||
|
||||
/// <summary>Ends-with LIKE predicate.</summary>
|
||||
public TypedSqlPredicate EndsWith(string value)
|
||||
{
|
||||
return Like("%" + (value ?? string.Empty));
|
||||
}
|
||||
|
||||
/// <summary>Contains LIKE predicate.</summary>
|
||||
public TypedSqlPredicate Contains(string value)
|
||||
{
|
||||
return Like("%" + (value ?? string.Empty) + "%");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Typed SQL expression.</summary>
|
||||
public abstract class TypedSqlExpression<T> : TypedSqlExpression
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Typed SQL predicate expression.</summary>
|
||||
public abstract class TypedSqlPredicate : TypedSqlExpression<bool>
|
||||
{
|
||||
/// <summary>Combine with AND.</summary>
|
||||
public TypedSqlPredicate And(TypedSqlPredicate right)
|
||||
{
|
||||
return new TypedSqlCombinedPredicate(this, "AND", right);
|
||||
}
|
||||
|
||||
/// <summary>Combine with OR.</summary>
|
||||
public TypedSqlPredicate Or(TypedSqlPredicate right)
|
||||
{
|
||||
return new TypedSqlCombinedPredicate(this, "OR", right);
|
||||
}
|
||||
|
||||
/// <summary>Negate predicate.</summary>
|
||||
public TypedSqlPredicate Not()
|
||||
{
|
||||
return new TypedSqlNegatedPredicate(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Aliased SQL expression.</summary>
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Ordered SQL expression.</summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>Append NULLS FIRST ordering.</summary>
|
||||
public TypedSqlOrderExpression NullsFirst()
|
||||
{
|
||||
return new TypedSqlOrderExpression(_expression, _ascending, "NULLS FIRST", _raw);
|
||||
}
|
||||
|
||||
/// <summary>Append NULLS LAST ordering.</summary>
|
||||
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<object>
|
||||
{
|
||||
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<T> : TypedSqlExpression<T>
|
||||
{
|
||||
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<T> : TypedSqlExpression<T>, 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<T> : TypedSqlExpression<T>
|
||||
{
|
||||
private readonly string _sql;
|
||||
|
||||
internal TypedSqlRawExpression(string sql)
|
||||
{
|
||||
_sql = sql;
|
||||
}
|
||||
|
||||
internal override string Render(ITypedSqlRenderContext context)
|
||||
{
|
||||
return _sql;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class TypedSqlFunctionExpression<T> : TypedSqlExpression<T>
|
||||
{
|
||||
private readonly string _name;
|
||||
private readonly IList<TypedSqlExpression> _arguments;
|
||||
|
||||
internal TypedSqlFunctionExpression(string name, params TypedSqlExpression[] arguments)
|
||||
{
|
||||
_name = name;
|
||||
_arguments = arguments ?? new TypedSqlExpression[0];
|
||||
}
|
||||
|
||||
internal override string Render(ITypedSqlRenderContext context)
|
||||
{
|
||||
List<string> rendered = new List<string>();
|
||||
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<object> objRight = _right as TypedSqlValueExpression<object>;
|
||||
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<string> rendered = new List<string>();
|
||||
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<T> : TypedSqlExpression<T>
|
||||
{
|
||||
private readonly IList<KeyValuePair<TypedSqlPredicate, TypedSqlExpression>> _cases;
|
||||
private readonly TypedSqlExpression _elseExpression;
|
||||
|
||||
internal TypedSqlCaseExpression(IList<KeyValuePair<TypedSqlPredicate, TypedSqlExpression>> cases, TypedSqlExpression elseExpression)
|
||||
{
|
||||
_cases = cases;
|
||||
_elseExpression = elseExpression;
|
||||
}
|
||||
|
||||
internal override string Render(ITypedSqlRenderContext context)
|
||||
{
|
||||
List<string> items = new List<string>();
|
||||
items.Add("CASE");
|
||||
|
||||
foreach (KeyValuePair<TypedSqlPredicate, TypedSqlExpression> 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<T> : TypedSqlExpression<T>
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
46
DynamORM/TypedSql/TypedTableContext.cs
Normal file
46
DynamORM/TypedSql/TypedTableContext.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>Typed table context used by the typed SQL DSL.</summary>
|
||||
/// <typeparam name="T">Mapped entity type.</typeparam>
|
||||
public sealed class TypedTableContext<T>
|
||||
{
|
||||
internal TypedTableContext(string alias)
|
||||
{
|
||||
Alias = alias;
|
||||
}
|
||||
|
||||
/// <summary>Gets table alias used by the current query.</summary>
|
||||
public string Alias { get; private set; }
|
||||
|
||||
/// <summary>Creates a mapped column expression.</summary>
|
||||
public TypedSqlExpression<TValue> Col<TValue>(Expression<Func<T, TValue>> 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<TValue>(typeof(T), member.Member.Name, Alias);
|
||||
}
|
||||
|
||||
/// <summary>Select all columns from this typed table context.</summary>
|
||||
public TypedSqlExpression<object> All()
|
||||
{
|
||||
return Sql.Raw<object>(string.IsNullOrEmpty(Alias) ? "*" : Alias + ".*");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<T>() / db.Update<T>() / db.Delete<T>()`
|
||||
|
||||
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).
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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<User>("u")
|
||||
.SelectSql(u => u.Col(x => x.Code))
|
||||
.WhereSql(u => u.Col(x => x.Id).Eq(19));
|
||||
|
||||
var value = cmd.ScalarAs<string>();
|
||||
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
|
||||
|
||||
367
docs/typed-fluent-syntax.md
Normal file
367
docs/typed-fluent-syntax.md
Normal file
@@ -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<T>("alias")`
|
||||
- scoped typed builder:
|
||||
- `db.FromTypedScope<T>("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<User>("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<T>`
|
||||
- `TypedSqlExpression<T>`
|
||||
- `TypedSqlPredicate`
|
||||
- `TypedSqlOrderExpression`
|
||||
- `Sql.*` helpers
|
||||
|
||||
Common building blocks:
|
||||
|
||||
```csharp
|
||||
u.Col(x => x.Id)
|
||||
Sql.Val(1)
|
||||
Sql.Count()
|
||||
Sql.Coalesce<string>(u.Col(x => x.Code), Sql.Val("N/A"))
|
||||
Sql.Case<string>().When(...).Else(...)
|
||||
```
|
||||
|
||||
## Positional Typed Builder
|
||||
|
||||
`FromTyped(...)` supports typed joins and then exposes joined tables by position.
|
||||
|
||||
Example:
|
||||
|
||||
```csharp
|
||||
var cmd = db.FromTyped<User>("u")
|
||||
.Join<UserClient>(j => j.Left().As("c").OnSql((u, c) =>
|
||||
u.Col(x => x.Id).Eq(c.Col(x => x.UserId))))
|
||||
.SelectSql<UserClient>(
|
||||
(u, c) => u.Col(x => x.Id).As("user_id"),
|
||||
(u, c) => c.Col(x => x.ClientCode).As("client_code"))
|
||||
.WhereSql<UserClient>((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<User>("u")
|
||||
.Join<UserClient>(j => j.Left().As("c").OnSql((u, c) =>
|
||||
u.Col(x => x.Id).Eq(c.Col(x => x.UserId))))
|
||||
.Join<UserRole>(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<TJoin>(...)` 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<UserClient>(j => j.Left().As("c").OnSql((u, c) =>
|
||||
u.Col(x => x.Id).Eq(c.Col(x => x.UserId))))
|
||||
|
||||
.Join<UserClient>(j => j.Type("CROSS APPLY").As("c").NoLock())
|
||||
|
||||
.Join<UserRole>(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<string>(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<string>()
|
||||
.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<T>(...)`
|
||||
- `Sql.Func<T>(...)`
|
||||
- `OnRaw(...)`
|
||||
|
||||
Examples:
|
||||
|
||||
```csharp
|
||||
Sql.Raw<int>("ROW_NUMBER() OVER(ORDER BY u.\"id_user\")")
|
||||
Sql.Func<string>("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<TModel, TResult>(...)`
|
||||
- `Sql.Exists<TModel>(...)`
|
||||
- scoped typed helper:
|
||||
- `Sql.SubQueryScope<TModel, TResult>(...)`
|
||||
- `Sql.ExistsScope<TModel>(...)`
|
||||
|
||||
Use the scoped helpers when the subquery itself benefits from `FromTypedScope(...)`.
|
||||
|
||||
Example:
|
||||
|
||||
```csharp
|
||||
.SelectSql(u => Sql.SubQueryScope<User, string>(
|
||||
db,
|
||||
sq => sq
|
||||
.Join<UserClient>(j => j.Left().As("c").OnSql((x, c) =>
|
||||
x.Col(a => a.Id).Eq(c.Col(a => a.UserId))))
|
||||
.Join<UserRole>(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<T>()`
|
||||
- `UpdateTyped<T>()`
|
||||
- `DeleteTyped<T>()`
|
||||
|
||||
Examples:
|
||||
|
||||
```csharp
|
||||
db.UpdateTyped<User>()
|
||||
.SetSql(u => u.Code, u => Sql.Coalesce<string>(Sql.Val("900"), u.Col(x => x.Code)))
|
||||
.WhereSql(u => u.Col(x => x.Id).Eq(1));
|
||||
|
||||
db.InsertTyped<User>()
|
||||
.InsertSql(u => u.Code, u => Sql.Val("901"));
|
||||
|
||||
db.DeleteTyped<User>()
|
||||
.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)
|
||||
Reference in New Issue
Block a user