1

我正在努力在我的 MVC 4 项目中更新到更易于管理的存储库模式,该模式首先使用实体​​框架代码。我已经集成了一个通用的基础存储库类,它将执行基本的 CRUD 操作,因此我不必在我创建的每个存储库中实现这些。我遇到了一个问题,如果实体是 TrackableEntity 类型,我的 All 方法需要通过已删除标志过滤查询。由于实体在基本存储库中是通用的,因此我尝试将其转换为 TrackableEntity 的类型,这只会导致以下错误消息。

不支持具有“NameSpace.Models.ClientFormField”类型输入和“NameSpace.Models.TrackableEntity”类型检查的“TypeAs”表达式。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; }
}

对此的任何帮助将不胜感激。

4

1 回答 1

1

我终于得到了一个令我满意的解决方案。我最终制作了 2 个通用存储库。一个是基础存储库,它处理所有实体继承自我的 BaseEntity 的数据库的所有调用。然后我创建了我的第二个通用 repo,它继承了 BaesEntity 并覆盖了一些方法来处理我的 TrackableEntities 的需求。最后,这通过处理存储库中软删除项目的过滤来满足我的需求,并且还为我提供了 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;
    }
于 2012-12-10T01:09:16.297 回答