diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs
index af91981..1504c0b 100644
--- a/AmalgamationTool/DynamORM.Amalgamation.cs
+++ b/AmalgamationTool/DynamORM.Amalgamation.cs
@@ -1952,7 +1952,7 @@ namespace DynamORM
}
/// Bulk update objects in database.
- /// Type of objects to update.
+ /// Type of objects to update.
/// Enumerable containing instances of objects to update.
/// Number of updated rows.
public virtual int Update(Type t, IEnumerable e)
@@ -13814,6 +13814,429 @@ namespace DynamORM
}
}
+ namespace Objects
+ {
+ /// Base class for strong typed objects.
+ public class DynamicEntityBase
+ {
+ private Dictionary _changedFields = new Dictionary();
+ private DynamicEntityState _dynamicEntityState = DynamicEntityState.Unknown;
+
+ /// Occurs when object property is changing.
+ public event EventHandler PropertyChanging;
+
+ /// Gets the state of the dynamic entity.
+ /// Current state of entity.
+ public virtual DynamicEntityState GetDynamicEntityState() { return _dynamicEntityState; }
+
+ /// Sets the state of the dynamic entity.
+ /// The state.
+ public virtual void SetDynamicEntityState(DynamicEntityState state) { _dynamicEntityState = state; }
+
+ /// Called when object property is changing.
+ /// Name of the property.
+ /// The old property value.
+ /// The new property value.
+ protected virtual void OnPropertyChanging(string propertyName, object oldValue, object newValue)
+ {
+ OnPropertyChanging(new DynamicPropertyChangingEventArgs(propertyName, oldValue, newValue));
+ }
+
+ /// Raises the event.
+ /// The instance containing the event data.
+ protected virtual void OnPropertyChanging(DynamicPropertyChangingEventArgs e)
+ {
+ _changedFields[e.PropertyName] = e.NewValue;
+ if (PropertyChanging != null)
+ PropertyChanging(this, e);
+ }
+
+ /// Validates this object instance.
+ /// Returns list of containing results of validation.
+ public virtual IList Validate()
+ {
+ return DynamicMapperCache.GetMapper(this.GetType()).ValidateObject(this);
+ }
+
+ /// Saves this object to database.
+ /// The database.
+ /// Returns true if operation was successful.
+ /// Can be thrown when object is in invalid state.
+ public virtual bool Save(DynamicDatabase database)
+ {
+ switch (GetDynamicEntityState())
+ {
+ default:
+ case DynamicEntityState.Unknown:
+ throw new InvalidOperationException("Unknown object state. Unable to decide whish action should be performed.");
+
+ case DynamicEntityState.New:
+ return Insert(database);
+
+ case DynamicEntityState.Existing:
+ return Update(database);
+
+ case DynamicEntityState.ToBeDeleted:
+ return Delete(database);
+
+ case DynamicEntityState.Deleted:
+ throw new InvalidOperationException("Unable to do any database action on deleted object.");
+ }
+ }
+
+ #region Insert/Update/Delete
+
+ /// Inserts this object to database.
+ /// The database.
+ /// Returns true if operation was successful.
+ public virtual bool Insert(DynamicDatabase db)
+ {
+ if (db.Insert(this.GetType())
+ .Values(x => this)
+ .Execute() > 0)
+ {
+ _changedFields.Clear();
+ SetDynamicEntityState(DynamicEntityState.Existing);
+ return true;
+ }
+
+ return false;
+ }
+
+ /// Updates this object in database.
+ /// The database.
+ /// Returns true if operation was successful.
+ public virtual bool Update(DynamicDatabase db)
+ {
+ var t = GetType();
+ var mapper = DynamicMapperCache.GetMapper(t);
+ var query = db.Update(t);
+
+ MakeQueryWhere(mapper, query);
+
+ if (_changedFields.Any())
+ {
+ bool any = false;
+
+ foreach (var cf in _changedFields)
+ {
+ var cn = mapper.PropertyMap[cf.Key];
+ var pm = mapper.ColumnsMap[cn.ToLower()];
+ if (pm.Ignore)
+ continue;
+
+ if (pm.Column != null)
+ {
+ if (pm.Column.IsKey)
+ continue;
+
+ if (!pm.Column.AllowNull && cf.Value == null)
+ continue;
+ }
+
+ query.Values(cn, cf.Value);
+ any = true;
+ }
+
+ if (!any)
+ query.Set(x => this);
+ }
+ else
+ query.Set(x => this);
+
+ if (query.Execute() == 0)
+ return false;
+
+ SetDynamicEntityState(DynamicEntityState.Existing);
+ _changedFields.Clear();
+
+ return true;
+ }
+
+ /// Deletes this object from database.
+ /// The database.
+ /// Returns true if operation was successful.
+ public virtual bool Delete(DynamicDatabase db)
+ {
+ var t = this.GetType();
+ var mapper = DynamicMapperCache.GetMapper(t);
+
+ var query = db.Delete(t);
+
+ MakeQueryWhere(mapper, query);
+
+ if (query.Execute() == 0)
+ return false;
+
+ SetDynamicEntityState(DynamicEntityState.Deleted);
+
+ return true;
+ }
+
+ #endregion Insert/Update/Delete
+
+ #region Select
+
+ /// Refresh non key data from database.
+ /// The database.
+ /// All properties that are primary key values must be filled.
+ /// Returns true if operation was successful.
+ public virtual bool Refresh(DynamicDatabase db)
+ {
+ var t = this.GetType();
+ var mapper = DynamicMapperCache.GetMapper(t);
+ var query = db.From(t);
+ MakeQueryWhere(mapper, query);
+ var o = (query.Execute() as IEnumerable).FirstOrDefault();
+
+ if (o == null)
+ return false;
+
+ mapper.Map(o, this);
+
+ SetDynamicEntityState(DynamicEntityState.Existing);
+ _changedFields.Clear();
+
+ return true;
+ }
+
+ #endregion Select
+
+ #region Query Helpers
+
+ private void MakeQueryWhere(DynamicTypeMap mapper, IDynamicUpdateQueryBuilder query)
+ {
+ bool keyNotDefined = true;
+
+ foreach (var cm in mapper.ColumnsMap)
+ {
+ if (cm.Value.Column != null && cm.Value.Column.IsKey)
+ {
+ query.Where(cm.Key, DynamicColumn.CompareOperator.Eq, cm.Value.Get(this));
+ keyNotDefined = false;
+ }
+ }
+
+ if (keyNotDefined)
+ throw new InvalidOperationException(String.Format("Class '{0}' have no key columns defined",
+ this.GetType().FullName));
+ }
+
+ private void MakeQueryWhere(DynamicTypeMap mapper, IDynamicDeleteQueryBuilder query)
+ {
+ bool keyNotDefined = true;
+
+ foreach (var cm in mapper.ColumnsMap)
+ {
+ if (cm.Value.Column != null && cm.Value.Column.IsKey)
+ {
+ query.Where(cm.Key, DynamicColumn.CompareOperator.Eq, cm.Value.Get(this));
+ keyNotDefined = false;
+ }
+ }
+
+ if (keyNotDefined)
+ throw new InvalidOperationException(String.Format("Class '{0}' have no key columns defined",
+ this.GetType().FullName));
+ }
+
+ private void MakeQueryWhere(DynamicTypeMap mapper, IDynamicSelectQueryBuilder query)
+ {
+ bool keyNotDefined = true;
+
+ foreach (var cm in mapper.ColumnsMap)
+ {
+ if (cm.Value.Column != null && cm.Value.Column.IsKey)
+ {
+ var v = cm.Value.Get(this);
+
+ if (v == null)
+ throw new InvalidOperationException(String.Format("Class '{0}' have key columns {1} not filled with data.",
+ this.GetType().FullName, cm.Value.Name));
+
+ query.Where(cm.Key, DynamicColumn.CompareOperator.Eq, cm.Value.Get(this));
+ keyNotDefined = false;
+ }
+ }
+
+ if (keyNotDefined)
+ throw new InvalidOperationException(String.Format("Class '{0}' have no key columns defined",
+ this.GetType().FullName));
+ }
+
+ #endregion Query Helpers
+ }
+
+ /// Possible states of dynamic database objects.
+ public enum DynamicEntityState
+ {
+ /// Default state. This state will only permit to refresh data from database.
+ /// In this state repository will be unable to tell if object with this state should be added
+ /// or updated in database, but you can still manually perform update or insert on such object.
+ Unknown,
+
+ /// This state should be set to new objects in database.
+ New,
+
+ /// This state is ser when data is refreshed from database or object was loaded from repository.
+ Existing,
+
+ /// You can set this state to an object if you want repository to perform delete from database.
+ ToBeDeleted,
+
+ /// This state is set for objects that were deleted from database.
+ Deleted,
+ }
+
+ /// Class containing changed property data.
+ ///
+ public class DynamicPropertyChangingEventArgs : EventArgs
+ {
+ /// Gets the name of the property.
+ /// The name of the property.
+ public string PropertyName { get; private set; }
+
+ /// Gets the old property value.
+ /// The old value.
+ public object OldValue { get; private set; }
+
+ /// Gets the new property value.
+ /// The new value.
+ public object NewValue { get; private set; }
+
+ /// Initializes a new instance of the class.
+ /// Name of the property.
+ /// The old property value.
+ /// The new property value.
+ public DynamicPropertyChangingEventArgs(string propertyName, object oldValue, object newValue)
+ {
+ PropertyName = propertyName;
+ OldValue = oldValue;
+ NewValue = newValue;
+ }
+ }
+
+ /// Base repository class for specified object type.
+ /// Type of stored object.
+ public class DynamicRepositoryBase : IDisposable where T : DynamicEntityBase
+ {
+ private DynamicDatabase _database;
+
+ /// Initializes a new instance of the class.
+ /// The database.
+ public DynamicRepositoryBase(DynamicDatabase database)
+ {
+ _database = database;
+ }
+
+ /// Get all rows from database.
+ /// Objects enumerator.
+ public virtual IEnumerable GetAll()
+ {
+ return EnumerateQuery(_database.From());
+ }
+
+ /// Get rows from database by custom query.
+ /// The query.
+ /// Query must be based on object type.
+ /// Objects enumerator.
+ public virtual IEnumerable GetByQuery(IDynamicSelectQueryBuilder query)
+ {
+ return EnumerateQuery(query);
+ }
+
+ private IEnumerable EnumerateQuery(IDynamicSelectQueryBuilder query, bool forceType = true)
+ {
+ if (forceType)
+ {
+ var mapper = DynamicMapperCache.GetMapper(typeof(T));
+
+ var tn = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Name) ?
+ mapper.Type.Name : mapper.Table.Name;
+
+ if (!query.Tables.Any(t => t.Name == tn))
+ throw new InvalidOperationException(string.Format("Query is not related to '{0}' class.", typeof(T).FullName));
+ }
+
+ foreach (var o in query.Execute())
+ {
+ o.SetDynamicEntityState(DynamicEntityState.Existing);
+ yield return o;
+ }
+ }
+
+ /// Saves single object to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Save(T element)
+ {
+ return element.Save(_database);
+ }
+
+ /// Saves collection of objects to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Save(IEnumerable element)
+ {
+ return element.All(x => x.Save(_database));
+ }
+
+ /// Insert single object to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Insert(T element)
+ {
+ return element.Insert(_database);
+ }
+
+ /// Insert collection of objects to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Insert(IEnumerable element)
+ {
+ return element.All(x => x.Insert(_database));
+ }
+
+ /// Update single object to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Update(T element)
+ {
+ return element.Update(_database);
+ }
+
+ /// Update collection of objects to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Update(IEnumerable element)
+ {
+ return element.All(x => x.Update(_database));
+ }
+
+ /// Delete single object to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Delete(T element)
+ {
+ return element.Delete(_database);
+ }
+
+ /// Delete collection of objects to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Delete(IEnumerable element)
+ {
+ return element.All(x => x.Delete(_database));
+ }
+
+ /// Releases unmanaged and - optionally - managed resources.
+ public virtual void Dispose()
+ {
+ _database = null;
+ }
+ }
+ }
+
namespace Validation
{
/// Required attribute can be used to validate fields in objects using mapper class.
diff --git a/DynamORM/DynamORM.csproj b/DynamORM/DynamORM.csproj
index 5757d10..ac6b209 100644
--- a/DynamORM/DynamORM.csproj
+++ b/DynamORM/DynamORM.csproj
@@ -105,6 +105,10 @@
+
+
+
+
diff --git a/DynamORM/DynamicDatabase.cs b/DynamORM/DynamicDatabase.cs
index 7d5bade..f568dec 100644
--- a/DynamORM/DynamicDatabase.cs
+++ b/DynamORM/DynamicDatabase.cs
@@ -492,7 +492,7 @@ namespace DynamORM
}
/// Bulk update objects in database.
- /// Type of objects to update.
+ /// Type of objects to update.
/// Enumerable containing instances of objects to update.
/// Number of updated rows.
public virtual int Update(Type t, IEnumerable e)
diff --git a/DynamORM/Objects/DynamicEntityBase.cs b/DynamORM/Objects/DynamicEntityBase.cs
new file mode 100644
index 0000000..b0029b6
--- /dev/null
+++ b/DynamORM/Objects/DynamicEntityBase.cs
@@ -0,0 +1,260 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using DynamORM.Builders;
+using DynamORM.Mapper;
+using DynamORM.Validation;
+
+namespace DynamORM.Objects
+{
+ /// Base class for strong typed objects.
+ public class DynamicEntityBase
+ {
+ private Dictionary _changedFields = new Dictionary();
+ private DynamicEntityState _dynamicEntityState = DynamicEntityState.Unknown;
+
+ /// Occurs when object property is changing.
+ public event EventHandler PropertyChanging;
+
+ /// Gets the state of the dynamic entity.
+ /// Current state of entity.
+ public virtual DynamicEntityState GetDynamicEntityState() { return _dynamicEntityState; }
+
+ /// Sets the state of the dynamic entity.
+ /// The state.
+ public virtual void SetDynamicEntityState(DynamicEntityState state) { _dynamicEntityState = state; }
+
+ /// Called when object property is changing.
+ /// Name of the property.
+ /// The old property value.
+ /// The new property value.
+ protected virtual void OnPropertyChanging(string propertyName, object oldValue, object newValue)
+ {
+ OnPropertyChanging(new DynamicPropertyChangingEventArgs(propertyName, oldValue, newValue));
+ }
+
+ /// Raises the event.
+ /// The instance containing the event data.
+ protected virtual void OnPropertyChanging(DynamicPropertyChangingEventArgs e)
+ {
+ _changedFields[e.PropertyName] = e.NewValue;
+ if (PropertyChanging != null)
+ PropertyChanging(this, e);
+ }
+
+ /// Validates this object instance.
+ /// Returns list of containing results of validation.
+ public virtual IList Validate()
+ {
+ return DynamicMapperCache.GetMapper(this.GetType()).ValidateObject(this);
+ }
+
+ /// Saves this object to database.
+ /// The database.
+ /// Returns true if operation was successful.
+ /// Can be thrown when object is in invalid state.
+ public virtual bool Save(DynamicDatabase database)
+ {
+ switch (GetDynamicEntityState())
+ {
+ default:
+ case DynamicEntityState.Unknown:
+ throw new InvalidOperationException("Unknown object state. Unable to decide whish action should be performed.");
+
+ case DynamicEntityState.New:
+ return Insert(database);
+
+ case DynamicEntityState.Existing:
+ return Update(database);
+
+ case DynamicEntityState.ToBeDeleted:
+ return Delete(database);
+
+ case DynamicEntityState.Deleted:
+ throw new InvalidOperationException("Unable to do any database action on deleted object.");
+ }
+ }
+
+ #region Insert/Update/Delete
+
+ /// Inserts this object to database.
+ /// The database.
+ /// Returns true if operation was successful.
+ public virtual bool Insert(DynamicDatabase db)
+ {
+ if (db.Insert(this.GetType())
+ .Values(x => this)
+ .Execute() > 0)
+ {
+ _changedFields.Clear();
+ SetDynamicEntityState(DynamicEntityState.Existing);
+ return true;
+ }
+
+ return false;
+ }
+
+ /// Updates this object in database.
+ /// The database.
+ /// Returns true if operation was successful.
+ public virtual bool Update(DynamicDatabase db)
+ {
+ var t = GetType();
+ var mapper = DynamicMapperCache.GetMapper(t);
+ var query = db.Update(t);
+
+ MakeQueryWhere(mapper, query);
+
+ if (_changedFields.Any())
+ {
+ bool any = false;
+
+ foreach (var cf in _changedFields)
+ {
+ var cn = mapper.PropertyMap[cf.Key];
+ var pm = mapper.ColumnsMap[cn.ToLower()];
+ if (pm.Ignore)
+ continue;
+
+ if (pm.Column != null)
+ {
+ if (pm.Column.IsKey)
+ continue;
+
+ if (!pm.Column.AllowNull && cf.Value == null)
+ continue;
+ }
+
+ query.Values(cn, cf.Value);
+ any = true;
+ }
+
+ if (!any)
+ query.Set(x => this);
+ }
+ else
+ query.Set(x => this);
+
+ if (query.Execute() == 0)
+ return false;
+
+ SetDynamicEntityState(DynamicEntityState.Existing);
+ _changedFields.Clear();
+
+ return true;
+ }
+
+ /// Deletes this object from database.
+ /// The database.
+ /// Returns true if operation was successful.
+ public virtual bool Delete(DynamicDatabase db)
+ {
+ var t = this.GetType();
+ var mapper = DynamicMapperCache.GetMapper(t);
+
+ var query = db.Delete(t);
+
+ MakeQueryWhere(mapper, query);
+
+ if (query.Execute() == 0)
+ return false;
+
+ SetDynamicEntityState(DynamicEntityState.Deleted);
+
+ return true;
+ }
+
+ #endregion Insert/Update/Delete
+
+ #region Select
+
+ /// Refresh non key data from database.
+ /// The database.
+ /// All properties that are primary key values must be filled.
+ /// Returns true if operation was successful.
+ public virtual bool Refresh(DynamicDatabase db)
+ {
+ var t = this.GetType();
+ var mapper = DynamicMapperCache.GetMapper(t);
+ var query = db.From(t);
+ MakeQueryWhere(mapper, query);
+ var o = (query.Execute() as IEnumerable).FirstOrDefault();
+
+ if (o == null)
+ return false;
+
+ mapper.Map(o, this);
+
+ SetDynamicEntityState(DynamicEntityState.Existing);
+ _changedFields.Clear();
+
+ return true;
+ }
+
+ #endregion Select
+
+ #region Query Helpers
+
+ private void MakeQueryWhere(DynamicTypeMap mapper, IDynamicUpdateQueryBuilder query)
+ {
+ bool keyNotDefined = true;
+
+ foreach (var cm in mapper.ColumnsMap)
+ {
+ if (cm.Value.Column != null && cm.Value.Column.IsKey)
+ {
+ query.Where(cm.Key, DynamicColumn.CompareOperator.Eq, cm.Value.Get(this));
+ keyNotDefined = false;
+ }
+ }
+
+ if (keyNotDefined)
+ throw new InvalidOperationException(String.Format("Class '{0}' have no key columns defined",
+ this.GetType().FullName));
+ }
+
+ private void MakeQueryWhere(DynamicTypeMap mapper, IDynamicDeleteQueryBuilder query)
+ {
+ bool keyNotDefined = true;
+
+ foreach (var cm in mapper.ColumnsMap)
+ {
+ if (cm.Value.Column != null && cm.Value.Column.IsKey)
+ {
+ query.Where(cm.Key, DynamicColumn.CompareOperator.Eq, cm.Value.Get(this));
+ keyNotDefined = false;
+ }
+ }
+
+ if (keyNotDefined)
+ throw new InvalidOperationException(String.Format("Class '{0}' have no key columns defined",
+ this.GetType().FullName));
+ }
+
+ private void MakeQueryWhere(DynamicTypeMap mapper, IDynamicSelectQueryBuilder query)
+ {
+ bool keyNotDefined = true;
+
+ foreach (var cm in mapper.ColumnsMap)
+ {
+ if (cm.Value.Column != null && cm.Value.Column.IsKey)
+ {
+ var v = cm.Value.Get(this);
+
+ if (v == null)
+ throw new InvalidOperationException(String.Format("Class '{0}' have key columns {1} not filled with data.",
+ this.GetType().FullName, cm.Value.Name));
+
+ query.Where(cm.Key, DynamicColumn.CompareOperator.Eq, cm.Value.Get(this));
+ keyNotDefined = false;
+ }
+ }
+
+ if (keyNotDefined)
+ throw new InvalidOperationException(String.Format("Class '{0}' have no key columns defined",
+ this.GetType().FullName));
+ }
+
+ #endregion Query Helpers
+ }
+}
\ No newline at end of file
diff --git a/DynamORM/Objects/DynamicEntityState.cs b/DynamORM/Objects/DynamicEntityState.cs
new file mode 100644
index 0000000..5744546
--- /dev/null
+++ b/DynamORM/Objects/DynamicEntityState.cs
@@ -0,0 +1,23 @@
+namespace DynamORM.Objects
+{
+ /// Possible states of dynamic database objects.
+ public enum DynamicEntityState
+ {
+ /// Default state. This state will only permit to refresh data from database.
+ /// In this state repository will be unable to tell if object with this state should be added
+ /// or updated in database, but you can still manually perform update or insert on such object.
+ Unknown,
+
+ /// This state should be set to new objects in database.
+ New,
+
+ /// This state is ser when data is refreshed from database or object was loaded from repository.
+ Existing,
+
+ /// You can set this state to an object if you want repository to perform delete from database.
+ ToBeDeleted,
+
+ /// This state is set for objects that were deleted from database.
+ Deleted,
+ }
+}
\ No newline at end of file
diff --git a/DynamORM/Objects/DynamicPropertyChangingEventArgs.cs b/DynamORM/Objects/DynamicPropertyChangingEventArgs.cs
new file mode 100644
index 0000000..f06ea35
--- /dev/null
+++ b/DynamORM/Objects/DynamicPropertyChangingEventArgs.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace DynamORM.Objects
+{
+ /// Class containing changed property data.
+ ///
+ public class DynamicPropertyChangingEventArgs : EventArgs
+ {
+ /// Gets the name of the property.
+ /// The name of the property.
+ public string PropertyName { get; private set; }
+
+ /// Gets the old property value.
+ /// The old value.
+ public object OldValue { get; private set; }
+
+ /// Gets the new property value.
+ /// The new value.
+ public object NewValue { get; private set; }
+
+ /// Initializes a new instance of the class.
+ /// Name of the property.
+ /// The old property value.
+ /// The new property value.
+ public DynamicPropertyChangingEventArgs(string propertyName, object oldValue, object newValue)
+ {
+ PropertyName = propertyName;
+ OldValue = oldValue;
+ NewValue = newValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DynamORM/Objects/DynamicRepositoryBase.cs b/DynamORM/Objects/DynamicRepositoryBase.cs
new file mode 100644
index 0000000..e954572
--- /dev/null
+++ b/DynamORM/Objects/DynamicRepositoryBase.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using DynamORM.Builders;
+using DynamORM.Mapper;
+
+namespace DynamORM.Objects
+{
+ /// Base repository class for specified object type.
+ /// Type of stored object.
+ public class DynamicRepositoryBase : IDisposable where T : DynamicEntityBase
+ {
+ private DynamicDatabase _database;
+
+ /// Initializes a new instance of the class.
+ /// The database.
+ public DynamicRepositoryBase(DynamicDatabase database)
+ {
+ _database = database;
+ }
+
+ /// Get all rows from database.
+ /// Objects enumerator.
+ public virtual IEnumerable GetAll()
+ {
+ return EnumerateQuery(_database.From());
+ }
+
+ /// Get rows from database by custom query.
+ /// The query.
+ /// Query must be based on object type.
+ /// Objects enumerator.
+ public virtual IEnumerable GetByQuery(IDynamicSelectQueryBuilder query)
+ {
+ return EnumerateQuery(query);
+ }
+
+ private IEnumerable EnumerateQuery(IDynamicSelectQueryBuilder query, bool forceType = true)
+ {
+ if (forceType)
+ {
+ var mapper = DynamicMapperCache.GetMapper(typeof(T));
+
+ var tn = mapper.Table == null || string.IsNullOrEmpty(mapper.Table.Name) ?
+ mapper.Type.Name : mapper.Table.Name;
+
+ if (!query.Tables.Any(t => t.Name == tn))
+ throw new InvalidOperationException(string.Format("Query is not related to '{0}' class.", typeof(T).FullName));
+ }
+
+ foreach (var o in query.Execute())
+ {
+ o.SetDynamicEntityState(DynamicEntityState.Existing);
+ yield return o;
+ }
+ }
+
+ /// Saves single object to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Save(T element)
+ {
+ return element.Save(_database);
+ }
+
+ /// Saves collection of objects to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Save(IEnumerable element)
+ {
+ return element.All(x => x.Save(_database));
+ }
+
+ /// Insert single object to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Insert(T element)
+ {
+ return element.Insert(_database);
+ }
+
+ /// Insert collection of objects to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Insert(IEnumerable element)
+ {
+ return element.All(x => x.Insert(_database));
+ }
+
+ /// Update single object to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Update(T element)
+ {
+ return element.Update(_database);
+ }
+
+ /// Update collection of objects to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Update(IEnumerable element)
+ {
+ return element.All(x => x.Update(_database));
+ }
+
+ /// Delete single object to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Delete(T element)
+ {
+ return element.Delete(_database);
+ }
+
+ /// Delete collection of objects to database.
+ /// The element.
+ /// Returns true if operation was successful.
+ public virtual bool Delete(IEnumerable element)
+ {
+ return element.All(x => x.Delete(_database));
+ }
+
+ /// Releases unmanaged and - optionally - managed resources.
+ public virtual void Dispose()
+ {
+ _database = null;
+ }
+ }
+}
\ No newline at end of file