This commit is contained in:
grzegorz.russek
2015-01-10 15:32:07 +00:00
parent 2f19bf5c49
commit 708728cf62
9 changed files with 680 additions and 107 deletions

View File

@@ -898,7 +898,7 @@ namespace DynamORM.Builders.Implementation
/// <returns>Builder instance.</returns>
public virtual IDynamicSelectQueryBuilder SelectColumn(params string[] columns)
{
var cols = new DynamicColumn[columns.Count];
var cols = new DynamicColumn[columns.Length];
for (int i = 0; i < columns.Length; i++)
cols[i] = DynamicColumn.ParseSelectColumn(columns[i]);

View File

@@ -30,39 +30,88 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Collections.Concurrent;
namespace DynamORM
{
/// <summary>Dynamic expando is a simple and temporary class to resolve memory leaks inside ExpandoObject.</summary>
public class DynamicExpando : DynamicObject, IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
{
/// <summary>Class containing information about last accessed property of dynamic object.</summary>
public class PropertyAccess
{
/// <summary>Enum describing type of access to object.</summary>
public enum TypeOfAccess
{
/// <summary>Get member.</summary>
Get,
/// <summary>Set member.</summary>
Set,
}
/// <summary>Gets the type of operation.</summary>
public TypeOfAccess Operation { get; internal set; }
/// <summary>Gets the name of property.</summary>
public string Name { get; internal set; }
/// <summary>Gets the type from binder.</summary>
public Type RequestedType { get; internal set; }
/// <summary>Gets the type of value stored in object.</summary>
public Type Type { get; internal set; }
/// <summary>Gets the value stored in object.</summary>
public object Value { get; internal set; }
}
private Dictionary<string, object> _data = new Dictionary<string, object>();
private PropertyAccess _lastProp = new PropertyAccess();
/// <summary>Initializes a new instance of the <see cref="DynamicExpando"/> class.</summary>
public DynamicExpando()
{
}
/// <summary>Gets the last accesses property.</summary>
/// <returns>Description of last accessed property.</returns>
public PropertyAccess GetLastAccessesProperty()
{
return _lastProp;
}
/// <summary>Tries to get member value.</summary>
/// <returns>Returns <c>true</c>, if get member was tryed, <c>false</c> otherwise.</returns>
/// <returns>Returns <c>true</c>, if get member was tried, <c>false</c> otherwise.</returns>
/// <param name="binder">The context binder.</param>
/// <param name="result">The invokation result.</param>
/// <param name="result">The invocation result.</param>
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _data.TryGetValue(binder.Name);
_lastProp.Operation = PropertyAccess.TypeOfAccess.Get;
_lastProp.RequestedType = binder.ReturnType;
_lastProp.Name = binder.Name;
_lastProp.Value = result;
_lastProp.Type = result == null ? typeof(void) : result.GetType();
return true;
}
/// <summary>Tries to set member.</summary>
/// <returns>Returns <c>true</c>, if set member was tryed, <c>false</c> otherwise.</returns>
/// <returns>Returns <c>true</c>, if set member was tried, <c>false</c> otherwise.</returns>
/// <param name="binder">The context binder.</param>
/// <param name="value">Value which will be set.</param>
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_data[binder.Name] = value;
_lastProp.Operation = PropertyAccess.TypeOfAccess.Set;
_lastProp.RequestedType = binder.ReturnType;
_lastProp.Name = binder.Name;
_lastProp.Value = value;
_lastProp.Type = value == null ? typeof(void) : value.GetType();
return true;
}
@@ -88,13 +137,13 @@ namespace DynamORM
return _data.TryGetValue(key, out value);
}
object IDictionary<string, object>.this [string index] { get { return _data[index]; } set { _data[index] = value; } }
object IDictionary<string, object>.this[string index] { get { return _data[index]; } set { _data[index] = value; } }
ICollection<string> IDictionary<string, object>.Keys { get { return _data.Keys; } }
ICollection<object> IDictionary<string, object>.Values { get { return _data.Values; } }
#endregion
#endregion IDictionary implementation
#region ICollection implementation
@@ -123,11 +172,11 @@ namespace DynamORM
return ((ICollection<KeyValuePair<string, object>>)_data).Remove(item);
}
int ICollection<KeyValuePair<string, object>>.Count{ get { return _data.Count; } }
int ICollection<KeyValuePair<string, object>>.Count { get { return _data.Count; } }
bool ICollection<KeyValuePair<string, object>>.IsReadOnly { get { return ((ICollection<KeyValuePair<string, object>>)_data).IsReadOnly; } }
#endregion
#endregion ICollection implementation
#region IEnumerable implementation
@@ -136,7 +185,7 @@ namespace DynamORM
return _data.GetEnumerator();
}
#endregion
#endregion IEnumerable implementation
#region IEnumerable implementation
@@ -145,7 +194,6 @@ namespace DynamORM
return ((IEnumerable)_data).GetEnumerator();
}
#endregion
#endregion IEnumerable implementation
}
}
}

View File

@@ -229,6 +229,20 @@ namespace DynamORM
return cmd;
}
/// <summary>Extension method for adding in a bunch of parameters.</summary>
/// <param name="cmd">Command to handle.</param>
/// <param name="database">Database object required to get proper formatting.</param>
/// <param name="args">Items to add in an expando object.</param>
/// <returns>Returns edited <see cref="System.Data.IDbCommand"/> instance.</returns>
public static IDbCommand AddParameters(this IDbCommand cmd, DynamicDatabase database, DynamicExpando args)
{
if (args != null && args.Count() > 0)
foreach (var item in args.ToDictionary())
cmd.AddParameter(database, item.Key, item.Value);
return cmd;
}
/// <summary>Extension for adding single parameter determining only type of object.</summary>
/// <param name="cmd">Command to handle.</param>
/// <param name="database">Database object required to get proper formatting.</param>
@@ -258,7 +272,7 @@ namespace DynamORM
p.DbType = TypeMap.TryGetNullable(type) ?? DbType.String;
if (type == typeof(ExpandoObject))
if (type == typeof(DynamicExpando) || type == typeof(ExpandoObject))
p.Value = ((IDictionary<string, object>)item).Values.FirstOrDefault();
else
p.Value = item;
@@ -985,7 +999,7 @@ namespace DynamORM
{
var ot = o.GetType();
if (ot == typeof(ExpandoObject) || ot == typeof(DynamicExpando))
if (ot == typeof(DynamicExpando) || ot == typeof(ExpandoObject))
return o;
var result = new DynamicExpando();
@@ -1158,14 +1172,14 @@ namespace DynamORM
int c = r.FieldCount;
for (int i = 0; i < c; i++)
try
{
d.Add(r.GetName(i), r.IsDBNull(i) ? null : r[i]);
}
catch (ArgumentException argex)
{
throw new ArgumentException(
string.Format("Field '{0}' is defined more than once in a query.", r.GetName(i)), "Column name or alias", argex);
}
{
d.Add(r.GetName(i), r.IsDBNull(i) ? null : r[i]);
}
catch (ArgumentException argex)
{
throw new ArgumentException(
string.Format("Field '{0}' is defined more than once in a query.", r.GetName(i)), "Column name or alias", argex);
}
return e;
}
@@ -1181,14 +1195,14 @@ namespace DynamORM
int c = r.FieldCount;
for (int i = 0; i < c; i++)
try
{
d.Add(r.GetName(i), r.IsDBNull(i) ? null : r[i]);
}
catch (ArgumentException argex)
{
throw new ArgumentException(
string.Format("Field '{0}' is defined more than once in a query.", r.GetName(i)), "Column name or alias", argex);
}
{
d.Add(r.GetName(i), r.IsDBNull(i) ? null : r[i]);
}
catch (ArgumentException argex)
{
throw new ArgumentException(
string.Format("Field '{0}' is defined more than once in a query.", r.GetName(i)), "Column name or alias", argex);
}
return e;
}
@@ -1201,6 +1215,14 @@ namespace DynamORM
return (IDictionary<string, object>)o;
}
/// <summary>Turns the object into a Dictionary.</summary>
/// <param name="o">Object to convert.</param>
/// <returns>Resulting dictionary.</returns>
public static IDictionary<string, object> ToDictionary(this DynamicExpando o)
{
return (IDictionary<string, object>)o;
}
/// <summary>Turns the object into a Dictionary.</summary>
/// <param name="o">Object to convert.</param>
/// <returns>Resulting dictionary.</returns>

View File

@@ -33,6 +33,7 @@ using System.Runtime.Serialization;
namespace DynamORM
{
/// <summary>Dynamic query exception.</summary>
[Serializable]
public class DynamicQueryException : Exception, ISerializable
{
/// <summary>Initializes a new instance of the

View File

@@ -456,9 +456,8 @@ namespace DynamORM
/// <summary>Execute stored procedure.</summary>
/// <param name="procName">Name of stored procedure to execute.</param>
/// <param name="args">Arguments (parameters) in form of expando object.</param>
/// <returns>Number of affected rows.</returns>
public virtual int Procedure(string procName, ExpandoObject args = null)
public virtual int Procedure(string procName)
{
if ((Database.Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
throw new InvalidOperationException("Database connection desn't support stored procedures.");
@@ -467,7 +466,64 @@ namespace DynamORM
using (var cmd = con.CreateCommand())
{
return cmd
.SetCommand(CommandType.StoredProcedure, procName).AddParameters(Database, args)
.SetCommand(CommandType.StoredProcedure, procName)
.ExecuteNonQuery();
}
}
/// <summary>Execute stored procedure.</summary>
/// <param name="procName">Name of stored procedure to execute.</param>
/// <param name="args">Arguments (parameters) in form of expando object.</param>
/// <returns>Number of affected rows.</returns>
public virtual int Procedure(string procName, params object[] args)
{
if ((Database.Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
throw new InvalidOperationException("Database connection desn't support stored procedures.");
using (var con = Database.Open())
using (var cmd = con.CreateCommand())
{
return cmd
.SetCommand(CommandType.StoredProcedure, procName)
.AddParameters(Database, args)
.ExecuteNonQuery();
}
}
/// <summary>Execute stored procedure.</summary>
/// <param name="procName">Name of stored procedure to execute.</param>
/// <param name="args">Arguments (parameters) in form of expando object.</param>
/// <returns>Number of affected rows.</returns>
public virtual int Procedure(string procName, DynamicExpando args)
{
if ((Database.Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
throw new InvalidOperationException("Database connection desn't support stored procedures.");
using (var con = Database.Open())
using (var cmd = con.CreateCommand())
{
return cmd
.SetCommand(CommandType.StoredProcedure, procName)
.AddParameters(Database, args)
.ExecuteNonQuery();
}
}
/// <summary>Execute stored procedure.</summary>
/// <param name="procName">Name of stored procedure to execute.</param>
/// <param name="args">Arguments (parameters) in form of expando object.</param>
/// <returns>Number of affected rows.</returns>
public virtual int Procedure(string procName, ExpandoObject args)
{
if ((Database.Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
throw new InvalidOperationException("Database connection desn't support stored procedures.");
using (var con = Database.Open())
using (var cmd = con.CreateCommand())
{
return cmd
.SetCommand(CommandType.StoredProcedure, procName)
.AddParameters(Database, args)
.ExecuteNonQuery();
}
}

View File

@@ -32,7 +32,6 @@
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
@@ -1020,9 +1019,7 @@ namespace DynamORM.Helpers.Dynamics
#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>
/// <summary>Finalizes an instance of the <see cref="Node"/> class.</summary>
~Node()
{
Dispose(false);

View File

@@ -25,7 +25,6 @@
* 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
{
@@ -37,5 +36,4 @@ namespace DynamORM.Helpers
/// <param name="disposing">If set to <c>true</c> dispose object.</param>
void Dispose(bool disposing);
}
}
}