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; 
     } 
    } 

} 

现在,您可以在删除状态中使用您的类方法。