存储库模式:如何延迟加载?或者,我应该拆分此汇总? [英] Repository Pattern: how to Lazy Load? or, Should I split this Aggregate?

查看:48
本文介绍了存储库模式:如何延迟加载?或者,我应该拆分此汇总?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个域模型,它具有编辑器和项目的概念.

I have a domain model that has the concept of an Editor and a Project.

编辑者拥有多个项目,并且一个项目不仅具有编辑者所有者,而且还具有许多编辑者成员.因此,编辑器也有许多连接"项目.

An Editor owns a number of Projects, and a Project has not only an Editor owner, but also a number of Editor members. Therefore, an Editor also has a number of "joined" Projects.

我正在采用DDD方法对此进行建模,并使用Repository模式进行持久化.但是,我对这种模式的理解还不够好,无法确定我应该如何做.

I am taking a DDD approach to modelling this and using the Repository pattern for persistence. However, I don't grok the pattern well enough yet to determine how I should do this.

我正在假设Editor和Project可能在同一聚合中,其根是Editor.因此,我可以得到一个Editor,然后枚举其Projects,然后可以从那里枚举Projects的成员Editors.

I'm working on the assumption that Editor and Project are potentially in the same aggregate, with the root being Editor. I can therefore get an Editor and then enumerate its Projects, and could from there enumerate the Projects' member Editors.

但是,如果只允许我从存储库中检索编辑器,这是否意味着当我获得拥有它们的编辑器时,我必须从存储库中加载所有项目吗?而且,如果我想延迟加载成员Editors,那么Project也需要对存储库的引用吗?

However, if I am only allowed to retrieve Editors from my repository, doesn't this mean I have to load all the Projects from the repository when I get the Editor that owns them? And if I want to lazy load the member Editors, the Project needs a reference to the repository as well?

或者,如果我拆分了聚合并拥有一个Editor库和一个Project库,那么我应该如何处理两者之间的事务,例如将新的Project添加到Editor时?例如:

Alternatively, if I split the aggregate and have an Editor repository and a Project repository, how should I handle a transaction across the two, such as when a new Project is added to an Editor? For example:

Editor e = new Editor("Editor Name");
editorRepository.Add(e);

Project p = e.CreateProject("Project Name");
projectRepository.Add(p);    // These two lines
editorRepository.Save(e);    // should be atomic

我是否误解了存储库模式的意图?

Am I misinterpreting the intent of the Repository pattern?

推荐答案

我是否误解了存储库模式的意图?

Am I misinterpreting the intent of the Repository pattern?

我要说是的",但是知道我和与我共事的每个人都出于同样的原因问了同样的事情... 你不是在第四度思考,马蒂.

I'm going to say "yeah", but know that me and every person I've worked with has asked the same thing for the same reason... "You're not thinking 4th dimensionally, Marty".

让我们稍微简化一下,并坚持使用构造函数,而不要先使用Create方法:

Let's simplify it a little and stick with constructors instead of Create methods first:

Editor e = new Editor("Editor Name");
e = editorRepository.Add(e);

Project p = new Project("Project Name", e);
p = projectRepository.Add(p);

在下面,您的项目存储库始终在创建项目数据时一直将有效所有者(p.EditorId)存储到项目数据中,但是,如果您重新填充编辑器的项目,它将在此处.这就是为什么将所有必需的属性放入构造函数是一个好习惯的原因.如果您不想传递整个对象,则只需e.Id即可.

Underneath, your project repository is always storing a valid owner (p.EditorId) into the project data as it's created, and however you re-populate an editor's projects, it will be there. This is why it's a good practice to put all required properties into constructors. If you don't want to pass the whole object, just the e.Id will do.

如果我想延迟加载成员Editors,那么Project也需要对存储库的引用吗?

And if I want to lazy load the member Editors, the Project needs a reference to the repository as well?

现在,关于如何按需重新填充编辑器的项目,您可以根据自己的选择进行选择.直接存储库说您想要:

Now, as to how to re-populate an editor's projects on demand, you have a couple of choices depending on what you're going for. Straight Repository says you want:

IEnumerable<Project> list = projectRepository.GetAllProjects()
                                .Where(x => x.editorId == e.Id);

但是放在哪里?是的,不在Project或Editor内部,否则他们将不得不访问存储库,这不好.上面的代码段是松散耦合的,但不能单独重用.您刚刚达到存储库模式的极限.

But where to put it? Not inside Project, or Editor, you're right, or they will have to get access to repositories and that's no good. The above snippet is loosely coupled, but isn't reusable on its own. You've just reached the limits of Repository Pattern.

接下来是您的应用程序的适配器层,具有共享存储库(StaticServiceWrapper)源和某种EditorAdapter对象(或Aggregate或您要称呼的任何对象),或者现在您可以混合使用扩展方法可以流畅地与任何及所有必需的存储库进行对话.在生产系统中,我还没有完全做到这一点,而是向您展示一个简洁的示例:

Next up is an Adapter Layer for your application, with a shared source of repositories (StaticServiceWrapper) and either some sort of EditorAdapter object (or Aggregate or whatever you'd call them) or now you can mix in extension methods that can talk to any and all necessary repositories fluently. I haven't done it exactly this way in a production system, but to show you a concise example:

public static class Aggregators
{
    // one to one, easy
    public static Editor GetOwner(this Project p)
    {
        return StaticServiceWrapper.editorRep.GetEditorById(p.editorId);
    }

    // one to many, medium
    public static IEnumerable<Project> GetProjects(this Editor e) 
    { 
        return StaticServiceWrapper.projectRep.GetAllProjects()
                .Where(x => x.editorId == e.Id);
    }

    // many to many, harder
    public static IEnumerable<Editor> GetMembers(this Project p)
    {
        var list = StaticServiceWrapper.projectMemberMap.GetAllMemberMaps()
                        .Where(x => x.projectId == p.projectId);

        foreach ( var item in list )
            yield return StaticServiceWrapper.editorRep.GetEditorById(item.editorId);
    }
}

基本上,完成GetAll,GetById,Add,Update,Remove Object Repository后,您就不必再进行关联了,而是将对象/层层次结构移到有趣的部分,例如Adapters和Caches以及Business Logic. (哦,我的!" ).

Basically, once your GetAll,GetById,Add,Update,Remove Object Repository is done, you've got to leave the associations alone and move on up the object/layer hierarchy to the fun parts like Adapters and Caches and Business Logic ("Oh, my!").

这篇关于存储库模式:如何延迟加载?或者,我应该拆分此汇总?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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