设计自己的数据访问层(2)数据上下文基类
接上篇数据上下文基类是上下文接口的实现类,其给出了接口的 部分实现,具体的上下文类可以继承自上下文基类
上下文基类的代码如下:
private bool isInTransaction = false;
private bool isDirty = false;
private List<ScheduledAction> actions = new List<ScheduledAction>();
private IdentityMap identityMap = new IdentityMap();
protected abstract IDataMapper<T> GetDataMapper<T>();
protected abstract void ExecuteScheduledAction(ScheduledAction action);
#region IObjectSpaceServices Members
/// <summary>
/// Reports whether this <c>ObjectSpaceServices</c> contain any changes which must be synchronized with the database
/// </summary>
public bool IsDirty
{
get { return isDirty; }
private set { isDirty = value; }
}
/// <summary>
/// Reports whether this <c>ObjectSpaceServices</c> is working transactionally
/// </summary>
public bool IsInTransaction
{
get { return isInTransaction; }
private set { isInTransaction = value; }
}
public T GetById<T>(object key) where T : class, new()
{
T item = (T)identityMap.GetObject(typeof(T), key);
if (item == null)
{
item = GetDataMapper<T>().GetByKey(key);
identityMap.PutObject(item, key);
}
return item;
}
public IList<T> GetAll<T>() where T : class, new()
{
return GetDataMapper<T>().GetAll();
}
public IList<T> GetAll<T>(int pageIndex, int pageSize) where T : class, new()
{
throw new NotImplementedException("The method or operation is not implemented.");
}
public IList<T> GetByCriteria<T>(Query query) where T : class, new()
{
return GetDataMapper<T>().GetByCriteria(query);
}
public IList<T> GetByCriteria<T>(Query query, int pageIndex, int pageSize) where T : class, new()
{
throw new NotImplementedException("The method or operation is not implemented.");
}
public virtual int GetCount<T>()
{
throw new NotImplementedException();
}
public virtual int GetCount<T>(Query query)
{
throw new NotImplementedException();
}
private void ManageAction(ScheduledAction action)
{
if (this.IsInTransaction)
{
actions.Add(action);
}
else
{
this.ExecuteScheduledAction(action);
}
}
public void Add(object item)
{
if (item == null)
{
throw new ArgumentNullException();
}
ScheduledAction action = new ScheduledAction(item, ScheduledAction.ActionType.Create);
ManageAction(action);
}
public void Save(object item)
{
if (item == null)
{
throw new ArgumentNullException();
}
ScheduledAction action = new ScheduledAction(item, ScheduledAction.ActionType.Update);
ManageAction(action);
}
public void Delete(object item)
{
if (item == null)
{
throw new ArgumentNullException();
}
ScheduledAction action = new ScheduledAction(item, ScheduledAction.ActionType.Delete);
ManageAction(action);
}
/// <summary>
/// Begins a transaction
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if there is an already active transaction</exception>
public void BeginTransaction()
{
if (this.IsInTransaction)
{
throw new InvalidOperationException("A transaction is already opened");
}
else
{
this.IsInTransaction = true;
}
}
/// <summary>
/// Commits the active transaction
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if there isn't an active transaction</exception>
public void Commit()
{
if (!this.IsInTransaction)
{
throw new InvalidOperationException("Operation requires an opened transaction");
}
else
{
foreach (ScheduledAction action in actions)
{
DomainObject target = action.Target as DomainObject;
if (target != null && !target.IsValid) //TODO: Enhance this
{
throw new ApplicationException(string.Format("Validation failed for object type: {0}", target.GetType().Name));
}
}
using (TransactionScope tx = new TransactionScope())
{
actions.ForEach(delegate(ScheduledAction action)
{
this.ExecuteScheduledAction(action);
}
);
tx.Complete();
}
actions.Clear();
this.IsInTransaction = false;
}
}
/// <summary>
/// Rollbacks the active transaction
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if there isn't an active transaction</exception>
public void Rollback()
{
if (!this.IsInTransaction)
{
throw new InvalidOperationException("Operation requires an opened transaction");
}
else
{
this.IsInTransaction = false;
}
}
#endregion
#region IDisposable Members
public void Dispose()
{
if (this.IsInTransaction)
{
this.Rollback();
}
}
#endregion
}
private bool isDirty = false;
private List<ScheduledAction> actions = new List<ScheduledAction>();
private IdentityMap identityMap = new IdentityMap();
protected abstract IDataMapper<T> GetDataMapper<T>();
protected abstract void ExecuteScheduledAction(ScheduledAction action);
#region IObjectSpaceServices Members
/// <summary>
/// Reports whether this <c>ObjectSpaceServices</c> contain any changes which must be synchronized with the database
/// </summary>
public bool IsDirty
{
get { return isDirty; }
private set { isDirty = value; }
}
/// <summary>
/// Reports whether this <c>ObjectSpaceServices</c> is working transactionally
/// </summary>
public bool IsInTransaction
{
get { return isInTransaction; }
private set { isInTransaction = value; }
}
public T GetById<T>(object key) where T : class, new()
{
T item = (T)identityMap.GetObject(typeof(T), key);
if (item == null)
{
item = GetDataMapper<T>().GetByKey(key);
identityMap.PutObject(item, key);
}
return item;
}
public IList<T> GetAll<T>() where T : class, new()
{
return GetDataMapper<T>().GetAll();
}
public IList<T> GetAll<T>(int pageIndex, int pageSize) where T : class, new()
{
throw new NotImplementedException("The method or operation is not implemented.");
}
public IList<T> GetByCriteria<T>(Query query) where T : class, new()
{
return GetDataMapper<T>().GetByCriteria(query);
}
public IList<T> GetByCriteria<T>(Query query, int pageIndex, int pageSize) where T : class, new()
{
throw new NotImplementedException("The method or operation is not implemented.");
}
public virtual int GetCount<T>()
{
throw new NotImplementedException();
}
public virtual int GetCount<T>(Query query)
{
throw new NotImplementedException();
}
private void ManageAction(ScheduledAction action)
{
if (this.IsInTransaction)
{
actions.Add(action);
}
else
{
this.ExecuteScheduledAction(action);
}
}
public void Add(object item)
{
if (item == null)
{
throw new ArgumentNullException();
}
ScheduledAction action = new ScheduledAction(item, ScheduledAction.ActionType.Create);
ManageAction(action);
}
public void Save(object item)
{
if (item == null)
{
throw new ArgumentNullException();
}
ScheduledAction action = new ScheduledAction(item, ScheduledAction.ActionType.Update);
ManageAction(action);
}
public void Delete(object item)
{
if (item == null)
{
throw new ArgumentNullException();
}
ScheduledAction action = new ScheduledAction(item, ScheduledAction.ActionType.Delete);
ManageAction(action);
}
/// <summary>
/// Begins a transaction
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if there is an already active transaction</exception>
public void BeginTransaction()
{
if (this.IsInTransaction)
{
throw new InvalidOperationException("A transaction is already opened");
}
else
{
this.IsInTransaction = true;
}
}
/// <summary>
/// Commits the active transaction
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if there isn't an active transaction</exception>
public void Commit()
{
if (!this.IsInTransaction)
{
throw new InvalidOperationException("Operation requires an opened transaction");
}
else
{
foreach (ScheduledAction action in actions)
{
DomainObject target = action.Target as DomainObject;
if (target != null && !target.IsValid) //TODO: Enhance this
{
throw new ApplicationException(string.Format("Validation failed for object type: {0}", target.GetType().Name));
}
}
using (TransactionScope tx = new TransactionScope())
{
actions.ForEach(delegate(ScheduledAction action)
{
this.ExecuteScheduledAction(action);
}
);
tx.Complete();
}
actions.Clear();
this.IsInTransaction = false;
}
}
/// <summary>
/// Rollbacks the active transaction
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if there isn't an active transaction</exception>
public void Rollback()
{
if (!this.IsInTransaction)
{
throw new InvalidOperationException("Operation requires an opened transaction");
}
else
{
this.IsInTransaction = false;
}
}
#endregion
#region IDisposable Members
public void Dispose()
{
if (this.IsInTransaction)
{
this.Rollback();
}
}
#endregion
}