2017-02-14 75 views
0

我有一個由EntityFramework持久化的域模型。在任何給定的實體/ POCO中,我希望能夠填充(通過EF CodeFirst),然後閱讀集合,但只允許通過單獨的域服務類對這些集合進行修改。保護EntityFramework集合不被修改

作爲一個例子,我可以具有類如:

public class Foo { 

    public Foo() { 
     _bars = new List<Bar>(); 
    } 

    private ICollection<Bar> _bars; 
    public virtual ICollection<Bar> Bars { get { return _bars; } protected set { _bars = value; } } 

} 

這將停止與myFoo.Bars = new List<Bar>());被覆蓋的集合。但是,它仍然允許任何使用POCO的人編寫代碼,例如myFoo.Bars.Add(new Bar());或類似的代碼。

我想讓Bars集合爲只讀,因此不僅可以直接停止集合,還可以阻止用戶直接向集合添加Bar實例。

這是因爲用戶被迫使用域服務類將項目添加到集合。該類還將對添加的Bar實例執行非平凡的驗證和業務邏輯檢查。例如:

public class AddBarToFooService() : IAddBarToFooService { 

    public AddBarToFooService(IBarChecker checker) { 
     _checker = checker; 
    } 

    private readonly IBarChecker _checker; 

    public Add(Foo foo, Bar bar) { 

     if(_checker.Check(foo, bar) { // Trivial validation check 
      foo.Bars.Add(foo); 
     } 
    } 
} 

有兩個要點:

  1. 的只讀限制需要能夠允許域名服務操作集合
  2. 該解決方案必須符合的EntityFramework
  3. 兼容
  4. 理想情況下,POCO和域名服務應該是鬆散耦合的

我該如何做到這一點?

+0

因此,您的服務從不暴露上下文?用戶是否調用您的代碼來保存更改,或者他們能否直接調用SaveChanges? –

回答

0

有一些選項可以防止使用實體框架添加或更新數據。

從模型中卸下實體

當你調用數據庫,你可以使用

Configuration.ProxyCreationEnabled = false; 

在這種情況下您禁用延遲加載和關閉某些對象跟蹤。或者你可以'取消代理'的對象與

protected internal List<T> UnProxyList<T>(List<T> list) where T : class 
{ 
    var proxyCreationEnabled = this.Configuration.ProxyCreationEnabled; 
    try 
    { 
     this.Configuration.ProxyCreationEnabled = false; 
     return list.Select(i => this.Entry(i).CurrentValues.ToObject() as T).ToList(); 
    } 
    finally 
    { 
     this.Configuration.ProxyCreationEnabled = proxyCreationEnabled; 
    } 
} 

在這兩種情況下的變化不再被追蹤。因此用戶是否修改集合並沒有關係,它沒有任何影響。請注意,用戶需要急切的加載來填充導航屬性。

回滾改變

這可以的DbContext完成。您可以創建一個內部方法,您可以調用base.SaveChanges,而用戶必須使用SaveChanges的重寫。您可以添加一些邏輯來回滾某些更改。

public override int SaveChanges() 
{ 
    var entries = base.ChangeTracker.Entries<Bar>().ToList(); 

    entries.ForEach(entry => entry.State = System.Data.Entity.EntityState.Unchanged); 
    return base.SaveChanges(); 
} 

延遲加載和跟蹤是可用的,所以你會得到正常的實體框架行爲。但是,更改不會落實。