This commit is contained in:
grzegorz.russek
2014-11-29 21:29:02 +00:00
parent ea6a74d967
commit 2f19bf5c49
6 changed files with 138 additions and 42 deletions

View File

@@ -821,9 +821,9 @@ namespace DynamORM.Builders.Implementation
//// return null;
// First we need to get real column name and it's owner if exist.
var parts = colName.Split('.')
.Select(c => Database.StripName(c))
.ToArray();
var parts = colName.Split('.');
for (int i = 0; i < parts.Length; i++)
parts[i] = Database.StripName(parts[i]);
var columnName = parts.Last();

View File

@@ -898,7 +898,11 @@ namespace DynamORM.Builders.Implementation
/// <returns>Builder instance.</returns>
public virtual IDynamicSelectQueryBuilder SelectColumn(params string[] columns)
{
return SelectColumn(columns.Select(c => DynamicColumn.ParseSelectColumn(c)).ToArray());
var cols = new DynamicColumn[columns.Count];
for (int i = 0; i < columns.Length; i++)
cols[i] = DynamicColumn.ParseSelectColumn(columns[i]);
return SelectColumn(cols);
}
#endregion Select
@@ -919,8 +923,11 @@ namespace DynamORM.Builders.Implementation
int index = GroupByFunc(-1, fn);
if (func != null)
foreach (var f in func)
for (int i = 0; i < func.Length; i++)
{
var f = func[i];
index = GroupByFunc(index, f);
}
return this;
}
@@ -958,8 +965,11 @@ namespace DynamORM.Builders.Implementation
/// <returns>Builder instance.</returns>
public virtual IDynamicSelectQueryBuilder GroupByColumn(params DynamicColumn[] columns)
{
foreach (var col in columns)
for (int i = 0; i < columns.Length; i++)
{
var col = columns[i];
GroupBy(x => col.ToSQLGroupByColumn(Database));
}
return this;
}
@@ -995,8 +1005,11 @@ namespace DynamORM.Builders.Implementation
int index = OrderByFunc(-1, fn);
if (func != null)
foreach (var f in func)
for (int i = 0; i < func.Length; i++)
{
var f = func[i];
index = OrderByFunc(index, f);
}
return this;
}
@@ -1087,8 +1100,11 @@ namespace DynamORM.Builders.Implementation
/// <returns>Builder instance.</returns>
public virtual IDynamicSelectQueryBuilder OrderByColumn(params DynamicColumn[] columns)
{
foreach (var col in columns)
for (int i = 0; i < columns.Length; i++)
{
var col = columns[i];
OrderBy(x => col.ToSQLOrderByColumn(Database));
}
return this;
}

View File

@@ -104,6 +104,7 @@
<Compile Include="Mapper\TableAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="DynamicExpando.cs" />
<Compile Include="Helpers\IFinalizerDisposable.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -52,7 +52,7 @@ namespace DynamORM.Helpers.Dynamics
/// a method of that argument.
/// </summary>
[Serializable]
public class Node : IDynamicMetaObjectProvider, IExtendedDisposable, ISerializable
public class Node : IDynamicMetaObjectProvider, IFinalizerDisposable, ISerializable
{
private DynamicParser _parser = null;
@@ -76,17 +76,16 @@ namespace DynamORM.Helpers.Dynamics
}
// Func was cool but caused memory leaks
private DynamicMetaObject GetBinder(Node newNode)
private DynamicMetaObject GetBinder(Node node)
{
var o = (Node)this.Value;
o.Parser.Last = newNode;
newNode.Parser = o.Parser;
node.Parser = o.Parser;
o.Parser.Last = node;
var p = Expression.Variable(typeof(Node), "ret");
var exp = Expression.Block(new ParameterExpression[] { p }, Expression.Assign(p, Expression.Constant(newNode)));
var exp = Expression.Block(new ParameterExpression[] { p }, Expression.Assign(p, Expression.Constant(node)));
return new MetaNode(exp, this.Restrictions, newNode);
return new MetaNode(exp, this.Restrictions, node);
}
/// <summary>
@@ -124,7 +123,7 @@ namespace DynamORM.Helpers.Dynamics
/// </returns>
public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
{
return GetBinder(new GetIndex((Node)this.Value, indexes.Select(m => m.Value).ToArray()));
return GetBinder(new GetIndex((Node)this.Value, MetaList2List(indexes)));
}
/// <summary>
@@ -138,7 +137,7 @@ namespace DynamORM.Helpers.Dynamics
/// </returns>
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
{
return GetBinder(new SetIndex((Node)this.Value, indexes.Select(m => m.Value).ToArray(), value.Value));
return GetBinder(new SetIndex((Node)this.Value, MetaList2List(indexes), value.Value));
}
/// <summary>
@@ -151,7 +150,7 @@ namespace DynamORM.Helpers.Dynamics
/// </returns>
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
{
return GetBinder(new Invoke((Node)this.Value, args.Select(m => m.Value).ToArray()));
return GetBinder(new Invoke((Node)this.Value, MetaList2List(args)));
}
/// <summary>
@@ -164,7 +163,7 @@ namespace DynamORM.Helpers.Dynamics
/// </returns>
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
return GetBinder(new Method((Node)this.Value, binder.Name, args.Select(m => m.Value).ToArray()));
return GetBinder(new Method((Node)this.Value, binder.Name, MetaList2List(args)));
}
/// <summary>
@@ -258,6 +257,17 @@ namespace DynamORM.Helpers.Dynamics
return new MetaNode(exp, this.Restrictions, node);
}
private static object[] MetaList2List(DynamicMetaObject[] metaObjects)
{
if (metaObjects == null) return null;
object[] list = new object[metaObjects.Length];
for (int i = 0; i < metaObjects.Length; i++)
list[i] = metaObjects[i].Value;
return list;
}
}
#endregion MetaNode
@@ -770,16 +780,17 @@ namespace DynamORM.Helpers.Dynamics
/// <summary>Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.</summary>
public override void Dispose()
/// <param name="disposing">If set to <c>true</c> dispose object.</param>
public override void Dispose(bool disposing)
{
base.Dispose();
base.Dispose(disposing);
if (Right != null && Right is Node)
if (disposing && Right != null && Right is Node)
{
Node n = (Node)Right;
if (!n.IsDisposed)
n.Dispose();
n.Dispose(disposing);
Right = null;
}
@@ -1007,7 +1018,15 @@ namespace DynamORM.Helpers.Dynamics
#endregion Implementation of IDynamicMetaObjectProvider
#region Implementation of IExtendedDisposable
#region Implementation of IFinalizerDisposable
/// <summary>Releases unmanaged resources and performs other cleanup operations before
/// the <see cref="DynamORM.Helpers.Dynamics.DynamicParser.Node"/> is reclaimed by
/// garbage collection.</summary>
~Node()
{
Dispose(false);
}
/// <summary>Gets a value indicating whether this instance is disposed.</summary>
public bool IsDisposed { get; private set; }
@@ -1016,17 +1035,29 @@ namespace DynamORM.Helpers.Dynamics
/// freeing, releasing, or resetting unmanaged resources.</summary>
public virtual void Dispose()
{
IsDisposed = true;
if (Host != null && !Host.IsDisposed)
Host.Dispose();
Host = null;
Parser = null;
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion Implementation of IExtendedDisposable
/// <summary>Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.</summary>
/// <param name="disposing">If set to <c>true</c> dispose object.</param>
public virtual void Dispose(bool disposing)
{
if (disposing)
{
IsDisposed = true;
if (Host != null && !Host.IsDisposed)
Host.Dispose();
Host = null;
Parser = null;
}
}
#endregion Implementation of IFinalizerDisposable
#region Implementation of ISerializable
@@ -1104,10 +1135,17 @@ namespace DynamORM.Helpers.Dynamics
private DynamicParser(Delegate f)
{
foreach (var p in f.Method.GetParameters())
// I know this can be almost a one liner
// but it causes memory leaks when so.
var pars = f.Method.GetParameters();
foreach (var p in pars)
{
if (p.GetCustomAttributes(typeof(DynamicAttribute), true).Any())
this._arguments.Add(new Node.Argument(p.Name) { Parser = this });
var attrs = p.GetCustomAttributes(typeof(DynamicAttribute), true).Length;
if (attrs != 0)
{
var par = new Node.Argument(p.Name) { Parser = this };
this._arguments.Add(par);
}
else
throw new ArgumentException(string.Format("Argument '{0}' must be dynamic.", p.Name));
}

View File

@@ -0,0 +1,41 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, 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;
namespace DynamORM.Helpers
{
/// <summary>Extends <see cref="IExtendedDisposable"/> interface.</summary>
public interface IFinalizerDisposable : IExtendedDisposable
{
/// <summary>Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.</summary>
/// <param name="disposing">If set to <c>true</c> dispose object.</param>
void Dispose(bool disposing);
}
}

View File

@@ -77,7 +77,7 @@ namespace Tester
{
string test_str = string.Empty;
for (int y = 0; y < 10; y++)
/*for (int y = 0; y < 10; y++)
{
string val = null;
for (int i = 0; i < 1000; i++)
@@ -119,7 +119,7 @@ namespace Tester
GC.Collect();
Console.Out.WriteLine("Expr: [ExpandoObject as Dict], Mem: {0}", GC.GetTotalMemory(true));
}
}*/
/*for (int y = 0; y < 10; y++)
{
@@ -148,7 +148,7 @@ namespace Tester
//using (var db = GetORM())
{
for (int y = 0; y < 10; y++)
for (int y = 0; y < 5; y++)
{
using (var db = GetORM())
for (int i = 0; i < 1000; i++)
@@ -160,7 +160,7 @@ namespace Tester
Console.Out.WriteLine("Expr: [db.Table(\"Test\").Scalar(\"SELECT id FROM Test;\")] = {0}, Mem: {1}", test_str, GC.GetTotalMemory(true));
}
for (int y = 0; y < 10; y++)
for (int y = 0; y < 5; y++)
{
using (var db = GetORM())
for (int i = 0; i < 1000; i++)
@@ -172,7 +172,7 @@ namespace Tester
Console.Out.WriteLine("Expr: [db.Table(\"Test\").Scalar(columns: \"id\")] = {0}, Mem: {1}", test_str, GC.GetTotalMemory(true));
}
for (int y = 0; y < 10; y++)
for (int y = 0; y < 5; y++)
{
using (var db = GetORM())
for (int i = 0; i < 1000; i++)
@@ -184,7 +184,7 @@ namespace Tester
Console.Out.WriteLine("Expr: [db.From(x => x.Test.As(x.t)).Where(t => t.id == 1).ToList().First().val] = {0}, Mem: {1}", test_str, GC.GetTotalMemory(true));
}
for (int y = 0; y < 10; y++)
for (int y = 0; y < 5; y++)
{
using (var db = GetORM())
for (int i = 0; i < 1000; i++)