这就是我想要完成的事情:
某些实体应该“软删除”,所以我想添加一个名为“IsDeleted”的字段(和相应的列)。我希望这个属性只能由DAL访问(可以通过朋友程序集完成)。如果DAL可以通过接口(IDeletable)处理所有这些实体,我也会喜欢它。
为了实现这两个目标,我可以将IDeletable作为内部接口,并且在实现此接口的类中,我可以使用显式接口:
bool IDeletable.IsDeleted { get; set; }
DAL代码可能看起来像这样:
public void Delete<T>(T entity)
{
var d = entity as IDeletable;
if(d != null)
//soft delete
d.IsDeleted = true;
else
//hard delete
//....
}
问题是EF Code First无法生成列,据我所知。我尝试过使用表达式,但是当我尝试转换为IDeletable时它会抱怨。
有没有办法强制EF Code First创建没有表达式的列?
答案 0 :(得分:3)
首先,我将实现该属性并为EF添加内部属性以了解:
public class A : IDeletable
{
bool IDeletable.IsDeleted
{
get { return this.IsDeleted; }
set { this.IsDeleted = value; }
}
internal bool IsDeleted { get; set; }
}
其次,我会扩展 DbSet<TEntity>
:
public class SmartDbSet<TEntity> : DbSet<TEntity>
{
public override TEntity Remove(TEntity entity)
{
if (entity == null)
throw //[your favorite exception]
if (entity is IDeletable)
(entity as IDeletable).IsDeleted = true;
else
base.Remove(entity);
return entity;
}
}
最后你的DbContext看起来像这样:
public class MyDbContext : DbContext
{
public SmartDbSet<A> As { get; set; }
protected override void OnModelCreating(DbModelBuilder builder)
{
//this is your internal property, NOT the explicit one
builder.Entity<A>().Property(t => t.IsDeleted);
}
}
希望这会有所帮助
答案 1 :(得分:0)
我不太清楚你的意思EF不会在没有表达的情况下创建列,但是这是你想要实现的一个有效例子。
class Program
{
static void Main(string[] args)
{
using (var ctx = new MyContext())
{
var a = new A { IsDeleted = false };
var b = new B { };
ctx.As.Add(a);
ctx.Bs.Add(b);
ctx.SaveChanges();
ctx.Delete(a);
ctx.Delete(b);
}
// At this point A is soft deleted and B is permanantly deleted
Console.ReadLine();
}
}
public class MyContext : DbContext
{
public DbSet<A> As { get; set; }
public DbSet<B> Bs { get; set; }
public void Delete<T>(T entity) where T:class
{
var d = entity as IDeletable;
if (d != null)
{
//soft delete
d.IsDeleted = true;
}
else
{
//Use ugly delete as we dont know the dbset this applies to
this.Entry(entity).State = System.Data.EntityState.Deleted;
}
this.SaveChanges();
}
}
public interface IDeletable
{
bool IsDeleted { get; set; }
}
public class A : IDeletable
{
public int Id { get; set; }
//Implementing this interface adds a column to this entity (no issues here?)
public bool IsDeleted { get; set; }
}
public class B
{
public int Id { get; set; }
}