2012-11-06 69 views
1

我正在更新爲更易於管理的存儲庫模式,在我的MVC 4項目中首先使用實體​​框架代碼。我已經集成了一個通用的基礎知識庫類,它將執行基本的CRUD操作,所以我不必在創建的每個知識庫中實現這些。如果實體是一種TrackableEntity,我遇到了一個問題,即我的All方法需要通過刪除標誌過濾查詢。由於該實體在基礎知識庫中是通用的,因此我試圖將其轉換爲只能導致以下錯誤消息的地方的TrackableEntity類型。實體框架類型case在謂詞中泛型

不支持輸入「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; } 
} 

任何幫助將非常感激。

+0

你可以嘗試'dbSet.OfType (),其中(E => e.IsDeleted!).ToList()'? – nemesv

+0

我得到''NameSpace.Models.TrackableEntity'不是用於類型過濾操作的有效元數據類型,類型過濾只對實體類型和複雜類型有效。「當試圖返回dbSet.OfType ()。其中​​(e =>!e.IsDeleted).ToList()爲IEnumerable ;我不得不再次表演讓返回類型感到高興。 – DSlagle

回答

1

我終於找到了一個我很滿意的解決方案。我最終制作了2個通用存儲庫。一個是基礎知識庫,它處理所有實體繼承的BaseEntity對數據庫的所有調用。然後我做了我的第二個通用回購,它繼承了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; 
    } 
+0

您好,首先感謝您指出問題,尤其是(當然)解決方案。 我和你有同樣的錯誤,但情況不同。 – ridermansb