Это вопрос о дизайне модели домена.Как разделить репозиторий и сущности
Скажем, для дизайна домена с участием пользователей и групп, мы имеем следующие интерфейсы для реализации:
interface IUser
{
string Name{get;}
DateTime DOB {get;}
}
interface IGroup
{
string Name {get;}
bool IsUserInGroup(IUser user); // #1
void IncludeUser(IUser user); // #2
void ExcludeUser(IUser user); // #3
}
interface IUserRepository
{
IUser Create(string name);
IUser GetByName(string name);
void Remove(IUser user);
void Save(IUser user);
}
interface IGroupRepository
{
IGroup Create(string name);
IGroup GetByName(string name);
void Remove(IGroup group);
void Save(IGroup group);
}
хитрый бит реализовать # 1 # 2 и # 3, сохраняя классы сущностей (User , Group), отделяемых от классов репозитория (UserRepository, GroupRepository.)
Еще одна важная особенность заключается в том, что большинство систем RMDB не реализуют отношения «многие ко многим», и на практике всегда существует отдельная таблица (например, UserGroupAssociation), чтобы иметь записи, каждый ассоциирует пользователя и группу с помощью внешних ключей. Я хотел бы скрыть эту деталь реализации от интерфейсов домена и выставить эквивалентную логику через члены # 1 # 2 и # 3.
Эффект вызова # 2 и # 3 не должны сохраняться, пока объект группы в вопросе не было сохранено (т.е. передается методу() объекта хранилища Сохранить)
Как вы обычно это делаете?
Использование интерфейса - представить более высокий уровень понятия, чем просто ведро свойств для чтения/записи. Например, вместо 'class User {public byte [] PasswordHash {get; set;}}' не было бы лучше, если бы это был интерфейс IUser {bool VerifyPassword (строковый пароль);} '? – Ben
В этом примере вы не могли бы просто сделать свойство 'PasswordHash' частным (или защищенным, если вы ограничены ORM)? 'User' будет по-прежнему иметь реализацию' VerifyPassword() ', поэтому он не просто будет ведром свойств. –
Для простых методов это совершенно верно. Но для других, таких как IncludeUser() и ExcludeUser() (пример № 2 и № 3), реализации необходимо получить доступ к объекту репозитория и необязательно его собственный объект репозитория. В случае IncludeUser() классу группы необходимо будет поговорить с GroupRepository, UserGroupAssociationRepository. Однако, сущность, чтобы знать репозиторий, однако, очень нежелательна связь. – Ben