如何避免在实体框架中重复相同的位置

时间:2016-01-31 10:54:08

标签: asp.net-mvc entity-framework linq ef-code-first entity-framework-6

在我的项目中,我不使用物理删除,我只是对所有表使用逻辑“软删除”。

我对所有查询使用此子句:

.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和代码优先。

3 个答案:

答案 0 :(得分: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 :(得分: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();

答案 2 :(得分:1)

如果你从不删除任何东西,那么你可以使用它的基本实体类和IsDelete属性。之后,将此基本实体用于Generic Repository。它看起来像;

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

}

现在,您可以将类方法与删除状态一起使用。