我创建了一个通用存储库(使用EF 6.1.1),我在几个项目中使用它并且它运行良好。 我实施了一个“软”的软件。删除功能,我们将数据标记为已删除,但实际上并未将其从数据库中删除。
然后,我可以过滤所有查询,因为所有实体都从具有IsDeleted属性的基本实体继承。这一切都很好用,但它显然没有过滤掉任何软删除的'子实体。
我不确定如何以通用方式执行此操作,因为我不想将解决方案编码到每个respoitory中,这实际上违背了拥有通用存储库的原因。
这是我目前的Generic 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);
}
}
对此的任何帮助都会很棒。
由于
答案 0 :(得分:6)
有人建立了全局过滤器,您可以尝试从nuget EntityFramework.Filters
安装它。
https://github.com/jbogard/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上下文实例后在存储库构造函数或某个位置启用它,因为默认情况下禁用了过滤器。
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");
}
}
答案 1 :(得分:0)
我遇到了同样的问题,但是我的解决方法几乎没有什么不同,我使用了通用的基本接口 IGenricInterface ,并以 IsDeleted 作为属性
public int DeletebyId(string Id)
{
var Ent = (IGenricInterface)_sitecontext.Set<TEntity>().Find(Id);
Ent.IsDeleted = 1;
}
并用于hardDelete
_sitecontext.Set<TEntity>().Remove(Ent);
这是在ID上,但当然,您也可以在EnTity上完成