Здравствуйте, коллеги!
"Рисуется" 3-х звенное приложение с кэшем (у app-сервера). DataService будут использовать ORM (сейчас всё вертится на BLToolkit-е). Встал вопрос каким образом реализовать кэширование, и (по возможности) отложенную загрузку на клиенте. Пришли вот в какому варианту:
public abstract class ParentEntity : BizEntity
{
public abstract Guid ID { get; set; }
public abstract Guid ChildID { get; set; }
[MapIgnore]
public ChildEntity Child
{
get { return _dataService.GetObject<ChildEntity>(ChildID); }
protected set { ... }
}
}
Мои сомнения по поводу одновременного хранения ID и самого объекта.
Есть ли более кошерные способы?
P.S. хотим услышать как можно больше вариантов, их "+" и "-", потому что сами уже обессилили в бесконечных спорах о них...
>Мои сомнения по поводу одновременного хранения ID и самого объекта > Есть ли более кошерные способы?
Приведите цитату из Торы, из которой следует, что наличие ID нарушает
кашрут.
Если нужен, почему не приделать?
Здравствуйте, Аноним, Вы писали:
А>"Рисуется" 3-х звенное приложение с кэшем (у app-сервера). DataService будут использовать ORM (сейчас всё вертится на BLToolkit-е). Встал вопрос каким образом реализовать кэширование, и (по возможности) отложенную загрузку на клиенте. Пришли вот в какому варианту:
А> get { return _dataService.GetObject<ChildEntity>(ChildID); }
А внутри каждой энтити хранить ссылку на сервис разве кузяво?
А>P.S. хотим услышать как можно больше вариантов, их "+" и "-", потому что сами уже обессилили в бесконечных спорах о них...
А сбрасывать кеши когда либо планируется? Синхронизировать кеши будете?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, Аноним, Вы писали:
_FR>
А>> get { return _dataService.GetObject<ChildEntity>(ChildID); }
_FR>
_FR>А внутри каждой энтити хранить ссылку на сервис разве кузяво?
нет. конечно же _dataService — не мембер Entity (он синглетон)
_FR>А сбрасывать кеши когда либо планируется?
да: пока, практически в каждой таблице в БД храниться TimeStamp
_FR>Синхронизировать кеши будете?
планируем, с помощью "арбитра" (как правильно, по научному — не знаю.)
А>>> get { return _dataService.GetObject<ChildEntity>(ChildID); }
_FR>>А внутри каждой энтити хранить ссылку на сервис разве кузяво? B>нет. конечно же _dataService — не мембер Entity (он синглетон)
Ну по сравнению с этим уже ничего не страшно
От сабжевой проблемы тогда можно уйти очень просто: объявить методы-расширения:
public abstract class ParentEntity : BizEntity
{
public abstract Guid ID { get; set; }
public abstract Guid ChildID { get; set; }
}
static class DataMethods
{
public static ChildEntity Child(this XDataService /* тип _dataService у вас */ dataService, ParentEntity entity) {
if(dataService == null) {
throw new ArgumentNullException("dataService");
} else if(entity == null) {
throw new ArgumentNullException("entity");
}//ifreturn dataService.GetObject<ChildEntity>(entity.ChildID);
}
// Или даже так, если синглетон не режет глазpublic static ChildEntity Child(this ParentEntity entity) {
if(entity == null) {
throw new ArgumentNullException("entity");
}//ifreturn _dataService.GetObject<ChildEntity>(entity.ChildID);
}
}
_FR>>А сбрасывать кеши когда либо планируется? B>да: пока, практически в каждой таблице в БД храниться TimeStamp _FR>>Синхронизировать кеши будете? B>планируем, с помощью "арбитра" (как правильно, по научному — не знаю.)
"_dataService" — это тулкитный объект? Он эти два пункта сумеет выполнить?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Ну по сравнению с этим уже ничего не страшно
Извините, но не совсем понял, что Вы имели ввиду...
Окромя шуток. Почитал Ваши посты... ответы, на мой взгляд, адекватны и в тему.
Вот и подумал, может всё-таки действительно что-то страшное уже намутили, но сами не видим
Спасибо!
Здравствуйте, bin64, Вы писали:
_FR>>Ну по сравнению с этим уже ничего не страшно
B>Извините, но не совсем понял, что Вы имели ввиду... B>Окромя шуток. Почитал Ваши посты... ответы, на мой взгляд, адекватны и в тему. B>Вот и подумал, может всё-таки действительно что-то страшное уже намутили, но сами не видим B>Спасибо!
Данная ремарка посвящена использованию синглетона, ибо в некоторых кругах, к коим имею честь принадлежать и я, использование изменяемых глобальных объектов считается за не комильфо. Подробнее о синглетонах можно вычитать здесь.
Хорошим примером синглетона может служить DBNull.Value. Плохим — глобальный кеш объектов.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, Аноним, Вы писали:
А>>Есть ли более кошерные способы?
L>Кошерный способ — не использовать отложенную загрузку на клиенте. За подробностями — в гугль с запросом "n+1 problem".
Видимо, я не так объяснил.
"Отложенная загрузка" — это возможность клиентской программе считывать данные по мере необходимости (и тем самым не захламлять память, возможно, лишними данными). Это совершенно не означает, что данные берутся прямо из БД. Просто-напросто, вовсе нет такой необходимости грузить все связанные объекты.
[off]есть ли способ редактирования ошибочно отправленного сообщения на RSDN?[/off]
Здравствуйте, _FRED_, Вы писали:
_FR>Данная ремарка посвящена использованию синглетона, ибо в некоторых кругах, к коим имею честь принадлежать и я, использование изменяемых глобальных объектов считается за не комильфо. Подробнее о синглетонах можно вычитать здесь.
Синглетон -- это когда нужен ровно один экземпляр. Вопрос контроля самого создания не ставится.
_dataService — именно этот случай. Кэш, как таковой, находится между БД и _dataService.
_FR>Хорошим примером синглетона может служить DBNull.Value. Плохим — глобальный кеш объектов.
Вот тут, видимо, тонкая грань и прорисовывается. Т.к. апп-серверов будет несколько (аля кластер), то решено было выделить Головного Арбитра. Он распределяет не только нагрузку по запросам, но и по кэшу (на самом деле их два: апп-арбитр и кэш-арбитр, для удобства, во время своих переговоров с коллегами мы объединяем их, для краткости). На каждом aпп-сервере есть свой арбитр, который в момент запуска определяется кто он: ведомый или ведущий...
Теперь вопрос. Такая модель, тоже является "плохим примером"?
Здравствуйте, bin64, Вы писали:
L>>Кошерный способ — не использовать отложенную загрузку на клиенте. За подробностями — в гугль с запросом "n+1 problem".
B>Видимо, я не так объяснил.
Вы все правильно объяснили.
B>"Отложенная загрузка" — это возможность клиентской программе считывать данные по мере необходимости (и тем самым не захламлять память, возможно, лишними данными). Это совершенно не означает, что данные берутся прямо из БД. Просто-напросто, вовсе нет такой необходимости грузить все связанные объекты.
Это не важно, берутся данные из базы или подкачиваются с апп-сервера. Проблема остается та же.
Здравствуйте, _FRED_, Вы писали:
B>>Вот и подумал, может всё-таки действительно что-то страшное уже намутили, но сами не видим B>>Спасибо!
_FR>Данная ремарка посвящена использованию синглетона, ибо в некоторых кругах, к коим имею честь принадлежать и я, использование изменяемых глобальных объектов считается за не комильфо.
Т.е. если синглтон сделать неизменяемым, то он сразу станет комильфо? Имхо, вы неправильно понимаете, почему синглтон — не комильфо.
_FR>Подробнее о синглетонах можно вычитать здесь.
_FR>Хорошим примером синглетона может служить DBNull.Value.
DBNull.Value — вообще ни разу ни синглтон. Ты бы еще null в этот отряд записал.
_FR>Плохим — глобальный кеш объектов.
А если он загружается при старте приложения и никогда более не меняется?
Здравствуйте, bin64, Вы писали:
B>Здравствуйте, Lloyd, Вы писали:
L>>Это не важно, берутся данные из базы или подкачиваются с апп-сервера. Проблема остается та же. B>Например?
погуглите по "n+1 problem". я вряд ли смогу лучше объяснить, чем гугл, у меня объяснялка плохо работает.
Здравствуйте, bin64, Вы писали:
_FR>>Данная ремарка посвящена использованию синглетона, ибо в некоторых кругах, к коим имею честь принадлежать и я, использование изменяемых глобальных объектов считается за не комильфо. Подробнее о синглетонах можно вычитать здесь. B>
B>Синглетон -- это когда нужен ровно один экземпляр. Вопрос контроля самого создания не ставится.
B>_dataService — именно этот случай. Кэш, как таковой, находится между БД и _dataService.
Именно про этот случай принято в нашей секте всячески порицать. Впрочем, никто вас не агитирует: если сказанно в статье не навело вас на "правильные" размышления, можете на мои слова внимания не обращать.
Разница в том, что "_dataService" у вас содержит некое состояние, которое требует настройки (это видно из протокола вызова — не сказано откуда брать данные, значит _dataService это знает, не сказано, как кешировать, значит _dataService это знает и прочее). Это очень печально видеть в, тем более, больших приложениях.
_FR>>Хорошим примером синглетона может служить DBNull.Value. Плохим — глобальный кеш объектов. B>Вот тут, видимо, тонкая грань и прорисовывается. Т.к. апп-серверов будет несколько (аля кластер), то решено было выделить Головного Арбитра. Он распределяет не только нагрузку по запросам, но и по кэшу (на самом деле их два: апп-арбитр и кэш-арбитр, для удобства, во время своих переговоров с коллегами мы объединяем их, для краткости). На каждом aпп-сервере есть свой арбитр, который в момент запуска определяется кто он: ведомый или ведущий... B>Теперь вопрос. Такая модель, тоже является "плохим примером"?
Понятия не имею, на самом деле вы сказали очень мало. Кстати, под "глобальный кеш объектов" я на самом деле подразумевал ("Плохим") не сам по-себе кеш, а реализацию его (доступа к нему) в виде синглетона.
Вообще я не очень понимаю идею распределения нагрузки "по кэшу" — это что же, распределятор должен знать, какой у кого кеш? Или по каким критериям он будет распределять? А то ведь и "по запросам" можно "распределять" в порядке живой очереди или даже рандомайзером
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, bin64, Вы писали:
_FR>Именно про этот случай принято в нашей секте всячески порицать. Впрочем, никто вас не агитирует: если сказанно в статье не навело вас на "правильные" размышления, можете на мои слова внимания не обращать.
Как говорится, дьявол кроется в мелочах... Высказывания мне не очень понравились, своей категоричностью. К сожалению, пока нет возможности её здесь обсуждать. Но в комментариях "несогласных" к статье, есть многое из-того с чем согласен. Всё-таки "мухи — отдельно, котлеты — отдельно"
_FR>Разница в том, что "_dataService" у вас содержит некое состояние, которое требует настройки (это видно из протокола вызова — не сказано откуда брать данные, значит _dataService это знает, не сказано, как кешировать, значит _dataService это знает и прочее). Это очень печально видеть в, тем более, больших приложениях.
Ок. Тогда по выделеному. Т.е., по вашему, в каждом обращении к данным из БД/кэша необходимо явно указыать/регулировать не только вызовы, но и откуда брать данные? ИМХО -- анархия... или я вообще не о том?
_FR>Понятия не имею, на самом деле вы сказали очень мало. Кстати, под "глобальный кеш объектов" я на самом деле подразумевал ("Плохим") не сам по-себе кеш, а реализацию его (доступа к нему) в виде синглетона.
А как тогда? Хотя бы примерно ткните пальцем на реализаию или тут в двух словах.
_FR>Вообще я не очень понимаю идею распределения нагрузки "по кэшу" — это что же, распределятор должен знать, какой у кого кеш? _FR>Или по каким критериям он будет распределять? А то ведь и "по запросам" можно "распределять" в порядке живой очереди или даже рандомайзером
Да, с кэшем (определение попадания/нахождения) есть некоторые проблемы, хотя и ID есть у каждого объекта. Однако, проблем с распределением как раз-таки — нет. Каждый арбитр (кэша) вычисляет условную нагрузку, объём данных и пр., а при опросе её возвращает, головному арбитру, который и решает что делать.
Признаться, в начаеле, мне самому не очень понравилась такая модель, да и исходники мы толком не видели в начале. Но человек, который это реализовал, продемострировал скорость работы на другом проекте, и мы пока приняли его . По ходу. Где можно посмотреть/почитать хорошую сатью о кластеризации/кэше (желательно, (но не обязательно) на русском -- у нас не все владеют английским на столько чтобы свободно читать)?
Здравствуйте, bin64, Вы писали:
_FR>>Разница в том, что "_dataService" у вас содержит некое состояние, которое требует настройки (это видно из протокола вызова — не сказано откуда брать данные, значит _dataService это знает, не сказано, как кешировать, значит _dataService это знает и прочее). Это очень печально видеть в, тем более, больших приложениях. B>Ок. Тогда по выделеному. Т.е., по вашему, в каждом обращении к данным из БД/кэша необходимо явно указыать/регулировать не только вызовы, но и откуда брать данные? ИМХО -- анархия... или я вообще не о том?
Нет конечно.
_FR>>Понятия не имею, на самом деле вы сказали очень мало. Кстати, под "глобальный кеш объектов" я на самом деле подразумевал ("Плохим") не сам по-себе кеш, а реализацию его (доступа к нему) в виде синглетона. B>А как тогда? Хотя бы примерно ткните пальцем на реализаию или тут в двух словах.
Не делать синглетон. Например, иметь DI-контейнер и передавать ссылку на него в различные куски программы.
_FR>>Вообще я не очень понимаю идею распределения нагрузки "по кэшу" — это что же, распределятор должен знать, какой у кого кеш? _FR>>Или по каким критериям он будет распределять? А то ведь и "по запросам" можно "распределять" в порядке живой очереди или даже рандомайзером B>Да, с кэшем (определение попадания/нахождения) есть некоторые проблемы, хотя и ID есть у каждого объекта. Однако, проблем с распределением как раз-таки — нет. Каждый арбитр (кэша) вычисляет условную нагрузку, объём данных и пр., а при опросе её возвращает, головному арбитру, который и решает что делать. B>Признаться, в начаеле, мне самому не очень понравилась такая модель, да и исходники мы толком не видели в начале. Но человек, который это реализовал, продемострировал скорость работы на другом проекте, и мы пока приняли его .
Без знания того, как именно и что конкретно при этом делается сложно давать советы.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, bin64, Вы писали:
_FR>>>Разница в том, что "_dataService" у вас содержит некое состояние, которое требует настройки (это видно из протокола вызова — не сказано откуда брать данные, значит _dataService это знает, не сказано, как кешировать, значит _dataService это знает и прочее). Это очень печально видеть в, тем более, больших приложениях. B>>Ок. Тогда по выделеному. Т.е., по вашему, в каждом обращении к данным из БД/кэша необходимо явно указыать/регулировать не только вызовы, но и откуда брать данные? ИМХО -- анархия... или я вообще не о том?
_FR>Нет конечно.
Если не затруднит, можно конкретнее и подробнее? Хотя бы на примере, того как надо. Мне вообще кажеться, что мы идём "не туда". Понятно, что идеальной архитектуры системы (тем более с самого начала) нет, но к идеалу стремиться всё-таки надо.
Здравствуйте, bin64, Вы писали:
_FR>>>>Разница в том, что "_dataService" у вас содержит некое состояние, которое требует настройки (это видно из протокола вызова — не сказано откуда брать данные, значит _dataService это знает, не сказано, как кешировать, значит _dataService это знает и прочее). Это очень печально видеть в, тем более, больших приложениях. B>>>Ок. Тогда по выделеному. Т.е., по вашему, в каждом обращении к данным из БД/кэша необходимо явно указыать/регулировать не только вызовы, но и откуда брать данные? ИМХО -- анархия... или я вообще не о том?
_FR>>Нет конечно. B>Если не затруднит, можно конкретнее и подробнее? Хотя бы на примере, того как надо. Мне вообще кажеться, что мы идём "не туда". Понятно, что идеальной архитектуры системы (тем более с самого начала) нет, но к идеалу стремиться всё-таки надо.
Ниже же и было сказано: передавать контейнер ("Не делать синглетон. Например, иметь DI-контейнер и передавать ссылку на него в различные куски программы."). Контейнер уже не будет синглетоном и при конструировании объектов сможет "честно" использоваться различные настройки.
Почитайте про IoC, DI и прочее и попробуйте написать программу со всем этим и без синглетонов.
Help will always be given at Hogwarts to those who ask for it.