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