2013-03-08 57 views
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創建列,而無需表達式?

+0

實體框架支持內部屬性。請參閱下面的答案。 – 2013-11-15 20:15:25

回答

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; } 
    } 
+0

問題是我不想讓IsDeleted成爲公共財產。我希望它只在DAL內部。所以IDeletable是一個內部接口,並且被實現爲顯式的。由於EF無法看到此屬性(不是因爲它是內部的,而是因爲它是顯式的),所以它不會生成該列。 – 2013-03-08 22:49:08

+0

@GiovanniGalbo沒有任何方法讓私有變量暴露給EF,因爲它需要能夠讀/寫它。實際執行此操作的唯一方法是創建不帶可刪除屬性的實體的第二個版本,並在離開DAL時將EF模型映射到另一個版本。顯然這是相當多的混亂。就我個人而言,我只是想讓可刪除的界面可見而不是沿着映射路徑 – 2013-03-08 23:11:08

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

希望這有助於