Repository Pattern: как Ленивые нагрузки? или я должен разделить этот агрегат?

голоса
66

У меня есть модель предметной области, которая имеет понятие редактора и проект.

Редактор имеет ряд проектов, и проект имеет не только владелец редактора, но и ряд членов редакторов. Таким образом, редактор также имеет ряд «присоединившиеся» проекты.

Я беру подход DDD для моделирования этого и используя Repository шаблон для персистенции. Тем не менее, я не обращал внимания на рисунок достаточно хорошо еще, чтобы определить, как я должен это сделать.

Я работаю на предположении, что редактор и проекта являются потенциально в одной и той же совокупности, с корнем будучи редактором. Поэтому я могу получить редактор, а затем перечислить свои проекты, и может оттуда перечислить Editors участников проектов.

Однако, если я только позволил получить редактор из моего репозитория, разве это не означает, что я должен загрузить все проекты из хранилища, когда я получаю редактор, который владеет им? И если я хочу ленивую нагрузку на Editors членов, проект необходима ссылка на хранилище, а?

С другой стороны, если я разделить совокупность и есть репозиторий редактора и репозиторий проекта, как я должен обрабатывать транзакции через два, например, когда новый проект добавляется в редакторе? Например:

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

Могу ли я искажая намерение Repository шаблона?

Задан 19/01/2009 в 15:10
пользователем
На других языках...                            


4 ответов

голоса
3

Это зависит от потребностей вашего приложения. Если это большая проблема , чтобы загрузить все проекты для данного редактора, а затем попробовать ленивый шаблон загрузки вроде виртуального прокси - сервера .

Что касается лениво загрузки Editors участником проекта, если вы используете виртуальный прокси-сервер, я не вижу, проблема инъекционного прокси с EditorRepository, так как я не считаю, прокси, чтобы быть частью домена.

Если вы разбили агрегированную, вы можете исследовать Единица работы шаблона в качестве одного решения атомарности. Эта проблема, однако, не является уникальной для DDD , и я уверен , что есть и другие решения для транзакционного поведения.

Ответил 23/01/2009 в 01:45
источник пользователем

голоса
4

Как насчет разделения обязанностей в EditorOwner и EditorMember?

Не зная ваш домен, я предположил бы, что они имеют разные обязанности - например, EditorOwner может быть весьма богатым (и может быть совокупным корнем), но проект может понадобиться знать только ограниченное количество информации о своих членах, так объект EditorMember может быть довольно легким.

Эти объекты области могут также относиться к пользователям, но это было бы в другом контексте.

Значит ли это помочь вещи, или просто сделать его более сложным?

Ответил 23/01/2009 в 03:55
источник пользователем

голоса
0

Здесь у вас есть 2 разных отношения, один для собственности и один для членства.

Собственность отношение простой один ко многим (один владелец для каждого проекта). Членство отношение многие ко многим (много редакторов по проекту, много проектов редактором).

Вы могли бы предоставить свойство Owner на класс проекта, и обеспечить способ на ProjectRepository получить все проекты, принадлежащие конкретному редактору.

Для многих отношений, обеспечивает свойство участников на классе проекта, и метод на ProjectRepository получить все проекты, содержащие указанный редактор в качестве члена.

Кроме того, кажется, что редактора и проекты являются юридическими лицами, я бы, вероятно, разделить агрегат, но, возможно, эти термины имеют особое значение в вашем контексте, которые делают его subentities из агрегата.

Ответил 11/02/2009 в 12:01
источник пользователем

голоса
30

Могу ли я искажая намерение Repository шаблона?

Я собираюсь сказать «да», но знаю , что я и каждый человек , с которыми я работал спросил то же самое по той же причине ... «Вы не думаете 4th размерно, Марти».

Давайте упростим немного и придерживаться конструкторов вместо создания методов первыми:

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будет делать.

И если я хочу ленивую нагрузку на Editors членов, проект необходима ссылка на хранилище, а?

Теперь о том, как повторно заполнить проекты редактора по требованию, у вас есть несколько вариантов, в зависимости от того, что вы собираетесь. Прямой Repository говорит, что вы хотите:

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

Но куда его деть? Не внутри проекта, или редактор, вы правы, или они должны будут получить доступ к хранилищам и это не хорошо. Выше фрагмент кода слабо связаны, но не подлежит повторному использованию на своих собственных. Вы только что достигли пределов Repository Pattern.

Затем это адаптер слой для вашего приложения, с общим источником хранилищ ( StaticServiceWrapper) и либо какое - то объект EditorAdapter (или агрегата или что вы хотите назвать их) или теперь вы можете смешать в методах расширения , которые могут говорить с любым и все необходимые хранилища свободно. Я не сделал это именно таким образом в производственной системе, но , чтобы показать вам краткий пример:

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, добавление, обновление, удаление Repository Object будет сделано, вы должны оставить в покое ассоциации и двигаться вверх по иерархии объекта / слоя к забаве части , как адаптеры и кэшей и бизнес - логики ( «О , мой!» ).

Ответил 14/05/2009 в 03:40
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more