Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 延迟加载集合-如何获取项目?_.net_Architecture_Ninject - Fatal编程技术网

.net 延迟加载集合-如何获取项目?

.net 延迟加载集合-如何获取项目?,.net,architecture,ninject,.net,Architecture,Ninject,我有一个简单的类,它是一个简单的POCO——它只保存数据。除了一个例外:它包含一组注释。我想延迟加载此集合,这样我就不必在不需要它们的页面上获取注释。此文件的存根如下所示: public class MyDTOClass { private ICollection<Note> _notes = null; public ICollection<Note> Notes { get { if(

我有一个简单的类,它是一个简单的POCO——它只保存数据。除了一个例外:它包含一组注释。我想延迟加载此集合,这样我就不必在不需要它们的页面上获取注释。此文件的存根如下所示:

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;
        }
    }
}
公共类MyDTOClass
{
私有ICollection_notes=null;
公开收集便笺
{
得到
{
如果(_notes==null)
{
//获取INoteRepository并初始化集合
}
还票;;
}
}
}
现在,我想知道如何从这里开始。这是一个ASP.net MVC应用程序,我使用依赖项注入将IRepositories注入到需要它们的类中,例如我的控制器。但是,由于这里的这个类应该是一个非常简单的DTO,我不愿意向其中注入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);
    }
}
公共类MyDataAccessClass
{
私人票据回购;
//Inject是Ninject的一部分,确保我通过了正确的
//自动去对位
[注入]
公共MyDataAccessClass(INoteRepository noteRepository)
{
_noteRepo=noteRepository;
}
公共IEnumerable GetNotes(int projectId)
{
return_noteRepo.GetNotes(projectd);
}
}
这当然可以,但我想知道这是否是正确的体系结构?我将简单的DTOClass耦合到另一个数据访问类,也可能耦合到我的DI机制(因为我需要在Notes的getter中创建数据访问类的实例)

你会换一种方式吗?有没有更好的方法来实现这一点,同时记住我已经使用了Ninject

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

我当前的解决方案非常难看,因为我需要从我的MVCAPApplication中获取Ninject内核,并使用它来启动ProjectDataProvider类,该类在其构造函数中采用InoteRecository,以避免必须将InoteRecository放在我的“DTO”类中的某个位置:

公共i收集说明
{
得到
{
如果(_notes==null)
{
var app=HttpContext.Current.ApplicationInstance作为mvcapapplication;
如果(app==null)
抛出新的InvalidOperationException(“找不到应用程序”);
var pdp=app.Kernel.Get();
_注释=新列表(pdp.GetNotes(Id));
}
还票;;
}
}

编辑:打开了悬赏。让我们忽略“POCO”和“DTO”这两个术语,我将相应地进行重构。因此,这是关于:在这种情况下,延迟加载代码应该是什么样子的,我是否可以/应该避免将INoteRepository传递到MyDTOClass中?

当您尝试将延迟加载逻辑添加到dto中时,您正在挫败dto的全部目的。我认为,您应该有两个独立的对象:一个有
Note
s,另一个——没有它们。

如果您可以等待.Net 4(即尚未投入生产)Lazy(of T)是.Net framework中一个新的延迟加载特性。

您可以将Notes属性作为一个参数包含在INoteRepository中。通过这种方式,调用代码可以传递到正确的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);
    }
}
因此,您可以在实体类中编写如下内容:

public class Monster
{
    public ReadOnlyCollection<Victim> _victims;
    public ReadOnlyCollection<Victim> Victims
    {
        get
        {
            if (this._victims == null) // Note: Thread-Safety left out for brevity
            {
                this._victims = VictimRepository.Instance.GetVictimsForMonster(this);
            }

            return this._victims;
        }
    }
}
公共类怪物
{
公众只读收集(受害者);;
公众只读收集受害者
{
得到
{
if(this.\u==null)//注意:为了简洁起见,省略了线程安全
{
this.\u受害者=VictimRepository.Instance.GetVictimsForMonster(this);
}
把这个还给受害者;
}
}
}
这真的解决了我所有的头痛问题

存储库的实现方式必须确保它始终知道如何处理数据

请记住,例如,一个存储库实现将从数据库获取数据,而另一个存储库实现可能从web服务获取数据。由于松散耦合,存储库实现模块易于更换,任何数据通信甚至可以任意链接

如果您有这样一个场景,您会说“但是存储库不能是单例的,因为我有一个复杂的场景,例如,我访问多个数据源,这取决于实际的
怪物
实例从何处获取
受害者
s”,然后我说,您必须创建一个存储库实现,它知道所有数据源,并跟踪实体实例的来源和去向,等等

如果您觉得这种方法还不够POCO,那么您必须创建另一个松散耦合的业务逻辑层,它包装或派生POCO实体,并在那里实现存储库交互


我希望我能给你和任何人一个正确的方向。我确实相信这是多层/层开发的圣杯。欢迎进一步讨论。

您的DTO不需要了解存储库本身。它所需要的只是一个可以为其提供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;
    }
}
公共类MyDTOClass
{
私有ICollection_notes=null;
公开收集便笺
{
得到
{
public class Repository
{
    public MyDTOClass GetData()
    {
        MyDTOClass dto = new MyDTOClass(FetchNotes);
        return dto;
    }

    public ICollection<Note> FetchNotes()
    {
        return new List<Note>(200);
    }
}
public class MyLazyDTOClass: MyDTOClass {   

    // Injected into the constructor by the MyDtoClass repository
    private INoteRepository noteRepository;        

    public ICollection<Note> Notes {
        get {
            if(base.Notes == null) {
                base.Notes = noteRepository.GetNotes(projectId);
            }
            return base.Notes;
        }
    }
}
public MyDTOClassRepository {
    public MyDTOClass GetMyDTOClass(int id) {
        // ... Execute data access code to obtain state ...
        return new MyLazyDTOClass(this, state);
    }
}