3

在我的項目中,我不使用物理刪除,我只對所有表使用邏輯「軟刪除」。如何避免在實體框架中重複相同

我用這個條款爲所有查詢:

.Where(row => row.IsDeleted == false) 

我想辦法,以避免重複此where子句中的所有查詢。

我有這樣的方法來獲取數據:

public new IDbSet<TEntity> Set<TEntity>() where TEntity : class 
{ 
    return base.Set<TEntity>(); 
} 

,我這樣稱呼它:

_categories = _uow.Set<Category>(); 

我怎樣才能做到這一點?

第一理念:

添加一個基類,並把Deleted列在從這個基類繼承的所有類。這是一個好方法嗎?

我使用UnitOfWork和代碼優先。

+0

難道你不覺得這會更「安全」顯式過濾你的記錄,而不是神奇的數據層_swallowing_你的一些數據嗎?特別是如果有多個人正在/將要處理此代碼。我想這將很難達到由此導致的意外行爲的底部。 – romeozor

+0

我想如果我在'Service'層中的所有查詢中使用'where',它可能是一個我忘記的地方,它是一個系統的bug,並且在軟件工程中重複一個代碼並不好 –

回答

2

我不會爲了重用單個屬性而創建基類。相反,我會創建一個interfase和一個擴展方法來封裝和重用where語句。像下面這樣:

public static class EntityFrameworkExtentions 
{ 
    public static ObservableCollection<TEntity> Alive<TEntity>(this DbSet<TEntity> set) 
     where TEntity : class, ISoftDeleteAware 
    { 
     var data = set.Where(e => e.IsDeleted == false); 
     return new ObservableCollection<TEntity>(data); 
    } 
} 

界面聲明

public interface ISoftDeleteAware 
{ 
    bool IsDeleted { get;set;} 
} 

用法:

var coll = DbContext.Categories.Alive(); 
+0

I this this Asnwer its better爲我的項目和我的Arcitcture。 –

2
public class GenericRepository<TEntity> where TEntity : class 
{ 
    internal MyContext context; 
    internal DbSet<TEntity> dbSet; 

    public GenericRepository(MyContext context) 
    { 
     this.context = context; 
     this.dbSet = context.Set<TEntity>(); 
    } 

    public virtual IQueryable<TEntity> GetNonDeleted(Expression<Func<TEntity, bool>> filter = null) 
    { 
     IQueryable<TEntity> query = dbSet; 

     if (filter != null) 
     { 
      query = query.Where(filter); 
     } 

     query = query.Where(row => row.IsDeleted == false); 

     return query; 
    } 
    // Other methods 
} 
1

如果你從來沒有刪除任何東西,那麼你可以使用基實體類和IsDelete財產吧。之後,使用此基本實體爲通用存儲庫。看起來像;

public abstract class BaseModel 
{ 
    public BaseModel() 
    { 
     IsDelete = false; 
     CreateDate = DateTime.Now; 
    } 
    [Key] 
    public int Id { get; set; } 
    public bool IsDelete{ get; set; } 
    public virtual DateTime CreateDate { get; set; } 
    public virtual DateTime UpdateDate { get; set; } 
} 

public class YourClassHere : BaseModel 
{ 
    // 
} 

public class Repository<T> : IRepository<T> where T : BaseModel 
{ 
    private readonly IDbContext _context; 
    private IDbSet<T> _entities; 

    public Repository(IDbContext context) 
    { 
     this._context = context; 
    } 

    public T GetByIdByIgnoringDeleteStatus(int id) 
    { 
     return this.Entities.Find(id); 
    } 

    public T GetById(int id) 
    { 
     return this.Entities.Single(item => item.Id == id && !item.IsDelete);   

    } 

    public void Create(T entity) 
    { 
     try 
     { 
      if (entity == null) 
      { 
       throw new ArgumentNullException("entity"); 
      } 
      entity.CreateDate = DateTime.Now; 
      this.Entities.Add(entity);     
      //this._context.SaveChanges(); 
     } 
     catch (DbEntityValidationException dbEx) 
     { 
      var msg = string.Empty; 

      foreach (var validationErrors in dbEx.EntityValidationErrors) 
      { 
       foreach (var validationError in validationErrors.ValidationErrors) 
       { 
        msg += string.Format("Property: {0} Error: {1}", 
        validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine; 
       } 
      } 

      var fail = new Exception(msg, dbEx); 
      throw fail; 
     } 
    } 

    public void Update(T entity) 
    { 
     try 
     { 
      if (entity == null) 
      { 
       throw new ArgumentNullException("entity"); 
      } 
      entity.UpdateDate = DateTime.Now; 
      this._context.SetModified(entity); 
      //this._context.SaveChanges(); 

     } 
     catch (DbEntityValidationException dbEx) 
     { 
      var msg = string.Empty; 
      foreach (var validationErrors in dbEx.EntityValidationErrors) 
      { 
       foreach (var validationError in validationErrors.ValidationErrors) 
       { 
        msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", 
        validationError.PropertyName, validationError.ErrorMessage); 
       } 
      } 
      var fail = new Exception(msg, dbEx); 
      throw fail; 
     } 
    } 

    public void Delete(T entity) 
    { 
     try 
     { 
      if (entity == null) 
      { 
       throw new ArgumentNullException("entity"); 
      } 
      entity.UpdateDate = DateTime.Now; 
      this.Entities.Remove(entity);     
      //this._context.SaveChanges(); 
     } 
     catch (DbEntityValidationException dbEx) 
     { 
      var msg = string.Empty; 

      foreach (var validationErrors in dbEx.EntityValidationErrors) 
      { 
       foreach (var validationError in validationErrors.ValidationErrors) 
       { 
        msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", 
        validationError.PropertyName, validationError.ErrorMessage); 
       } 
      } 
      var fail = new Exception(msg, dbEx); 
      throw fail; 
     } 
    } 

    public virtual IQueryable<T> GetAll() 
    {   
     return this.Entities;    
    } 

    private IDbSet<T> Entities 
    { 
     get 
     { 
      if (_entities == null) 
      { 
       _entities = _context.Set<T>(); 
      } 
      return _entities; 
     } 
    } 

} 

現在,您可以在刪除狀態中使用您的類方法。