仓储提供了访问域对象
中
内存的集合接口。所以,是关注的重点部分,当操作域对象时仓储就像一个集合。为如何添加/删除到存储库的调用提供内部机制,调用的数据存储抽象转换成实际的数据访问。对象可以从一个简单的对象集合仓储中删除,映射代码封装库进行相应的操作幕后。从概念上讲,一个存储库保存在数据存储和在他们所执行的操作,提供一个更面向对象的持久层封装的对象集。 Repository还支持一个干净的分离和域之间的单向依赖和数据映射层实现的目标。
因此,仓储让我们得到了一个很好的抽象,为我们提供了持久性的很好地分离关注的责任。
public interface IRepository<E, C>
{
DbTransaction BeginTransaction();
void Add(E entity);
void AddOrAttach(E entity);
void DeleteRelatedEntries(E entity);
void DeleteRelatedEntries
(E entity, ObservableCollection<string> keyListOfIgnoreEntites);
void Delete(E entity);
int Save();
ObjectQuery<E> DoQuery(string entitySetName);
ObjectQuery<E> DoQuery();
ObjectQuery<E> DoQuery(string entitySetName, ISpecification<E> where);
ObjectQuery<E> DoQuery(ISpecification<E> where);
ObjectQuery<E> DoQuery(int maximumRows, int startRowIndex);
ObjectQuery<E> DoQuery(Expression<Func<E, object>> sortExpression);
ObjectQuery<E> DoQuery(Expression<Func<E, object>> sortExpression,
int maximumRows, int startRowIndex);
IList<E> SelectAll(string entitySetName);
IList<E> SelectAll();
IList<E> SelectAll(string entitySetName, ISpecification<E> where);
IList<E> SelectAll(ISpecification<E> where);
IList<E> SelectAll(int maximumRows, int startRowIndex);
IList<E> SelectAll(Expression<Func<E, object>> sortExpression);
IList<E> SelectAll(Expression<Func<E, object>> sortExpression,
int maximumRows, int startRowIndex);
E SelectByKey(string Key);
bool TrySameValueExist(string fieldName, object fieldValue, string key);
bool TryEntity(ISpecification<E> selectSpec);
int GetCount();
int GetCount(ISpecification<E> selectSpec);
}
public class Repository<E, C> : IRepository<E, C>, IDisposable
where E : EntityObject
where C : ObjectContext
{
private readonly C _ctx;
private string _KeyProperty = "ID";
public string KeyProperty
{
get
{
return _KeyProperty;
}
set
{
_KeyProperty = value;
}
}
public C Session
{
get { return _ctx; }
}
public Repository(C session)
{
_ctx = session;
}
#region IRepository<E,C> Members
public int Save()
{
return _ctx.SaveChanges();
}
/// <summary>
/// A generic method to return ALL the entities
/// </summary>
/// <param name=”entitySetName”>
/// The EntitySet name of the entity in the model.
/// </param>
/// <typeparam name=”TEntity”>
/// The Entity to load from the database.
/// </typeparam>
/// <returns>Returns a set of TEntity.</returns>
public ObjectQuery<E> DoQuery(string entitySetName)
{
return _ctx.CreateQuery<E>("[" + entitySetName + "]");
}
/// <summary>
/// A generic method to return ALL the entities
/// </summary>
/// <typeparam name=”TEntity”>
/// The Entity to load from the database.
/// </typeparam>
/// <returns>Returns a set of TEntity.</returns>
public ObjectQuery<E> DoQuery()
{
return _ctx.CreateQuery<E>("[" + typeof(E).Name + "]");
}
/// <summary>
/// </summary>
/// <param name=”entitySetName”>
/// The EntitySet name of the entity in the model.
/// </param>
/// <typeparam name=”TEntity”>
/// The Entity to load from the database.
/// </typeparam>
/// <returns>Returns a set of TEntity.</returns>
public ObjectQuery<E> DoQuery(string entitySetName, ISpecification<E> where)
{
return
(ObjectQuery<E>)_ctx.CreateQuery<E>("[" + entitySetName + "]")
.Where(where.EvalPredicate);
}
/// <summary>
/// </summary>
/// <typeparam name=”TEntity”>
/// The Entity to load from the database.
/// </typeparam>
/// <returns>Returns a set of TEntity.</returns>
public ObjectQuery<E> DoQuery(ISpecification<E> where)
{
return
(ObjectQuery<E>)_ctx.CreateQuery<E>("[" + typeof(E).Name + "]")
.Where(where.EvalPredicate);
}
/// <summary>
/// Query Entity with Paging
/// </summary>
/// <param name="maximumRows">Max no of row to Fetch</param>
/// <param name="startRowIndex">Start Index</param>
/// <returns>Collection of Entities</returns>
public ObjectQuery<E> DoQuery(int maximumRows, int startRowIndex)
{
return (ObjectQuery<E>)_ctx.CreateQuery<E>
("[" + typeof(E).Name + "]").Skip<E>(startRowIndex).Take(maximumRows);
}
/// <summary>
/// Query Entity in sorted Order
/// </summary>
/// <param name="sortExpression">Sort Expression/condition</param>
/// <param name="ErrorCode">custom Error Message</param>
/// <returns>Collection of Entities</returns>
public ObjectQuery<E> DoQuery(Expression<Func<E, object>> sortExpression)
{
if (null == sortExpression)
{
return ((IRepository<E, C>)this).DoQuery();
}
return (ObjectQuery<E>)((IRepository<E, C>)this).DoQuery().OrderBy
<E, object>(sortExpression);
}
/// <summary>
/// Query All Entity in sorted Order with Paging support
/// </summary>
/// <param name="sortExpression">Sort Expression/condition</param>
/// <param name="maximumRows">Max no of row to Fetch</param>
/// <param name="startRowIndex">Start Index</param>
/// <returns>Collection Of entities</returns>
public ObjectQuery<E> DoQuery(Expression<Func<E, object>>
sortExpression, int maximumRows, int startRowIndex)
{
if (sortExpression == null)
{
return ((IRepository<E, C>)this).DoQuery(maximumRows, startRowIndex);
}
return (ObjectQuery<E>)((IRepository<E, C>)this).DoQuery
(sortExpression).Skip<E>(startRowIndex).Take(maximumRows);
}
/// <summary>
/// A generic method to return ALL the entities
/// </summary>
/// <param name=”entitySetName”>
/// The EntitySet name of the entity in the model.
/// </param>
/// <typeparam name=”TEntity”>
/// The Entity to load from the database.
/// </typeparam>
/// <returns>Returns a set of TEntity.</returns>
public IList<E> SelectAll(string entitySetName)
{
return DoQuery(entitySetName).ToList();
}
/// <summary>
/// A generic method to return ALL the entities
/// </summary>
/// <typeparam name=”TEntity”>
/// The Entity to load from the database.
/// </typeparam>
/// <returns>Returns a set of TEntity.</returns>
public IList<E> SelectAll()
{
try
{
return DoQuery().ToList(); //_ctx.CreateQuery<E>("[" + typeof(E).Name + "]");
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// A generic method to return ALL the entities
/// </summary>
/// <param name=”entitySetName”>
/// The EntitySet name of the entity in the model.
/// </param>
/// <typeparam name=”TEntity”>
/// The Entity to load from the database.
/// </typeparam>
/// <returns>Returns a set of TEntity.</returns>
public IList<E> SelectAll(string entitySetName, ISpecification<E> where)
{
return DoQuery(entitySetName, where).ToList();
}
/// <summary>
/// A generic method to return ALL the entities
/// </summary>
/// <typeparam name=”TEntity”>
/// The Entity to load from the database.
/// </typeparam>
/// <returns>Returns a set of TEntity.</returns>
public IList<E> SelectAll(ISpecification<E> where)
{
return DoQuery(where).ToList();
}
/// <summary>
/// Select All Entity with Paging
/// </summary>
/// <param name="maximumRows">Max no of row to Fetch</param>
/// <param name="startRowIndex">Start Index</param>
/// <returns>Collection of Entities</returns>
public IList<E> SelectAll(int maximumRows, int startRowIndex)
{
return DoQuery(maximumRows, startRowIndex).ToList();
}
/// <summary>
/// Select All Entity in sorted Order
/// </summary>
/// <param name="sortExpression">Sort Expression/condition</param>
/// <param name="ErrorCode">custom Error Message</param>
/// <returns>Collection of Entities</returns>
public IList<E> SelectAll(Expression<Func<E, object>> sortExpression)
{
if (null == sortExpression)
{
return DoQuery(sortExpression).ToList();
}
return DoQuery(sortExpression).ToList();
}
/// <summary>
/// Select All Entity in sorted Order with Paging support
/// </summary>
/// <param name="sortExpression">Sort Expression/condition</param>
/// <param name="maximumRows">Max no of row to Fetch</param>
/// <param name="startRowIndex">Start Index</param>
/// <returns>Collection Of entities</returns>
public IList<E> SelectAll(Expression<Func<E, object>>
sortExpression, int maximumRows, int startRowIndex)
{
if (sortExpression == null)
{
return DoQuery(maximumRows, startRowIndex).ToList();
}
return DoQuery(sortExpression, maximumRows, startRowIndex).ToList();
}
/// <summary>
/// Get Entity By Primary Key
/// </summary>
/// <typeparam name="E">Entity Type</typeparam>
/// <param name="Key">Primary Key Value</param>
/// <returns>return entity</returns>
public E SelectByKey(string Key)
{
// First we define the parameter that we are going to use the clause.
var xParam = Expression.Parameter(typeof(E), typeof(E).Name);
MemberExpression leftExpr = MemberExpression.Property(xParam, this._KeyProperty);
Expression rightExpr = Expression.Constant(Key);
BinaryExpression binaryExpr = MemberExpression.Equal(leftExpr, rightExpr);
//Create Lambda Expression for the selection
Expression<Func<E, bool>> lambdaExpr =
Expression.Lambda<Func<E, bool>>(binaryExpr,
new ParameterExpression[] { xParam });
//Searching ....
IList<E> resultCollection = ((IRepository<E, C>)this).SelectAll
(new Specification<E>(lambdaExpr));
if (null != resultCollection && resultCollection.Count() > 0)
{
//return valid single result
return resultCollection.First<E>();
}//end if
return null;
}
/// <summary>
/// Check if value of specific field is already exist
/// </summary>
/// <typeparam name="E"></typeparam>
/// <param name="fieldName">name of the Field</param>
/// <param name="fieldValue">Field value</param>
/// <param name="key">Primary key value</param>
/// <returns>True or False</returns>
public bool TrySameValueExist(string fieldName, object fieldValue, string key)
{
// First we define the parameter that we are going to use the clause.
var xParam = Expression.Parameter(typeof(E), typeof(E).Name);
MemberExpression leftExprFieldCheck =
MemberExpression.Property(xParam, fieldName);
Expression rightExprFieldCheck = Expression.Constant(fieldValue);
BinaryExpression binaryExprFieldCheck =
MemberExpression.Equal(leftExprFieldCheck, rightExprFieldCheck);
MemberExpression leftExprKeyCheck =
MemberExpression.Property(xParam, this._KeyProperty);
Expression rightExprKeyCheck = Expression.Constant(key);
BinaryExpression binaryExprKeyCheck =
MemberExpression.NotEqual(leftExprKeyCheck, rightExprKeyCheck);
BinaryExpression finalBinaryExpr =
Expression.And(binaryExprFieldCheck, binaryExprKeyCheck);
//Create Lambda Expression for the selection
Expression<Func<E, bool>> lambdaExpr =
Expression.Lambda<Func<E, bool>>(finalBinaryExpr,
new ParameterExpression[] { xParam });
//Searching ....
return ((IRepository<E, C>)this).TryEntity(new Specification<E>(lambdaExpr));
}
/// <summary>
/// Check if Entities exist with Condition
/// </summary>
/// <param name="selectExpression">Selection Condition</param>
/// <returns>True or False</returns>
public bool TryEntity(ISpecification<E> selectSpec)
{
return _ctx.CreateQuery<E>("[" + typeof(E).Name + "]").Any<E>
(selectSpec.EvalPredicate);
}
/// <summary>
/// Get Count of all records
/// </summary>
/// <typeparam name="E"></typeparam>
/// <returns>count of all records</returns>
public int GetCount()
{
return _ctx.CreateQuery<E>("[" + typeof(E).Name + "]").Count();
}
/// <summary>
/// Get count of selection
/// </summary>
/// <typeparam name="E">Selection Condition</typeparam>
/// <returns>count of selection</returns>
public int GetCount(ISpecification<E> selectSpec)
{
return _ctx.CreateQuery<E>("[" + typeof(E).Name + "]")
.Where(selectSpec.EvalPredicate).Count();
}
/// <summary>
/// Delete data from context
/// </summary>
/// <typeparam name="E"></typeparam>
/// <param name="entity"></param>
public void Delete(E entity)
{
_ctx.DeleteObject(entity);
}
/// <summary>
/// Delete data from context
/// </summary>
/// <typeparam name="E"></typeparam>
/// <param name="entity"></param>
public void Delete(object entity)
{
_ctx.DeleteObject(entity);
}
/// <summary>
/// Insert new data into context
/// </summary>
/// <typeparam name="E"></typeparam>
/// <param name="entity"></param>
public void Add(E entity)
{
_ctx.AddObject(entity.GetType().Name, entity);
}
/// <summary>
/// Insert if new otherwise attach data into context
/// </summary>
/// <param name="entity"></param>
public void AddOrAttach(E entity)
{
// Define an ObjectStateEntry and EntityKey for the current object.
EntityKey key;
object originalItem;
// Get the detached object's entity key.
if (entity.EntityKey == null)
{
// Get the entity key of the updated object.
key = _ctx.CreateEntityKey(entity.GetType().Name, entity);
}
else
{
key = entity.EntityKey;
}
try
{
// Get the original item based on the entity key from the context
// or from the database.
if (_ctx.TryGetObjectByKey(key, out originalItem))
{//accept the changed property
if (originalItem is EntityObject &&
((EntityObject)originalItem).EntityState != EntityState.Added)
{
// Call the ApplyPropertyChanges method to apply changes
// from the updated item to the original version.
_ctx.ApplyCurrentValues(key.EntitySetName, entity);
}
}
else
{//add the new entity
Add(entity);
}//end else
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Start Transaction
/// </summary>
/// <returns></returns>
public DbTransaction BeginTransaction()
{
if (_ctx.Connection.State != ConnectionState.Open)
{
_ctx.Connection.Open();
}
return _ctx.Connection.BeginTransaction();
}
/// <summary>
/// Delete all related entries
/// </summary>
/// <param name="entity"></param>
public void DeleteRelatedEntries(E entity)
{
foreach (var relatedEntity in (((IEntityWithRelationships)entity).
RelationshipManager.GetAllRelatedEnds().SelectMany(re =>
re.CreateSourceQuery().OfType<EntityObject>()).Distinct()).ToArray())
{
_ctx.DeleteObject(relatedEntity);
}//end foreach
}
/// <summary>
/// Delete all related entries
/// </summary>
/// <param name="entity"></param>
public void DeleteRelatedEntries(E entity, ObservableCollection<string>
keyListOfIgnoreEntites)
{
foreach (var relatedEntity in (((IEntityWithRelationships)entity).
RelationshipManager.GetAllRelatedEnds().SelectMany(re =>
re.CreateSourceQuery().OfType<EntityObject>()).Distinct()).ToArray())
{
PropertyInfo propInfo = relatedEntity.GetType().GetProperty
(this._KeyProperty);
if (null != propInfo)
{
string value = (string)propInfo.GetValue(relatedEntity, null);
if (!string.IsNullOrEmpty(value) &&
keyListOfIgnoreEntites.Contains(value))
{
continue;
}//end if
}//end if
_ctx.DeleteObject(relatedEntity);
}//end foreach
}
#endregion
#region IDisposable Members
public void Dispose()
{
if (null != _ctx)
{
_ctx.Dispose();
}
}
#endregion
}
public interface ISpecification<E>
{
/// <summary>
/// Select/Where Expression
/// </summary>
Expression<Func<E, bool>> EvalPredicate { get; }
/// <summary>
/// Function to evaluate where Expression
/// </summary>
Func<E, bool> EvalFunc { get; }
}
public class Specification<E> : ISpecification<E>
{
#region Private Members
private Func<E, bool> _evalFunc = null;
private Expression<Func<E, bool>> _evalPredicate;
#endregion
#region Virtual Accessors
public virtual Expression<Func<E, bool>> EvalPredicate
{
get { return _evalPredicate; }
}
public virtual Func<E, bool> EvalFunc
{
get { return _evalFunc; }
}
#endregion
#region Constructors
public Specification(Expression<Func<E, bool>> predicate)
{
_evalPredicate = predicate;
}
private Specification() { }
#endregion
}