Конструкция, управляемая доменом: репозиторий для каждого корневого узла? - PullRequest
4 голосов
/ 11 февраля 2011

Я пытаюсь выяснить, как выполнить следующее:

User can have many Websites

Что мне нужно сделать перед добавлением нового сайта пользователю, это взять URL-адрес сайта и передать егометод, который будет проверять, существует ли Веб-сайт уже в базе данных (тот же веб-сайт связан с другим Пользователем) или создать новую запись.<= Причина этого заключается в том, создавать ли новый эскиз или использовать существующий. </p>

Проблема в том, что репозиторий должен быть для каждого агрегатного корня, что означает, что я не могу сделать то, что объяснил выше?- Я мог бы сначала получить ВСЕХ пользователей в базе данных, а затем каждый раз просматривать оператор if, который проверяет, есть ли у пользователя запись веб-сайта с тем же URL-адресом, но это приведет к бесконечному и медленному процессу.

Ответы [ 3 ]

4 голосов
/ 11 февраля 2011

Какой бы подход к хранилищу вы ни использовали, вы должны иметь возможность задавать критерии каким-либо образом.Поэтому выполните поиск пользователя, связанного с данным веб-сайтом - если поиск не возвращает пользователей, веб-сайт не используется.

Например, вы можете добавить метод со следующей подписью (или выпередать объект запроса как , описанный в этой статье ):

User GetUser(string hasUrl);

Этот метод должен генерировать SQL более или менее так:

select u.userId
from   User u
join   Website w
on     w.UserId = u.UserId
where  w.Url    = @url

Это должно быть почтитакой же эффективный, как прямой запрос к таблице Website;нет необходимости загружать всех пользователей и записи сайта в память.Позвольте вашей реляционной базе данных выполнить тяжелую работу, а ваша реализация репозитория (или объектно-реляционный картограф) обработает перевод.

1 голос
/ 12 февраля 2011

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

Но теперь, когда пользователь хочет добавить новый веб-сайт, вы сначала хотите проверить, существует ли «веб-сайт в базе данных», прежде чем создавать новый. Это означает, что веб-сайты действительно имеют глобальный охват. В противном случае каждый раз, когда пользователь запрашивает новый веб-сайт, вы создаете новый веб-сайт для этого конкретного пользователя, причем этот веб-сайт имеет значение для данного пользователя. Здесь у вас есть веб-сайты, которые являются общими и, следовательно, значимыми для многих пользователей и поэтому не входят в совокупность пользователей.

Исправьте свою модель, и вы исправите трудности запроса.

0 голосов
/ 11 февраля 2011

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

public interface IWebsiteUniquenessValidator 
{
    bool IsWebsiteUnique(string websiteUrl);
}

Затем вам придется реализовать это, то, как вы это сделаете, будет зависеть от факторов, которых я не знаю, но я предлагаю не беспокоиться о прохождении домена. Сделайте это просто, это всего лишь запрос (* - я добавлю к этому внизу).

public class WebsiteUniquenessValidator : IWebsiteUniquenessValidator
{
 //.....
}

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

public class User 
{
    public void AddWebsite(string websiteUrl, IWebsiteUniquenessValidator uniquenessValidator) 
    {
        if (!uniquenessValidator.IsWebsiteUnique(websiteUrl) {
            throw new ValidationException(...);
        }

        //....
    }
}

Независимо от того, кто является вашим пользователем и его репозиторием - если это класс Service или CommandHandler - может обеспечить эту зависимость для проверки уникальности. Этот потребитель должен быть подключен через IoC, так как он будет использовать UserRepository:

public class UserService 
{
    private readonly IUserRepository _repo;
    private readonly IWebsiteUniquenessValidator _validator;

    public UserService(IUserRepository repo, IWebsiteUniquenessValidator validator) 
    {
        _repo = repo;
        _validator = validator;
    }

    public Result AddWebsiteToUser(Guid userId, string websiteUrl)
    {
        try {
            var user = _repo.Get(userId);
            user.AddWebsite(websiteUrl, _validator);
        }
        catch (AggregateNotFoundException ex) {
          //....
        }
        catch (ValidationException ex) {
          //....
        }
    } 


}

* Я упомянул упрощение проверки и обход домена.

Мы создаем домены для инкапсуляции часто сложного поведения, связанного с изменением данных.

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

Это похоже на болевую точку, которую вы испытываете, потому что вы пытаетесь заставить чтение пройти систему записи.

Можно отделить чтение данных от Домена со стороны записи, чтобы облегчить эти болевые точки.

CQRS - название, данное этой технике. Я просто скажу, что целая куча лампочек щелкнула, когда я просмотрел DDD в контексте CQRS. Я настоятельно рекомендую попытаться понять концепции CQRS.

...