我正在努力更新到我的MVC 4项目中更易于管理的存储库模式,该模式首先使用Entity Framework代码。我已经集成了一个通用的基础存储库类,它将执行基本的CRUD操作,因此我不必在我创建的每个存储库中实现这些。我遇到了一个问题,如果实体是一种TrackableEntity,我的All方法需要通过删除标志来过滤查询。由于实体在基本存储库中是通用的,我试图将其转换为一种TrackableEntity,其中只会导致以下错误消息。
不支持带有“NameSpace.Models.ClientFormField”类型输入的“TypeAs”表达式和“NameSpace.Models.TrackableEntity”类型的检查。 LINQ to Entities查询中仅支持实体类型和复杂类型。
此错误使得完成,因为我理解为什么我的代码不起作用,但我试图找到一种方法来过滤掉已删除的项目,而不必在我的所有存储库中覆盖此方法。我对All方法的代码如下。
public virtual IEnumerable<T> All()
{
if (typeof(T).IsSubclassOf(typeof(TrackableEntity)))
return dbSet.Where(e => !(e as TrackableEntity).IsDeleted).ToList();
return dbSet.ToList();
}
我知道我可以做以下事情
public virtual IEnumerable<T> All(Expression<Func<T, bool>> predicate = null)
{
if (predicate != null)
return dbSet.Where(predicate).IsDeleted).ToList();
return dbSet.ToList();
}
然后将其添加到我的所有存储库
public override IEnumerable<CaseType> All(Expression<Func<CaseType,bool>> predicate = null)
{
if (predicate == null)
predicate = e => !e.IsDeleted;
return base.All(predicate);
}
我遇到的问题是我正在复制代码,这基本上是复制并粘贴到我的所有存储库中,这使得更改为新的存储库模式的目的失败了。我切换到了我的存储库中的重复代码。
以下是我的某个实体的示例。
public class CaseType : TrackableEntity, IValidatableObject
{
public int Id { get; set; }
public string Name { get; set; }
public bool InUse { get; set; }
public bool IsValid { get { return !this.Validate(null).Any(); } }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (String.IsNullOrEmpty(Name))
yield return new ValidationResult("Case Type name cannot be blank", new[] { "Name" });
//Finish Validation Rules
}
}
TrackableEntity
public abstract class TrackableEntity
{
public bool Active { get; set; }
public bool IsDeleted { get; set; }
public virtual User CreatedBy { get; set; }
public virtual User ModifiedBy { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
}
对此的任何帮助都将非常感激。
答案 0 :(得分:1)
我终于找到了一个我很满意的解决方案。我最终制作了2个通用存储库。一个是基本存储库,它处理所有实体继承的BaseEntity对数据库的所有调用。然后我制作了我的第二个通用仓库,它继承了BaesEntity并覆盖了一些方法来处理我的TrackableEntities的需求。最后,通过处理repo中软删除项目的过滤,我可以满足我的需求,同时也为TrackableEntity提供了更大的灵活性。
BaseRepository -
public class BaseRepository<T> : IBaseRepository<T> where T : BaseEntity
{
private readonly IAppDb _db;
private readonly IDbSet<T> _dbSet;
public BaseRepository(IAppDb db)
{
_db = db;
_dbSet = Lwdb.Set<T>();
}
protected IAppDb Lwdb
{
get { return _db; }
}
#region IBaseRepository<T> Members
public virtual T GetById(int id)
{
return _dbSet.Find(id);
}
public virtual T Add(T entity)
{
_dbSet.Add(entity);
_db.Commit();
return entity;
}
public virtual bool Any(Expression<Func<T, bool>> expression)
{
return _dbSet.Any(expression);
}
public virtual void Delete(T entity)
{
_dbSet.Remove(entity);
_db.Commit();
}
public virtual IEnumerable<T> All()
{
return _dbSet.ToList();
}
public virtual T Update(T entity, bool attachOnly = false)
{
_dbSet.Attach(entity);
_db.SetModified(entity);
if (!attachOnly) _db.Commit();
return entity;
}
#endregion
protected User GetCurrentUser()
{
return
_db.Set<User>().Find(HttpContext.Current != null ? ((User) HttpContext.Current.Session["User"]).Id : 1);
}
BaseTrackableEntityRepository -
public class BaseTrackableEntityRepository<T> : BaseRepository<T>, IBaseTrackableEntityRepository<T>
where T : TrackableEntity
{
private readonly IAppDb _db;
private readonly IDbSet<T> _teDB;
public BaseTrackableEntityRepository(IAppDb db)
: base(db)
{
_db = db;
_teDB = _db.Set<T>();
}
#region IBaseTrackableEntityRepository<T> Members
public virtual T SetDeleteFlag(int id)
{
var entity = _teDB.Find(id);
if (entity == null) return null; //throw exception
entity.IsDeleted = true;
entity.DateModified = DateTime.Now;
entity.ModifiedBy = GetCurrentUser();
return Update(entity);
}
public override IEnumerable<T> All()
{
return _teDB.Where(e => !e.IsDeleted).ToList();
}
public override T Add(T entity)
{
var curUser = GetCurrentUser();
entity.CreatedBy = curUser;
entity.ModifiedBy = curUser;
entity.DateCreated = DateTime.Now;
entity.DateModified = DateTime.Now;
entity.Active = true;
entity.IsDeleted = false;
_teDB.Add(entity);
_db.Commit();
return entity;
}
public override T Update(T entity, bool attachOnly = false)
{
InsertTeData(ref entity);
entity.ModifiedBy = GetCurrentUser();
entity.DateModified = DateTime.Now;
_teDB.Attach(entity);
_db.SetModified(entity);
if (!attachOnly) _db.Commit();
return entity;
}
public virtual T SetStatus(int id, bool status)
{
var entity = _teDB.Find(id);
if (entity == null) return null;
entity.Active = status;
return Update(entity);
}
#endregion
private void InsertTeData(ref T entity)
{
if (entity == null || entity == null) return;
var dbEntity = GetById(entity.Id);
if (dbEntity == null) return;
_db.Detach(dbEntity);
entity.CreatedBy = dbEntity.CreatedBy;
entity.DateCreated = dbEntity.DateCreated;
entity.ModifiedBy = dbEntity.ModifiedBy;
entity.DateModified = dbEntity.DateModified;
}