3

这是我要完成的工作:

有些实体应该被“软删除”,所以我想添加一个名为“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 创建列而不使用表达式?

4

2 回答 2

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

希望这可以帮助

于 2013-10-28T14:00:05.950 回答
-1

我不太确定你的意思是什么 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; }
    }
于 2013-03-08T22:39:18.000 回答