diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs
index e6ac6b5..dccfcbe 100644
--- a/AmalgamationTool/DynamORM.Amalgamation.cs
+++ b/AmalgamationTool/DynamORM.Amalgamation.cs
@@ -1895,14 +1895,15 @@ namespace DynamORM
/// Owner of table from which extract column info.
/// List of objects .
/// If your database doesn't get those values in upper case (like most of the databases) you should override this method.
- protected virtual IEnumerable ReadSchema(string table, string owner)
+ protected virtual IList ReadSchema(string table, string owner)
{
using (var con = Open())
using (var cmd = con.CreateCommand()
.SetCommand(string.Format("SELECT * FROM {0}{1} WHERE 1 = 0",
!string.IsNullOrEmpty(owner) ? string.Format("{0}.", DecorateName(owner)) : string.Empty,
DecorateName(table))))
- return ReadSchema(cmd).ToList();
+ return ReadSchema(cmd)
+ .ToList();
}
/// Get schema describing objects from reader.
@@ -1912,7 +1913,8 @@ namespace DynamORM
protected virtual IEnumerable ReadSchema(IDbCommand cmd)
{
using (var rdr = cmd.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo))
- foreach (DataRow col in rdr.GetSchemaTable().Rows)
+ using (var st = rdr.GetSchemaTable())
+ foreach (DataRow col in st.Rows)
{
var c = col.RowToDynamicUpper();
@@ -1950,7 +1952,8 @@ namespace DynamORM
if (databaseSchemaSupport && !Schema.ContainsKey(tableName.ToLower()))
{
schema = ReadSchema(tableName, owner)
- .Distinct()
+ .Where(x => x.Name != null)
+ .DistinctBy(x => x.Name)
.ToDictionary(k => k.Name.ToLower(), k => k);
Schema[tableName.ToLower()] = schema;
@@ -2391,6 +2394,170 @@ namespace DynamORM
DumpCommands = 0x01000000,
}
+ /// Dynamic expando is a simple and temporary class to resolve memory leaks inside ExpandoObject.
+ public class DynamicExpando : DynamicObject, IDictionary, ICollection>, IEnumerable>, IEnumerable
+ {
+ /// Class containing information about last accessed property of dynamic object.
+ public class PropertyAccess
+ {
+ /// Enum describing type of access to object.
+ public enum TypeOfAccess
+ {
+ /// Get member.
+ Get,
+
+ /// Set member.
+ Set,
+ }
+
+ /// Gets the type of operation.
+ public TypeOfAccess Operation { get; internal set; }
+
+ /// Gets the name of property.
+ public string Name { get; internal set; }
+
+ /// Gets the type from binder.
+ public Type RequestedType { get; internal set; }
+
+ /// Gets the type of value stored in object.
+ public Type Type { get; internal set; }
+
+ /// Gets the value stored in object.
+ public object Value { get; internal set; }
+ }
+
+ private Dictionary _data = new Dictionary();
+
+ private PropertyAccess _lastProp = new PropertyAccess();
+
+ /// Initializes a new instance of the class.
+ public DynamicExpando()
+ {
+ }
+
+ /// Gets the last accesses property.
+ /// Description of last accessed property.
+ public PropertyAccess GetLastAccessesProperty()
+ {
+ return _lastProp;
+ }
+
+ /// Tries to get member value.
+ /// Returns true, if get member was tried, false otherwise.
+ /// The context binder.
+ /// The invocation result.
+ 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;
+ }
+
+ /// Tries to set member.
+ /// Returns true, if set member was tried, false otherwise.
+ /// The context binder.
+ /// Value which will be set.
+ 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;
+ }
+
+ #region IDictionary implementation
+
+ bool IDictionary.ContainsKey(string key)
+ {
+ return _data.ContainsKey(key);
+ }
+
+ void IDictionary.Add(string key, object value)
+ {
+ _data.Add(key, value);
+ }
+
+ bool IDictionary.Remove(string key)
+ {
+ return _data.Remove(key);
+ }
+
+ bool IDictionary.TryGetValue(string key, out object value)
+ {
+ return _data.TryGetValue(key, out value);
+ }
+
+ object IDictionary.this[string index] { get { return _data[index]; } set { _data[index] = value; } }
+
+ ICollection IDictionary.Keys { get { return _data.Keys; } }
+
+ ICollection