实体框架代码第一个和显式接口

时间:2013-03-08 22:10:29

标签: entity-framework ef-code-first

这就是我想要完成的事情:

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

2 个答案:

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