0

我有這樣一個實體:延遲加載

public class Doctor : User 
{ 
    public Doctor(string userName, string firstName, string lastName, 
     string mobileNumber, string email, Sexes sex, Role myRole, DoctorExpertises expertise) 
     : base(userName, firstName, lastName, mobileNumber, email, sex, myRole) 
    { 
     this.Expertise = expertise; 
     this.Results = new List<Result>(); 
    } 

    private Doctor() 
    { 
     this.Results = new List<Result>(); 
    } 

    public void AddResult(Result result) 
    { 
     this.Results.Add(result); 
    } 

    public DoctorExpertises Expertise { get; private set; } 

    private ICollection<Result> results; 

    public virtual ICollection<Result> Results 
    { 
     get { return results; } 
     private set { results = value; } 
    } 
} 

,我有典型的資源庫,如:

public abstract class RepositoryBase<T> where T : class 
    { 
     private DbContext dataContext; 
     protected readonly IDbSet<T> dbset; 

     protected RepositoryBase(IDatabaseFactory databaseFactory) 
     { 
      DatabaseFactory = databaseFactory; 
      dbset = DataContext.Set<T>(); 
     } 

     protected IDatabaseFactory DatabaseFactory 
     { 
      get; 
      private set; 
     } 

     protected DbContext DataContext 
     { 
      get { return dataContext ?? (dataContext = DatabaseFactory.Get()); } 
     } 
     public virtual void Add(T entity) 
     { 
      dbset.Add(entity); 
     } 
     public virtual void Update(T entity) 
     { 
      dbset.Attach(entity); 
      dataContext.Entry(entity).State = EntityState.Modified; 
     } 
     public virtual void Delete(T entity) 
     { 
      dbset.Remove(entity); 
     } 
     public virtual void Delete(Expression<Func<T, bool>> where) 
     { 
      IEnumerable<T> objects = dbset.Where<T>(where).AsEnumerable(); 
      foreach (T obj in objects) 
       dbset.Remove(obj); 
     } 
     public virtual T GetById(long id) 
     { 
      return dbset.Find(id); 
     } 
     public virtual T GetById(string id) 
     { 
      return dbset.Find(id); 
     } 
     public virtual IEnumerable<T> GetAll() 
     { 
      return dbset.ToList(); 
     } 
     public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where) 
     { 
      return dbset.Where(where).ToList(); 
     } 
     public T Get(Expression<Func<T, bool>> where) 
     { 
      return dbset.Where(where).FirstOrDefault<T>(); 
     } 
} 

,我想偷懶負荷醫生用下面的測試結果之一代碼:

[TestMethod] 
public void TestShouldLoadPropertyIfLazyLoaded() 
{ 
    // Act 
    Doctor doctor = this.userRepository.Get(u => u.UserName == "soroosh") as Doctor; 
    Result result = doctor.Results.FirstOrDefault(); 

    // Asserts 
    Assert.IsNotNull(doctor); 
    Assert.IsNotNull(result); 
} 

不幸的是,它不能正常工作醫生不爲空,但結果爲空。

如果我使用include方法加載正確,它會正確加載,但我希望使用延遲加載。

我看過this question以及其他類似的問題,但其中沒有一個是沒用的,因爲它們都使用急切的加載來解決問題。急於加載不適合我們,因爲在我的main problem似乎急於加載是不可能的。

我該怎麼辦?

+0

對不起,但我不明白你說的是什麼。我再次說醫生不是零。謝謝:) –

+0

好吧,我誤會了你 - 對不起;)我刪除了評論;)也許你可以嘗試以下內容: 結果結果= doctor.Results.ToList()。FirstOrDefault(); 順便說一句你應該conssider分裂成兩個單獨的測試;) –

+0

哦,以及userRepository從哪裏來?你在關注數據庫嗎? –

回答

0

這應該只是工作,包括我自己在內的人每天都會這樣做,並且工作。我看到了兩個可能的罪魁禍首:

  • 該工廠的DbContext可能可能創造一個懶加載被禁用
  • 您記錄setter方法需要一個背景是私人的,生成的代理實體可能只是不妥善處理。只需將其改爲公開。

檢查兩個,重點在第二個。

+1

我會建議使用'protected'而不是'public',因爲懶加載的屬性可能不應該有setter http://stackoverflow.com/a/14774042/150342。然後,我會添加一個後臺字段以避免「構造函數中的虛擬調用」代碼異味 – Colin

0

我認爲,如果你完整地定義你真的不需要擔心這個你總邊界 - 你可以總是加載實體時執行域操作,因爲你的關係不應該越過邊界總熱切加載。因此,您的存儲庫只能加載和保存給定類型的單個聚合,以便可以調用該聚合上的行爲。

不要誤解我的意思,你可能仍然想查詢你的數據庫把數據放在UI等等上,但是你可以使用一個簡單的工具,比如Linq到SQL,Dapper等,直接從數據庫中取出數據DB進入用戶界面,跳過所有的ORM eager/lazy加載廢話。

+0

將數據直接從數據庫重新打包到ui聽起來像是應該避免的任何代價,如果您的代碼要在第一個演示中存活的時間更長。 Orm可能是非版本的,但是適當的分層和可測試的代碼至少要求在這兩者之後的一個抽象層。 –

+0

這個抽象層試圖解決什麼問題?而像EF數據庫 - 第一,L2S或Dapper *這樣的技術怎麼不會成爲抽象層?您應該在重要的地方花費精力 - 根據您的域邏輯以及內部的不變式和業務規則。這是大部分測試應該在的地方。從數據庫中讀取測試幾乎沒有什麼意義,實際上,您多久可能會切換到新的rdbms?我不是說在沒有異常處理的情況下編寫可怕的代碼,它應該仍然是Clean Code,只是它不是DDD應用程序*目標所在的地方。 –