This commit is contained in:
@@ -49,7 +49,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="nunit.framework, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
|
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Data.SQLite">
|
<Reference Include="System.Data.SQLite">
|
||||||
@@ -61,6 +61,7 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="DynamicClassBuilderTest.cs" />
|
||||||
<Compile Include="Helpers\Dynamic\DynamicParserTests.cs" />
|
<Compile Include="Helpers\Dynamic\DynamicParserTests.cs" />
|
||||||
<Compile Include="Helpers\PoolingTests.cs" />
|
<Compile Include="Helpers\PoolingTests.cs" />
|
||||||
<Compile Include="Modify\DynamicModificationTests.cs" />
|
<Compile Include="Modify\DynamicModificationTests.cs" />
|
||||||
|
|||||||
108
DynamORM.Tests/DynamicClassBuilderTest.cs
Normal file
108
DynamORM.Tests/DynamicClassBuilderTest.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace DynamORM.Tests
|
||||||
|
{
|
||||||
|
public class DynamicProduct : IDictionary
|
||||||
|
{
|
||||||
|
private IDictionary _dict = null;
|
||||||
|
|
||||||
|
public DynamicProduct(IDictionary dict)
|
||||||
|
{
|
||||||
|
_dict = dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties from dict
|
||||||
|
public int ID
|
||||||
|
{
|
||||||
|
get { return (int)(_dict["ID"] ?? 0); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!IsReadOnly)
|
||||||
|
_dict["ID"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return (string)(_dict["Name"] ?? 0); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!IsReadOnly)
|
||||||
|
_dict["Name"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime Delivery
|
||||||
|
{
|
||||||
|
get { return (DateTime)(_dict["Delivery"] ?? 0); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!IsReadOnly)
|
||||||
|
_dict["Delivery"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Data
|
||||||
|
{
|
||||||
|
get { return (object)(_dict["Data"] ?? 0); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!IsReadOnly)
|
||||||
|
_dict["Data"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDictionary implementation
|
||||||
|
public void Add(object key, object value)
|
||||||
|
{
|
||||||
|
_dict.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_dict.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(object key)
|
||||||
|
{
|
||||||
|
return _dict.Contains(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDictionaryEnumerator GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(object key)
|
||||||
|
{
|
||||||
|
_dict.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(System.Array array, int index)
|
||||||
|
{
|
||||||
|
_dict.CopyTo(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return _dict.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsFixedSize { get { return _dict.IsFixedSize; } }
|
||||||
|
|
||||||
|
public bool IsReadOnly { get { return _dict.IsReadOnly; } }
|
||||||
|
|
||||||
|
public ICollection Keys { get { return _dict.Keys; } }
|
||||||
|
|
||||||
|
public ICollection Values { get { return _dict.Values; } }
|
||||||
|
|
||||||
|
public object this[object key] { get { return _dict[key]; } set { _dict[key] = value; } }
|
||||||
|
|
||||||
|
public int Count { get { return _dict.Count; } }
|
||||||
|
|
||||||
|
public bool IsSynchronized { get { return _dict.IsSynchronized; } }
|
||||||
|
|
||||||
|
public object SyncRoot { get { return _dict.SyncRoot; } }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -180,6 +180,19 @@ namespace DynamORM.Tests.Select
|
|||||||
Assert.AreEqual("SELECT * FROM (SELECT * FROM \"dbo\".\"Users\") AS u", cmd.CommandText());
|
Assert.AreEqual("SELECT * FROM (SELECT * FROM \"dbo\".\"Users\") AS u", cmd.CommandText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests from method using invoke with sub query.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestFromSubQuery3()
|
||||||
|
{
|
||||||
|
IDynamicSelectQueryBuilder cmd = new DynamicSelectQueryBuilder(Database);
|
||||||
|
|
||||||
|
cmd.SubQuery((b, s) => b.From(y => y(s.From(x => x.dbo.Users)).As("u")));
|
||||||
|
|
||||||
|
Assert.AreEqual("SELECT * FROM (SELECT * FROM \"dbo\".\"Users\") AS u", cmd.CommandText());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tests where method with alias.
|
/// Tests where method with alias.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -341,6 +354,21 @@ namespace DynamORM.Tests.Select
|
|||||||
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());
|
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>
|
/// <summary>
|
||||||
/// Tests left outer join method.
|
/// Tests left outer join method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
29
DynamORM.sln
29
DynamORM.sln
@@ -1,25 +1,52 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
# Visual Studio 2010
|
# Visual Studio 2010
|
||||||
# SharpDevelop 4.2.0.8774-RC
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamORM", "DynamORM\DynamORM.csproj", "{63963ED7-9C78-4672-A4D4-339B6E825503}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamORM", "DynamORM\DynamORM.csproj", "{63963ED7-9C78-4672-A4D4-339B6E825503}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamORM.Tests", "DynamORM.Tests\DynamORM.Tests.csproj", "{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamORM.Tests", "DynamORM.Tests\DynamORM.Tests.csproj", "{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Workbench", "Workbench\Workbench.csproj", "{01429808-B1A9-4272-852E-B2F7649BD788}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|Mixed Platforms = Release|Mixed Platforms
|
||||||
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{63963ED7-9C78-4672-A4D4-339B6E825503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{63963ED7-9C78-4672-A4D4-339B6E825503}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{63963ED7-9C78-4672-A4D4-339B6E825503}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{63963ED7-9C78-4672-A4D4-339B6E825503}.Release|Any CPU.Build.0 = Release|Any CPU
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{63963ED7-9C78-4672-A4D4-339B6E825503}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{D5013B4E-8A1B-4DBB-8FB5-E09935F4F764}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Release|Any CPU.ActiveCfg = Release|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{01429808-B1A9-4272-852E-B2F7649BD788}.Release|x86.Build.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
namespace DynamORM.Builders
|
namespace DynamORM.Builders
|
||||||
{
|
{
|
||||||
@@ -44,10 +45,30 @@ namespace DynamORM.Builders
|
|||||||
/// <returns>Enumerator of objects expanded from query.</returns>
|
/// <returns>Enumerator of objects expanded from query.</returns>
|
||||||
IEnumerable<T> Execute<T>() where T : class;
|
IEnumerable<T> Execute<T>() where T : class;
|
||||||
|
|
||||||
|
/// <summary>Execute this builder as a data reader.</summary>
|
||||||
|
/// <param name="reader">Action containing reader.</param>
|
||||||
|
void ExecuteDataReader(Action<IDataReader> reader);
|
||||||
|
|
||||||
/// <summary>Returns a single result.</summary>
|
/// <summary>Returns a single result.</summary>
|
||||||
/// <returns>Result of a query.</returns>
|
/// <returns>Result of a query.</returns>
|
||||||
object Scalar();
|
object Scalar();
|
||||||
|
|
||||||
|
#region SubQuery
|
||||||
|
|
||||||
|
/// <summary>Adds to the 'From' clause of sub query the contents obtained by
|
||||||
|
/// parsing the dynamic lambda expressions given. The supported formats are:
|
||||||
|
/// <para>- Resolve to a string: 'x => "Table AS Alias', where the alias part is optional.</para>
|
||||||
|
/// <para>- Resolve to an expression: 'x => x.Table.As( x.Alias )', where the alias part is optional.</para>
|
||||||
|
/// <para>- Generic expression: 'x => x( expression ).As( x.Alias )', where the alias part is mandatory. In this
|
||||||
|
/// case the alias is not annotated.</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="subquery">First argument is parent query, second one is a subquery.</param>
|
||||||
|
/// <param name="func">The specification for subquery.</param>
|
||||||
|
/// <returns>This instance to permit chaining.</returns>
|
||||||
|
IDynamicSelectQueryBuilder SubQuery(Action<IDynamicSelectQueryBuilder, IDynamicSelectQueryBuilder> subquery, params Func<dynamic, object>[] func);
|
||||||
|
|
||||||
|
#endregion SubQuery
|
||||||
|
|
||||||
#region From/Join
|
#region From/Join
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace DynamORM.Builders
|
|||||||
/// <summary>Gets or sets a value indicating whether name of temporary parameter is well known.</summary>
|
/// <summary>Gets or sets a value indicating whether name of temporary parameter is well known.</summary>
|
||||||
bool WellKnown { get; set; }
|
bool WellKnown { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets a value indicating whether this <see cref="Parameter"/> is virtual.</summary>
|
/// <summary>Gets or sets a value indicating whether this <see cref="IParameter"/> is virtual.</summary>
|
||||||
bool Virtual { get; set; }
|
bool Virtual { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets the parameter schema information.</summary>
|
/// <summary>Gets or sets the parameter schema information.</summary>
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ namespace DynamORM.Builders.Implementation
|
|||||||
/// <param name="isMultiPart">If set parse argument as alias. This is workaround for AS method.</param>
|
/// <param name="isMultiPart">If set parse argument as alias. This is workaround for AS method.</param>
|
||||||
/// <param name="columnSchema">This parameter is used to determine type of parameter used in query.</param>
|
/// <param name="columnSchema">This parameter is used to determine type of parameter used in query.</param>
|
||||||
/// <returns>A string containing the result of the parsing, along with the parameters extracted in the
|
/// <returns>A string containing the result of the parsing, along with the parameters extracted in the
|
||||||
/// <see cref="pars" /> instance if such is given.</returns>
|
/// <paramref name="pars" /> instance if such is given.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">Null nodes are not accepted.</exception>
|
/// <exception cref="System.ArgumentNullException">Null nodes are not accepted.</exception>
|
||||||
internal virtual string Parse(object node, IDictionary<string, IParameter> pars = null, bool rawstr = false, bool nulls = false, bool decorate = true, bool isMultiPart = true, DynamicSchemaColumn? columnSchema = null)
|
internal virtual string Parse(object node, IDictionary<string, IParameter> pars = null, bool rawstr = false, bool nulls = false, bool decorate = true, bool isMultiPart = true, DynamicSchemaColumn? columnSchema = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using DynamORM.Builders.Extensions;
|
using DynamORM.Builders.Extensions;
|
||||||
@@ -147,32 +148,30 @@ namespace DynamORM.Builders.Implementation
|
|||||||
{
|
{
|
||||||
using (var con = Database.Open())
|
using (var con = Database.Open())
|
||||||
using (var cmd = con.CreateCommand())
|
using (var cmd = con.CreateCommand())
|
||||||
{
|
using (var rdr = cmd
|
||||||
using (var rdr = cmd
|
.SetCommand(this)
|
||||||
.SetCommand(this)
|
.ExecuteReader())
|
||||||
.ExecuteReader())
|
while (rdr.Read())
|
||||||
while (rdr.Read())
|
{
|
||||||
|
dynamic val = null;
|
||||||
|
|
||||||
|
// Work around to avoid yield being in try...catchblock:
|
||||||
|
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
|
||||||
|
try
|
||||||
{
|
{
|
||||||
dynamic val = null;
|
val = rdr.RowToDynamic();
|
||||||
|
|
||||||
// Work around to avoid yield being in try...catchblock:
|
|
||||||
// http://stackoverflow.com/questions/346365/why-cant-yield-return-appear-inside-a-try-block-with-a-catch
|
|
||||||
try
|
|
||||||
{
|
|
||||||
val = rdr.RowToDynamic();
|
|
||||||
}
|
|
||||||
catch (ArgumentException argex)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
cmd.Dump(sb);
|
|
||||||
|
|
||||||
throw new ArgumentException(string.Format("{0}{1}{2}", argex.Message, Environment.NewLine, sb),
|
|
||||||
argex.InnerException.NullOr(a => a, argex));
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return val;
|
|
||||||
}
|
}
|
||||||
}
|
catch (ArgumentException argex)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
cmd.Dump(sb);
|
||||||
|
|
||||||
|
throw new ArgumentException(string.Format("{0}{1}{2}", argex.Message, Environment.NewLine, sb),
|
||||||
|
argex.InnerException.NullOr(a => a, argex));
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Execute this builder and map to given type.</summary>
|
/// <summary>Execute this builder and map to given type.</summary>
|
||||||
@@ -215,6 +214,18 @@ namespace DynamORM.Builders.Implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Execute this builder as a data reader.</summary>
|
||||||
|
/// <param name="reader">Action containing reader.</param>
|
||||||
|
public virtual void ExecuteDataReader(Action<IDataReader> reader)
|
||||||
|
{
|
||||||
|
using (var con = Database.Open())
|
||||||
|
using (var cmd = con.CreateCommand())
|
||||||
|
using (var rdr = cmd
|
||||||
|
.SetCommand(this)
|
||||||
|
.ExecuteReader())
|
||||||
|
reader(rdr);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Returns a single result.</summary>
|
/// <summary>Returns a single result.</summary>
|
||||||
/// <returns>Result of a query.</returns>
|
/// <returns>Result of a query.</returns>
|
||||||
public virtual object Scalar()
|
public virtual object Scalar()
|
||||||
@@ -230,6 +241,34 @@ namespace DynamORM.Builders.Implementation
|
|||||||
|
|
||||||
#endregion Execution
|
#endregion Execution
|
||||||
|
|
||||||
|
#region Subquery
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds to the 'From' clause of sub query the contents obtained by
|
||||||
|
/// parsing the dynamic lambda expressions given. The supported formats are:
|
||||||
|
/// <para>- Resolve to a string: 'x => "Table AS Alias', where the alias part is optional.</para>
|
||||||
|
/// <para>- Resolve to an expression: 'x => x.Table.As( x.Alias )', where the alias part is optional.</para>
|
||||||
|
/// <para>- Generic expression: 'x => x( expression ).As( x.Alias )', where the alias part is mandatory. In this
|
||||||
|
/// case the alias is not annotated.</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="subquery">First argument is parent query, second one is a subquery.</param>
|
||||||
|
/// <param name="func">The specification for subquery.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// This instance to permit chaining.
|
||||||
|
/// </returns>
|
||||||
|
public virtual IDynamicSelectQueryBuilder SubQuery(Action<IDynamicSelectQueryBuilder, IDynamicSelectQueryBuilder> subquery, params Func<dynamic, object>[] func)
|
||||||
|
{
|
||||||
|
var sub = func == null || func.Length == 0 ? base.SubQuery() : base.SubQuery(func);
|
||||||
|
|
||||||
|
subquery(this, sub);
|
||||||
|
|
||||||
|
ParseCommand(sub as DynamicQueryBuilder, Parameters);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Subquery
|
||||||
|
|
||||||
#region From/Join
|
#region From/Join
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -312,6 +351,12 @@ namespace DynamORM.Builders.Implementation
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*if (node is DynamicParser.Node.Method && ((DynamicParser.Node.Method)node).Name.ToUpper() == "subquery")
|
||||||
|
{
|
||||||
|
main = Parse(this.SubQuery(((DynamicParser.Node.Method)node).Arguments.Where(p => p is Func<dynamic, object>).Cast<Func<dynamic, object>>().ToArray()), Parameters);
|
||||||
|
continue;
|
||||||
|
}*/
|
||||||
|
|
||||||
// Support for table specifications...
|
// Support for table specifications...
|
||||||
if (node is DynamicParser.Node.GetMember)
|
if (node is DynamicParser.Node.GetMember)
|
||||||
{
|
{
|
||||||
@@ -560,7 +605,7 @@ namespace DynamORM.Builders.Implementation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Support for Join Type specifications...
|
// Support for Join Type specifications...
|
||||||
if (node is DynamicParser.Node.Method && node.Host is DynamicParser.Node.Argument)
|
if (node is DynamicParser.Node.Method && (node.Host is DynamicParser.Node.Argument || node.Host is DynamicParser.Node.Invoke))
|
||||||
{
|
{
|
||||||
if (type != null) throw new ArgumentException(string.Format("Join type '{0}' is already set when parsing '{1}'.", main, result));
|
if (type != null) throw new ArgumentException(string.Format("Join type '{0}' is already set when parsing '{1}'.", main, result));
|
||||||
type = ((DynamicParser.Node.Method)node).Name;
|
type = ((DynamicParser.Node.Method)node).Name;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<DocumentationFile>bin\Release\DynamORM.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
|||||||
@@ -652,39 +652,41 @@ namespace DynamORM
|
|||||||
if (connection == null)
|
if (connection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (SyncLock)
|
if (!_singleConnection && connection != null && TransactionPool.ContainsKey(connection))
|
||||||
{
|
{
|
||||||
if (!_singleConnection && connection != null && TransactionPool.ContainsKey(connection))
|
// Close all commands
|
||||||
|
if (CommandsPool.ContainsKey(connection))
|
||||||
{
|
{
|
||||||
// Close all commands
|
var tmp = CommandsPool[connection].ToList();
|
||||||
if (CommandsPool.ContainsKey(connection))
|
tmp.ForEach(cmd => cmd.Dispose());
|
||||||
{
|
|
||||||
CommandsPool[connection].ForEach(cmd => cmd.Dispose());
|
|
||||||
CommandsPool[connection].Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rollback remaining transactions
|
CommandsPool[connection].Clear();
|
||||||
while (TransactionPool[connection].Count > 0)
|
}
|
||||||
{
|
|
||||||
IDbTransaction trans = TransactionPool[connection].Pop();
|
|
||||||
trans.Rollback();
|
|
||||||
trans.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close connection
|
// Rollback remaining transactions
|
||||||
if (connection.State == ConnectionState.Open)
|
while (TransactionPool[connection].Count > 0)
|
||||||
connection.Close();
|
{
|
||||||
|
IDbTransaction trans = TransactionPool[connection].Pop();
|
||||||
|
trans.Rollback();
|
||||||
|
trans.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// remove from pools
|
// Close connection
|
||||||
|
if (connection.State == ConnectionState.Open)
|
||||||
|
connection.Close();
|
||||||
|
|
||||||
|
// remove from pools
|
||||||
|
lock (SyncLock)
|
||||||
|
{
|
||||||
TransactionPool.Remove(connection);
|
TransactionPool.Remove(connection);
|
||||||
CommandsPool.Remove(connection);
|
CommandsPool.Remove(connection);
|
||||||
|
|
||||||
// Set stamp
|
|
||||||
_poolStamp = DateTime.Now.Ticks;
|
|
||||||
|
|
||||||
// Dispose the corpse
|
|
||||||
connection.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set stamp
|
||||||
|
_poolStamp = DateTime.Now.Ticks;
|
||||||
|
|
||||||
|
// Dispose the corpse
|
||||||
|
connection.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,43 +735,46 @@ namespace DynamORM
|
|||||||
/// releasing, or resetting unmanaged resources.</summary>
|
/// releasing, or resetting unmanaged resources.</summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
lock (SyncLock)
|
var tables = TablesCache.Values.ToList();
|
||||||
|
TablesCache.Clear();
|
||||||
|
|
||||||
|
tables.ForEach(t => t.Dispose());
|
||||||
|
|
||||||
|
foreach (var con in TransactionPool)
|
||||||
{
|
{
|
||||||
var tables = TablesCache.Values.ToList();
|
// Close all commands
|
||||||
TablesCache.Clear();
|
if (CommandsPool.ContainsKey(con.Key))
|
||||||
|
|
||||||
tables.ForEach(t => t.Dispose());
|
|
||||||
|
|
||||||
foreach (var con in TransactionPool)
|
|
||||||
{
|
{
|
||||||
// Close all commands
|
var tmp = CommandsPool[con.Key].ToList();
|
||||||
if (CommandsPool.ContainsKey(con.Key))
|
tmp.ForEach(cmd => cmd.Dispose());
|
||||||
{
|
|
||||||
CommandsPool[con.Key].ForEach(cmd => cmd.Dispose());
|
|
||||||
CommandsPool[con.Key].Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rollback remaining transactions
|
CommandsPool[con.Key].Clear();
|
||||||
while (con.Value.Count > 0)
|
|
||||||
{
|
|
||||||
IDbTransaction trans = con.Value.Pop();
|
|
||||||
trans.Rollback();
|
|
||||||
trans.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close connection
|
|
||||||
if (con.Key.State == ConnectionState.Open)
|
|
||||||
con.Key.Close();
|
|
||||||
|
|
||||||
// Dispose it
|
|
||||||
con.Key.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear pools
|
// Rollback remaining transactions
|
||||||
|
while (con.Value.Count > 0)
|
||||||
|
{
|
||||||
|
IDbTransaction trans = con.Value.Pop();
|
||||||
|
trans.Rollback();
|
||||||
|
trans.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close connection
|
||||||
|
if (con.Key.State == ConnectionState.Open)
|
||||||
|
con.Key.Close();
|
||||||
|
|
||||||
|
// Dispose it
|
||||||
|
con.Key.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear pools
|
||||||
|
lock (SyncLock)
|
||||||
|
{
|
||||||
TransactionPool.Clear();
|
TransactionPool.Clear();
|
||||||
CommandsPool.Clear();
|
CommandsPool.Clear();
|
||||||
IsDisposed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IsDisposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Gets a value indicating whether this instance is disposed.</summary>
|
/// <summary>Gets a value indicating whether this instance is disposed.</summary>
|
||||||
|
|||||||
@@ -816,6 +816,17 @@ namespace DynamORM
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Sets the virtual mode on builder.</summary>
|
||||||
|
/// <typeparam name="T">Class implementing <see cref="IDynamicQueryBuilder"/> interface.</typeparam>
|
||||||
|
/// <param name="b">The builder on which set delegate.</param>
|
||||||
|
/// <param name="virtualMode">Virtual mode.</param>
|
||||||
|
/// <returns>Returns instance of builder on which virtual mode is set.</returns>
|
||||||
|
public static T SetVirtualMode<T>(this T b, bool virtualMode) where T : IDynamicQueryBuilder
|
||||||
|
{
|
||||||
|
b.VirtualMode = virtualMode;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Sets the on create real parameter action.</summary>
|
/// <summary>Sets the on create real parameter action.</summary>
|
||||||
/// <typeparam name="T">Class implementing <see cref="IDynamicQueryBuilder"/> interface.</typeparam>
|
/// <typeparam name="T">Class implementing <see cref="IDynamicQueryBuilder"/> interface.</typeparam>
|
||||||
/// <param name="b">The builder on which set delegate.</param>
|
/// <param name="b">The builder on which set delegate.</param>
|
||||||
@@ -1071,7 +1082,7 @@ namespace DynamORM
|
|||||||
{
|
{
|
||||||
TValue val;
|
TValue val;
|
||||||
|
|
||||||
if (dict.TryGetValue(key, out val))
|
if (key != null && dict.TryGetValue(key, out val))
|
||||||
return val;
|
return val;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -1087,7 +1098,7 @@ namespace DynamORM
|
|||||||
{
|
{
|
||||||
TValue val;
|
TValue val;
|
||||||
|
|
||||||
if (dict.TryGetValue(key, out val))
|
if (key != null && dict.TryGetValue(key, out val))
|
||||||
return val;
|
return val;
|
||||||
|
|
||||||
return default(TValue);
|
return default(TValue);
|
||||||
|
|||||||
@@ -696,7 +696,7 @@ namespace DynamORM.Helpers.Dynamics
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a binary operation between a dynamic element and an arbitrary object, including null ones, as in
|
/// Represents a binary operation between a dynamic element and an arbitrary object, including null ones, as in
|
||||||
/// 'x => (x && null)'. The left operand must be an instance of <see cref="DynamicNode"/>, whereas the right one
|
/// 'x => (x && null)'. The left operand must be an instance of <see cref="Node"/>, whereas the right one
|
||||||
/// can be any object, including null values.
|
/// can be any object, including null values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -770,7 +770,7 @@ namespace DynamORM.Helpers.Dynamics
|
|||||||
#region Unary
|
#region Unary
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an unary operation, as in 'x => !x'. The target must be a <see cref="DynamicNode"/> instance. There
|
/// Represents an unary operation, as in 'x => !x'. The target must be a <see cref="Node"/> instance. There
|
||||||
/// is no distinction between pre- and post- version of the same operation.
|
/// is no distinction between pre- and post- version of the same operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -1055,7 +1055,7 @@ namespace DynamORM.Helpers.Dynamics
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the result of the parsing of the dynamic lambda expression. This result can be either an arbitrary object,
|
/// Gets the result of the parsing of the dynamic lambda expression. This result can be either an arbitrary object,
|
||||||
/// including null, if the expression resolves to it, or an instance of the <see cref="DynamicNode"/> class that
|
/// including null, if the expression resolves to it, or an instance of the <see cref="Node"/> class that
|
||||||
/// contains the last logic expression evaluated when parsing the dynamic lambda expression.
|
/// contains the last logic expression evaluated when parsing the dynamic lambda expression.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object Result
|
public object Result
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ namespace DynamORM.Helpers.Dynamics
|
|||||||
/// during the invoke operation. For example, for the statement
|
/// during the invoke operation. For example, for the statement
|
||||||
/// sampleObject.SampleMethod(100), where sampleObject is derived from the
|
/// sampleObject.SampleMethod(100), where sampleObject is derived from the
|
||||||
/// <see cref="T:System.Dynamic.DynamicObject" /> class,
|
/// <see cref="T:System.Dynamic.DynamicObject" /> class,
|
||||||
/// <paramref name="args[0]" /> is equal to 100.</param>
|
/// First element of <paramref name="args" /> is equal to 100.</param>
|
||||||
/// <param name="result">The result of the member invocation.</param>
|
/// <param name="result">The result of the member invocation.</param>
|
||||||
/// <returns>Returns <c>true</c> if the operation is successful; otherwise,
|
/// <returns>Returns <c>true</c> if the operation is successful; otherwise,
|
||||||
/// <c>false</c>. If this method returns false, the run-time binder of the
|
/// <c>false</c>. If this method returns false, the run-time binder of the
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace DynamORM.Helpers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides with an alternate and generic way to obtain an alternate string representation for this instance,
|
/// Provides with an alternate and generic way to obtain an alternate string representation for this instance,
|
||||||
/// applying the following rules:
|
/// applying the following rules:
|
||||||
/// <para>- Null values are returned as with the <see cref="NullString"/> value, or a null object.</para>
|
/// <para>- Null values are returned as with the <paramref name="nullString"/> value, or a null object.</para>
|
||||||
/// <para>- Enum values are translated into their string representation.</para>
|
/// <para>- Enum values are translated into their string representation.</para>
|
||||||
/// <para>- If the type has override the 'ToString' method then it is used.</para>
|
/// <para>- If the type has override the 'ToString' method then it is used.</para>
|
||||||
/// <para>- If it is a dictionary, then a collection of key/value pairs where the value part is also translated.</para>
|
/// <para>- If it is a dictionary, then a collection of key/value pairs where the value part is also translated.</para>
|
||||||
|
|||||||
Reference in New Issue
Block a user