【问题标题】:Object not loaded due to lazy loading. How to return all objects from BLL由于延迟加载而未加载对象。如何从 BLL 返回所有对象
【发布时间】:2012-02-15 23:16:05
【问题描述】:

我在弄清楚如何使这个存储库模式起作用时遇到了一些麻烦。

简而言之,我的解决方案看起来像这样......

        ASP.Net MVC
             ^
             |
       Business Logic
             ^
             |
       Data Access 
(Repositories and Unit of Work)
             ^
             |
  Entity Framework Models

我有一个引用角色表的用户表。

在我的 MVC 应用程序中,我使用 GetAllUsers 调用 BLL。 BLL 中的代码如下所示:

public List<User> GetAllUsers()
{
    using (UnitOfWork uow = new UnitOfWork())
    {
        UserRepository userRepository = new UserRepository(uow);
        return userRepository.GetAll().ToList();
    }
}

UserRepository 派生自 GenericRepository,它有一个 GetAll()

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    private IUnitOfWork _uow = null;

    public GenericRepository(IUnitOfWork uow)
    {
        _uow = uow;
    }

    public virtual IQueryable<T> GetAll()
    {
        return _uow.Set<T>().AsQueryable();
    }
}

它将用户列表返回到我的 MVC 应用程序,但是当我尝试访问角色引用时,由于延迟加载,它尚未加载。

public ActionResult Index()
{
    BusinessLogic.Account blAcct = new BusinessLogic.Account();
    List<User> users = blAcct.GetAllUsers();

    string firstName = users.FirstName;  // Works fine
    string role = users.Roles.RoleName;  // Fails because the context is closed.

    return View();
}

我尝试在 GetAllUsers 上放置一个 .Include(Roles),但在 IQueryable 上没有 .Include。

从理论上讲,我是否认为 MVC 应用程序不需要了解有关上下文或数据访问的任何信息? 其次,在离开 BLL 之前,我应该如何将这个角色引用包含在我的图表中?

【问题讨论】:

    标签: linq asp.net-mvc-3 entity-framework repository-pattern unit-of-work


    【解决方案1】:

    您认为您的 MVC 应用程序是正确的,鉴于您当前的应用程序架构,不应该关心 DataContext 和数据检索。

    一种解决方案可能是添加另一个 Repository 方法,该方法会急切地加载您的 Roles

    public IList&lt;Users&gt; GetAllUsersWithRoles()

    然后根据上下文有选择地使用合适的方法。

    【讨论】:

    • 我很乐意这样做,但即使是我的 UserRepository 也在使用 IQueryable 并且无权访问上下文。上下文完全在工作单元中控制。也许我需要重新考虑我的 UoW 和存储库是如何构建的。
    • 您可以通过UoW 类将DataContext 公开为公共属性,仅在检索方法期间使用它。虽然这感觉像是一种代码味道。
    • 另一种选择是让存储库采用基础DataContext(通过它的构造函数)并使用IoC container 注入它。仅在 Retrieval 期间使用此上下文,而不是 UpdatingInsertingDeleting
    • 是的,我将它作为公共财产公开。现在我的 UserRepository 覆盖了所有的 get 方法并 .Includes 角色。完美运行。除了现在我的上下文向所有人公开。朋友方法在这里将是完美的。当然希望 C# 有这些......我会看看注入上下文。这听起来可能是一种更 OO 友好的方法!谢谢!
    【解决方案2】:

    我自己也遇到过这种情况,您希望代码“漂亮而自鸣得意”,但抽象不允许您以您想要的方式控制底层实现。

    首先,让我们问一个重要的问题:您将正在使用的 OR/M 切换到另一个实现的可能性有多大?

    如果很有可能,并且您确实需要抽象,那么这取决于您在所有惰性提取中损失的性能是否显着。也许这不是问题?然后我可以处理一些 N + 1 个查询。

    但是,如果性能不可接受,您可以尝试在自己的IQueryable 上添加包含Include 方法的自己的接口。如果你想要很多底层功能,那就有点难看了。

    要绕过关闭的会话,您可以将会话生活方式提升到更高级别,或者使用更具体的方法,返回 DTO。那你就不会有不知道什么是懒加载什么不是的问题了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多