集合的延迟加载 - 如何获取项目? [英] Lazy Loading of Collection - how to get the items?

查看:19
本文介绍了集合的延迟加载 - 如何获取项目?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的类,它旨在成为一个简单的 POCO - 它只保存数据.有一个例外:它包含一个笔记集.我想延迟加载这个集合,这样我就不必在不需要它们的页面上获取注释.这个存根是这样的:

I have a simply Class that is intended to be a simple POCO - it just holds data. With one exception: It contains a Collection of Notes. I want to lazy-load this collection so that I don't have to fetch the Notes on Pages that don't need them. The stub for this is this:

public class MyDTOClass 
{
    private ICollection<Note> _notes = null;

    public ICollection<Note> Notes
    {
        get
        {
            if(_notes == null)
            {
                // Get an INoteRepository and initialize the collection
            }
            return _notes;
        }
    }
}

现在,我想知道如何从这里开始.这是一个 ASP.net MVC 应用程序,我使用依赖注入将 IRepositories 注入需要它们的类中,例如我的控制器.但是因为这里的这个类应该是一个非常简单的 DTO,所以我不愿意将 INoteRepository 注入其中,也是因为调用者不应该担心或关心这是延迟加载的事实.

Now, I'm wondering how to proceed from here. It's an ASP.net MVC application and I use Dependency Injection to inject the IRepositories in classes that need them, for example my controllers. But as this class here is supposed to be a really simple DTO, I'm reluctant to inject an INoteRepository into it, also because the caller shouldn't worry or care about the fact that this is lazy-loaded.

所以我想在我的模型中有另一个包含 INoteRepository 的类.

So I'm thinking of having another Class in my Model that holds a INoteRepository.

public class MyDataAccessClass
{
    private INoteRepository _noteRepo;

    // Inject is part of Ninject and makes sure I pass the correct
    // INoteRepository automatically
    [Inject]
    public MyDataAccessClass(INoteRepository noteRepository)
    {
        _noteRepo = noteRepository;
    }

    public IEnumerable<Note> GetNotes(int projectId)
    {
        return _noteRepo.GetNotes(projectId);
    }
}

这当然可行,但我想知道这是否是正确的架构?我将简单的 DTOClass 耦合到另一个数据访问类,也可能耦合到我的 DI 机制(因为我需要在 Notes 的 getter 中创建数据访问类的实例).

This would work of course, but I wonder if this is the correct architecture? I couple the simple DTOClass to another Data Access class and possibly also to my DI mechanism (as I need to create an Instance of the Data Access class in the getter of Notes).

你会做不同的事情吗?有没有更好的方法来做到这一点,还要记住我已经在使用 Ninject?

Would you do it differently? Is there a better way to do this, also keeping in mind I already use Ninject?

我猜这不再是 POCO 或 DTO,因为它现在包含逻辑,但没关系.我希望它出现像外部调用者的 POCO,所以我喜欢在这个或其他类上有一个属性Notes"而不是像GetNotesForProject"这样的方法.

I'm guessing that this is not a POCO or DTO anymore as it now contains logic, but that's okay. I want it to appear like a POCO to outside caller so I like to have a Property "Notes" rather than methods like "GetNotesForProject" on this or other classes.

我当前的解决方案真的很丑,因为我需要从我的 MvcApplication 中获取 Ninject 内核并使用它来启动 ProjectDataProvider 类,该类在其构造函数中使用 INoteRepository,以避免不得不将 INoteRepository 放在我的DTO"中"-班级:

My current solution is really ugly, as I need to get the Ninject Kernel from my MvcApplication and use it to spin up the ProjectDataProvider class which takes an INoteRepository in it's constructor, to avoid having to put the INoteRepository somewhere in my "DTO"-Class:

public ICollection<Note> Notes
{
    get
    {
        if(_notes == null)
        {
            var app = HttpContext.Current.ApplicationInstance as MvcApplication;
            if (app == null)
             throw new InvalidOperationException("Application couldn't be found");
            var pdp = app.Kernel.Get<ProjectDataProvider>();
            _notes = new List<Note>(pdp.GetNotes(Id));
        }
        return _notes;
    }
}

打开赏金.让我们忽略POCO"和DTO"的术语,我会相应地重构.所以这是关于:延迟加载代码在这种情况下应该如何看,我可以/应该避免将 INoteRepository 传递到 MyDTOClass 中吗?

Opened a bounty. Let's ignore the terminology of "POCO" and "DTO", I'll refactor accordingly. So this is about: How should the Lazy-Loading code look in such a situation, and can/should I avoid passing INoteRepository into the MyDTOClass?

推荐答案

您的 DTO 不需要了解存储库本身.它所需要的只是一个可以为其提供笔记值的委托.

Your DTO doesn't need to know about the repository itself. All it needs is a delegate that can provide it with the value for notes.

这样的事情怎么样:

public class MyDTOClass
{
    private ICollection<Note> _notes = null;

    public ICollection<Note> Notes
    {
        get
        {
            if (_notes == null)
            {
                if (notesValueProvider == null)
                    throw new InvalidOperationException("ValueProvider for notes is invalid");
                _notes = notesValueProvider();
            }
            return _notes;
        }
    }

    private Func<ICollection<Note>> notesValueProvider = null;

    public MyDTOClass(Func<ICollection<Note>> valueProvider)
    {
        notesValueProvider = valueProvider;
    }
}

由于根据定义,您的存储库应该为您提供 DTO 的实例,因此我们应该能够像这样传入值提供程序委托:

Since by definition, your repository is supposed to provide you with an instance of the DTO, we should be able to pass in the value provider delegate like so:

public class Repository
{
    public MyDTOClass GetData()
    {
        MyDTOClass dto = new MyDTOClass(FetchNotes);
        return dto;
    }

    public ICollection<Note> FetchNotes()
    {
        return new List<Note>(200);
    }
}

这对你有用吗?

这篇关于集合的延迟加载 - 如何获取项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆