通用存储库模式软删除
本文关键字:删除 模式 存储 | 更新日期: 2023-09-27 18:11:06
我创建了一个通用存储库(使用EF 6.1.1),我在几个项目中使用它,它工作得很好。我已经实现了一个"软"删除功能,我们将数据标记为已删除,但实际上并没有从数据库中删除它。
然后我可以过滤所有的查询,因为所有实体都继承自具有IsDeleted属性的基本实体。这一切都工作得很好,但它显然没有过滤掉任何"软删除"的子实体。
我不确定如何以一种通用的方式来做这件事,因为我不想在每个职责中都要过多地编写解决方案,这真的违背了拥有通用repo的理由。
这是我当前通用回购的一个例子
public sealed class MyRepository<T> : IRepository<T> where T : BaseEntity
{
public String CurrentUser { get; set; }
private readonly MyObjectContext context;
private readonly Configuration configuration = ConfigurationManager.GetConfiguration();
private IDbSet<T> entities;
private IDbSet<T> Entities
{
get { return entities ?? (entities = context.Set<T>()); }
}
public MyRepository(MyObjectContext context, String userName = null)
{
this.context = context;
var providerManager = new DataProviderManager(configuration);
var dataProvider = (IDataProvider)providerManager.LoadDataProvider();
dataProvider.InitDatabase();
CurrentUser = userName;
}
public void Dispose()
{
//do nothing at the moment
}
public T GetById(Guid id)
{
return Entities.FirstOrDefault(x => x.Id == id && !x.IsDeleted);
}
public IQueryable<T> GetAll()
{
return Entities.Where(x => !x.IsDeleted);
}
public IQueryable<T> Query(Expression<Func<T, bool>> filter)
{
return Entities.Where(filter).Where(x => !x.IsDeleted);
}
public void Delete(T entity)
{
if (configuration.HardDelete)
{
HardDelete(entity);
}
else
{
SoftDelete(entity);
}
}
private void HardDelete(T entity)
{
try
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
Entities.Attach(entity);
Entities.Remove(entity);
}
catch (DbEntityValidationException ex)
{
var msg = string.Empty;
foreach (var validationErrors in ex.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, ex);
throw fail;
}
}
private void SoftDelete(T entity)
{
entity.IsDeleted = true;
Update(entity);
}
}
如果有任何帮助就太好了。
谢谢
有人建立了一个全局过滤器,你可以尝试它并从nuget EntityFramework.Filters
安装它。
下面是一个如何使用它的例子。
public abstract class BaseEntity
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
}
public class Foo : BaseEntity
{
public string Name { get; set; }
public ICollection<Bar> Bars { get; set; }
}
public class Bar : BaseEntity
{
public string Name { get; set; }
public int FooId { get; set; }
public Foo Foo { get; set; }
}
public class AppContext : DbContext
{
public DbSet<Foo> Foos { get; set; }
public DbSet<Bar> Bars { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Registers and configures it first.
DbInterception.Add(new FilterInterceptor());
var softDeleteFilter = FilterConvention.Create<BaseEntity>("SoftDelete",
e => e.IsDeleted == false); // don't change it into e => !e.IsDeleted
modelBuilder.Conventions.Add(softDeleteFilter);
}
}
然后你可以在你的仓库构造函数中启用它,或者在db context实例创建后的某个地方启用它,因为默认情况下过滤器是禁用的。
using (var db = new AppContext())
{
db.EnableFilter("SoftDelete");
var foos = db.Foos.Include(f => f.Bars).ToArray(); // works on Include
}
using (var db = new AppContext())
{
db.EnableFilter("SoftDelete");
var foos = db.Foos.ToArray();
foreach (var foo in foos)
{
var bars = foo.Bars; // works on lazy loading
}
}
using (var db = new AppContext())
{
db.EnableFilter("SoftDelete");
var foos = db.Foos.ToArray();
foreach (var foo in foos)
{
db.Entry(foo).Collection(f => f.Bars).Load(); // works on manual loading
}
}
这个过滤器不再需要了。
public IQueryable<T> Query(Expression<Func<T, bool>> filter)
{
return Entities.Where(filter);//.Where(x => !x.IsDeleted);
}
只要你启用了它。
public MyRepository(MyObjectContext context, String userName = null)
{
this.context = context;
if (!configuration.HardDelete)
{
this.context.EnableFilter("SoftDelete");
}
}
我有同样的问题,但我的解决方法有点不同,我使用了一个通用的基接口IGenricInterface与IsDeleted作为属性
public int DeletebyId(string Id)
{
var Ent = (IGenricInterface)_sitecontext.Set<TEntity>().Find(Id);
Ent.IsDeleted = 1;
}
和
_sitecontext.Set<TEntity>().Remove(Ent);
这是在ID上当然你也可以在EnTity上设置