Справочная информация:
я проектирую серверное приложение и создаю отдельные библиотеки DLL для разных подсистем. Для упрощения скажем у меня есть две подсистемы: 1) Users
2)Projects
Публичный интерфейс пользователя имеет такой метод:
IEnumerable<User> GetUser(int id);
И открытый интерфейс Projects имеет такой метод:
IEnumerable<User> GetProjectUsers(int projectId);
Так, например, когда нам нужно отобразить пользователей для определенного проекта, мы можем позвонить, GetProjectUsers
и это вернет объекты с достаточной информацией для отображения в таблице данных или аналогичной.
Проблема: в
идеале, Projects
подсистема не должна также хранить информацию о пользователях и должна просто хранить идентификаторы пользователей, участвующих в проекте. Для того , чтобы служить GetProjectUsers
, он должен позвонить GetUser
в Users
системе для каждого идентификатора пользователя , хранящегося в собственной базе данных. Тем не менее, это требует много отдельных GetUser
вызовов, вызывая много отдельных запросов SQL внутри User
подсистемы. Я на самом деле не проверял это, но этот болтливый дизайн повлияет на масштабируемость системы.
Если бы я оставил в стороне разделение подсистем, я мог бы хранить всю информацию в одной схеме, доступной для обеих систем, и Projects
мог просто сделать так, JOIN
чтобы все пользователи проекта были в одном запросе. Projects
Также необходимо знать, как генерировать User
объекты из результатов запроса. Но это нарушает разделение, которое имеет много преимуществ.
Вопрос:
Может ли кто-нибудь предложить способ сохранить разделение, избегая при этом всех этих отдельных GetUser
вызовов во время GetProjectUsers
?
Например, одна из моих идей заключалась в том, чтобы пользователи могли предоставлять внешним системам возможность «помечать» пользователей парой метка-значение и запрашивать пользователей с определенным значением, например:
void AddUserTag(int userId, string tag, string value);
IEnumerable<User> GetUsersByTag(string tag, string value);
Затем система Projects может пометить каждого пользователя по мере его добавления в проект:
AddUserTag(userId,"project id", myProjectId.ToString());
и во время GetProjectUsers он может запросить всех пользователей проекта за один вызов:
var projectUsers = usersService.GetUsersByTag("project id", myProjectId.ToString());
часть, в которой я не уверен: да, пользователи не зависят от проектов, но на самом деле информация о членстве в проекте хранится в системе Пользователи, а не в проектах. Я просто не чувствую себя естественно, поэтому я пытаюсь определить, есть ли здесь большой недостаток, который я пропускаю.
источник
GetUser
вместо запросов к базе данных, будет выглядеть в кеше. Это означает, что на самом деле не имеет значения, сколько раз вы будете звонитьGetUser
, поскольку он будет загружать данные из памяти, а не из базы данных (если только кэш не был аннулирован).select
запросов в день, лучше использовать кэширование. С другой стороны, если вы добавляете миллиарды объектов в базу данных, но получаете только несколько тысячselect
с очень избирательнымиwhere
, кэширование может быть не таким уж полезным.