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应用程序*目标所在的地方。 –