Заранее извиняюсь если что не так написал, только начал изучение етих вопросов.
1.Объясните пожалуйста когда и что лучше использовать.
Мне известно два варианта заполнения объекта из базы данных.
а. Использование меппера, который заполняет и редактирует объект.
б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
Интересно что для первого варианта всегда употребляют слово меппер, для второго DAL объект.
2. Есть объект(Company), который заполняется меппeром(CompanyMapper).
У объекта Company есть функция CalcCreditRisk которая производит определённые
расчёты и должна взаимодействовать с данными из БД. Ето значит что ета функция внутри должна использовать
CompanyMapper.Ето меня и смущает, с одной стороны для заполнения объекта используется первый способ(а), а для расчёта второй(б). Что-то у меня не сходится. Помогите разобраться, со всеми возможными вариантами, как прабильно поступать.
Здравствуйте, Аноним, Вы писали:
А>Заранее извиняюсь если что не так написал, только начал изучение етих вопросов.
А>1.Объясните пожалуйста когда и что лучше использовать.
А> Мне известно два варианта заполнения объекта из базы данных. А> а. Использование меппера, который заполняет и редактирует объект. А> б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
А> Интересно что для первого варианта всегда употребляют слово меппер, для второго DAL объект.
А>2. Есть объект(Company), который заполняется меппeром(CompanyMapper). А> У объекта Company есть функция CalcCreditRisk которая производит определённые А> расчёты и должна взаимодействовать с данными из БД. Ето значит что ета функция внутри должна использовать А> CompanyMapper.Ето меня и смущает, с одной стороны для заполнения объекта используется первый способ(а), а для расчёта второй(б). Что-то у меня не сходится. Помогите разобраться, со всеми возможными вариантами, как прабильно поступать.
Все хотят хорошо провести время, но время не проведешь !
Re[2]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
25.04.05 05:53
Оценка:
Здравствуйте, Chupa_Kabra, Вы писали:
C_K>Здравствуйте, Аноним, Вы писали:
А>>Заранее извиняюсь если что не так написал, только начал изучение етих вопросов.
А>>1.Объясните пожалуйста когда и что лучше использовать.
А>> Мне известно два варианта заполнения объекта из базы данных. А>> а. Использование меппера, который заполняет и редактирует объект. А>> б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
А>> Интересно что для первого варианта всегда употребляют слово меппер, для второго DAL объект.
А>>2. Есть объект(Company), который заполняется меппeром(CompanyMapper). А>> У объекта Company есть функция CalcCreditRisk которая производит определённые А>> расчёты и должна взаимодействовать с данными из БД. Ето значит что ета функция внутри должна использовать А>> CompanyMapper.Ето меня и смущает, с одной стороны для заполнения объекта используется первый способ(а), а для расчёта второй(б). Что-то у меня не сходится. Помогите разобраться, со всеми возможными вариантами, как прабильно поступать.
C_K>Посмотри на этот мапер
Хороший меппер, но только он не дал мне ответов на мой вопрос.
Судя по етому мепперу комманда RSDN активно использует reflection , а все говорят что ето тормоза, видимо ето не так страшно.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Chupa_Kabra, Вы писали:
C_K>>Здравствуйте, Аноним, Вы писали:
А>>>Заранее извиняюсь если что не так написал, только начал изучение етих вопросов.
А>>>1.Объясните пожалуйста когда и что лучше использовать.
А>>> Мне известно два варианта заполнения объекта из базы данных. А>>> а. Использование меппера, который заполняет и редактирует объект. А>>> б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
А>>> Интересно что для первого варианта всегда употребляют слово меппер, для второго DAL объект.
А>>>2. Есть объект(Company), который заполняется меппeром(CompanyMapper). А>>> У объекта Company есть функция CalcCreditRisk которая производит определённые А>>> расчёты и должна взаимодействовать с данными из БД. Ето значит что ета функция внутри должна использовать А>>> CompanyMapper.Ето меня и смущает, с одной стороны для заполнения объекта используется первый способ(а), а для расчёта второй(б). Что-то у меня не сходится. Помогите разобраться, со всеми возможными вариантами, как прабильно поступать.
C_K>>Посмотри на этот мапер
А>Хороший меппер, но только он не дал мне ответов на мой вопрос.
А>Судя по етому мепперу комманда RSDN активно использует reflection , а все говорят что ето тормоза, видимо ето не так страшно.
Почитайте форум и посмотрите код, с каждым типов ваших данных ассоциируется mapper, который генерится на лету и в итоге никакого рефлекшина нет.
Все хотят хорошо провести время, но время не проведешь !
> 2. Есть объект(Company), который заполняется меппeром(CompanyMapper). > У объекта Company есть функция CalcCreditRisk которая производит определённые > расчёты и должна взаимодействовать с данными из БД. Ето значит что ета функция внутри должна использовать > CompanyMapper.Ето меня и смущает, с одной стороны для заполнения объекта используется первый способ(а), а для расчёта второй(б). Что-то у меня не сходится. Помогите разобраться, со всеми возможными вариантами, как прабильно поступать.
вот этого-то она как раз и не должна: маппер занимается отображением данных БД в данные модели предметной области и обратно, а не обслуживанием всей работы данного объекта с БД. И придуман он для того, чтобы модель предметной области (а она появляется когда БЛ нетривиальная) ничегошеньки не знала о том, как и где она хранится. Это облегчает ее разработку, поддержку и юнит-тестирование.
По сути, тебе бы надо иметь 2 способа вычисления Credit Risk: в памяти и в БД. Можно написать 2 стратежки (впрос как подсовывать, но это тебе виднее), которые наверняка захочется назвать шлюзом ибо похож.
ЗЫ: Мое скромное ИМХО...
Posted via RSDN NNTP Server 1.9
Да хранит вас господь в сухом прохладном месте...
Re[2]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
25.04.05 06:35
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:
>> 2. Есть объект(Company), который заполняется меппeром(CompanyMapper). >> У объекта Company есть функция CalcCreditRisk которая производит определённые >> расчёты и должна взаимодействовать с данными из БД. Ето значит что ета функция внутри должна использовать >> CompanyMapper.Ето меня и смущает, с одной стороны для заполнения объекта используется первый способ(а), а для расчёта второй(б). Что-то у меня не сходится. Помогите разобраться, со всеми возможными вариантами, как прабильно поступать.
КП>вот этого-то она как раз и не должна: маппер занимается отображением данных БД в данные модели предметной области и обратно, а не обслуживанием всей работы данного объекта с БД. И придуман он для того, чтобы модель предметной области (а она появляется когда БЛ нетривиальная) ничегошеньки не знала о том, как и где она хранится. Это облегчает ее разработку, поддержку и юнит-тестирование. КП>По сути, тебе бы надо иметь 2 способа вычисления Credit Risk: в памяти и в БД. Можно написать 2 стратежки (впрос как подсовывать, но это тебе виднее), которые наверняка захочется назвать шлюзом ибо похож.
Спасибо.
У меня возник вопрос про класс стратегия который будет работать с БД.
Как он должен взаимодейсцтвовать с БД.
КП>ЗЫ: Мое скромное ИМХО...
Re[4]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
25.04.05 06:37
Оценка:
Здравствуйте, Chupa_Kabra, Вы писали:
C_K>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Chupa_Kabra, Вы писали:
C_K>>>Здравствуйте, Аноним, Вы писали:
А>>>>Заранее извиняюсь если что не так написал, только начал изучение етих вопросов.
А>>>>1.Объясните пожалуйста когда и что лучше использовать.
А>>>> Мне известно два варианта заполнения объекта из базы данных. А>>>> а. Использование меппера, который заполняет и редактирует объект. А>>>> б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
А>>>> Интересно что для первого варианта всегда употребляют слово меппер, для второго DAL объект.
А>>>>2. Есть объект(Company), который заполняется меппeром(CompanyMapper). А>>>> У объекта Company есть функция CalcCreditRisk которая производит определённые А>>>> расчёты и должна взаимодействовать с данными из БД. Ето значит что ета функция внутри должна использовать А>>>> CompanyMapper.Ето меня и смущает, с одной стороны для заполнения объекта используется первый способ(а), а для расчёта второй(б). Что-то у меня не сходится. Помогите разобраться, со всеми возможными вариантами, как прабильно поступать.
C_K>>>Посмотри на этот мапер
А>>Хороший меппер, но только он не дал мне ответов на мой вопрос.
А>>Судя по етому мепперу комманда RSDN активно использует reflection , а все говорят что ето тормоза, видимо ето не так страшно. C_K>Почитайте форум и посмотрите код, с каждым типов ваших данных ассоциируется mapper, который генерится на лету и в итоге никакого рефлекшина нет.
Спасибо, обязательно почитаю
> Спасибо. > У меня возник вопрос про класс стратегия который будет работать с БД. > Как он должен взаимодейсцтвовать с БД.
точно так же как и маппер (по сути, реализация, которая работает с БД — это тот же слой, что и мапперы).
Если я правильно понимаю классику жанра, то для расчета риска ты должен засосать в память все используемые объекты и вызовами их методов получить результат. Но для тебя это неприемлемо, ибо много памяти, медленно или что-то еще, поэтому ты оптимизируешь так, что эти вычисления производятся в БД. Но писать код этого метода в самом классе предметной области не хочется. Поэтому ты описывашь некий интерфейс стратегии:
public interface ICreditRiskCalculation {
int CalculateCreditRisk(Declarant dec);
}
Потом пишешь его реализацию, которая аналогично мапперу лезет в БД, вызывает процедуру и получает результат, слегка его обрабатывает и возвращает.
Если есть желание — пишешь вторую реализацию (типа, тестовую) которая что-то возвращает сама, без БД.
Теперь при создании объекта маппером ты создаешь реализацию стратегии, которая работает с БД, и подсовываешь созданному объекту ссылку на нее (в виде ссылки на интерфейс). Все, когда надо — берешь из полей ссылку на стратегию и дергаешь ее (можешь даже целый метод написать для полной наглядности).
Если объект создается не маппером, то в конструкторе создаешь стратегию по умолчанию, которая в БД не лазает, тем самым получая тестовый вариант.
Posted via RSDN NNTP Server 1.9
Да хранит вас господь в сухом прохладном месте...
Re[4]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
25.04.05 07:06
Оценка:
Потом пишешь его реализацию, которая аналогично мапперу лезет в БД, вызывает процедуру и получает результат, слегка его обрабатывает и возвращает.
На етом хотелось бы остановится по-подробней.
Етот расчёт действительно делается полностью в Бд в СП. Расчёт имеет отношение к бизнесс логики, поетому он не должен лезть сам в БД, а через какой-то DAL(Mapper)
объект. Что-то у меня каша какая-та в голове.
> Етот расчёт действительно делается полностью в Бд в СП. Расчёт имеет отношение к бизнесс логики, поетому он не должен лезть сам в БД, а через какой-то DAL(Mapper) > объект. Что-то у меня каша какая-та в голове.
вот представь свою модель. Какой класс в ответе за вычисление этого риска? Я так думаю, что какая-то Заявка (к примеру). Соответсвенно, все желающие получить эти сведения для известной им заявки будут делать так:
Заявка ord;
int risk = ord.GetCreditRisk();
Похож? Далее. Класс Заявка не хочет ничего знать о том, где и как производятся вычисления, верно? Значит его надо от этого абстрагировать. Ты настаиваешь на том, что этот класс должен дернуть какой-то DAL(Mapper). Я же говорю, что не стоит (чтобы у других не было соблазна его дергать), а написать стратегию (в твоих терминах тот же DAL, только с одним методом и никому кроме тебя недоступный). Вот и все. Не надо давать сервис по вычислению риска никому кроме ответственного за это объекта. А уж он должен позаботиться о том, как его предоставить окружающим.
Возможно, я ошибся в предположении и в ответе за этот сервис будет Заявитель, но опять же, тебе виднее...
Posted via RSDN NNTP Server 1.9
Да хранит вас господь в сухом прохладном месте...
Re[6]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
25.04.05 07:50
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:
>> Етот расчёт действительно делается полностью в Бд в СП. Расчёт имеет отношение к бизнесс логики, поетому он не должен лезть сам в БД, а через какой-то DAL(Mapper) >> объект. Что-то у меня каша какая-та в голове.
КП>вот представь свою модель. Какой класс в ответе за вычисление этого риска? Я так думаю, что какая-то Заявка (к примеру). Соответсвенно, все желающие получить эти сведения для известной им заявки будут делать так: КП>Заявка ord; КП>int risk = ord.GetCreditRisk();
КП>Похож?
Да, похож.
Давай определимся с терминами.
Я понимаю под стратегией класс который, отвечает за логику расчёта риска.
Он взаимодействует с БД. И если я правильно понимаю, то обращение к БД, должно быть в этом же классе. Может это оправдано поскольку основная логика написана в процедуре, но если сама стратегия отягасчена логикой и многократными обращениями в БД, то мы теряем разделение между двумя слоями, или я неправильно понял.
> Давай определимся с терминами. > Я понимаю под стратегией класс который, отвечает за логику расчёта риска. > Он взаимодействует с БД. И если я правильно понимаю, то обращение к БД, должно быть в этом же классе. Может это оправдано поскольку основная логика написана в процедуре, но если сама стратегия отягасчена логикой и многократными обращениями в БД, то мы теряем разделение между двумя слоями, или я неправильно понял.
ну, я не знаю, что там за алгоритм Я рассчитываю на эту стратегию как на некоторую оболочку над процедурой (уж коли ты ее написал в БД) и не имеющую никакой логики кроме вызова этой процедуры и представления результатов.
Если есть куча логики, но она требует только вызова (возможно, и многократного) этой процедуры — так и напиши ее в методе ответственного класса, а стратегию оставь как оболочку над вызовом процедуры, и никакого перемешивания слоев не будет.
Posted via RSDN NNTP Server 1.9
Да хранит вас господь в сухом прохладном месте...
Re[8]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
25.04.05 08:21
Оценка:
Алгоритм довольно сложный, проверяющий всю поднаготную самой компании, дочерних и родительских компаний. Нужна скорость, поетому перенесли её в прцедуру.
Ну вообщем разобрались.
А как по-поводу первого вопроса, как лучше и правильней.
> А как по-поводу первого вопроса, как лучше и правильней.
и так хорошо, и эдак. см тут раздел Data Source Architectural Patterns, в основном наверное Table Data Gateway и Data Mapper.
Posted via RSDN NNTP Server 1.9
Да хранит вас господь в сухом прохладном месте...
Re[10]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
25.04.05 09:06
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:
>> А как по-поводу первого вопроса, как лучше и правильней. КП>и так хорошо, и эдак. см тут раздел Data Source Architectural Patterns, в основном наверное Table Data Gateway и Data Mapper.
Здравствуйте, Аноним, Вы писали:
[..] А>Давай определимся с терминами. А>Я понимаю под стратегией класс который, отвечает за логику расчёта риска. А>Он взаимодействует с БД. И если я правильно понимаю, то обращение к БД, должно быть в этом же классе. Может это оправдано поскольку основная логика написана в процедуре, но если сама стратегия отягасчена логикой и многократными обращениями в БД, то мы теряем разделение между двумя слоями, или я неправильно понял.
Логическое разделение между слоями — не самоцель, а средство. В определенных случаях бывает выгодно выделить частные решения в рамках системы, которые могут (внутри себя) нарушать это самое четкое разделение.
А> Мне известно два варианта заполнения объекта из базы данных. А> а. Использование меппера, который заполняет и редактирует объект. А> б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
Без разницы. Просто вариант а лучше выделенным слоем DAL. А следовательно есть путь к независимости от типа источника.
А> Интересно что для первого варианта всегда употребляют слово меппер, для второго DAL объект.
Обычно для второго употребляют CRUD объект. (CRUD — create, read, update, delete).
А>2. Есть объект(Company), который заполняется меппeром(CompanyMapper). А> У объекта Company есть функция CalcCreditRisk которая производит определённые А> расчёты и должна взаимодействовать с данными из БД. Ето значит что ета функция внутри должна использовать А> CompanyMapper.Ето меня и смущает, с одной стороны для заполнения объекта используется первый способ(а), а для расчёта второй(б). Что-то у меня не сходится. Помогите разобраться, со всеми возможными вариантами, как прабильно поступать.
Наибольшая проблема таких систем — рассогласования кэша и состояния базы данных. Допустим, у тебя Company изменил аттрибут. Тут ты лезешь в базу в котором лежат старое состояние объекта Company. В результате получаешь неверный результат.
Здравствуйте, <Аноним>, Вы писали:
А> Мне известно два варианта заполнения объекта из базы данных. А> а. Использование меппера, который заполняет и редактирует объект. А> б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
Принципиальный вопрос, но с мапперами он связан весьма опосредованно. Mapping — это процесс отображения чего-либо на что-либо. В данном контексте — построение соответствий между полями таблиц базы данных и полями объекта. Твой же вопрос в большей степени относится к Object.Save() vs Save(Object).
В первом случае мы добавляем к связям, которые уже имеет объект ещё одну — связь с источником данных, в котором этот объект хранится, связь с внешним по отношению к объекту миром. Результат — если мы захотим использовать объект повторно, то мы получим в нагрузку и эту связь. Так например, если мы имеем толстого клиента и сервер приложений и хотим использовать объект и там и там, то нам придётся тащить на клиента практически весь бизнес код сервера. В общем, добавление к объекту внешних по отношению к нему связей всегда приводит к куче ограничений и проблем в дальнейшем.
Проблема второго варианта в том, что он выгладит некошерно, не очень объекто ориентированно
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
02.05.05 19:09
Оценка:
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, <Аноним>, Вы писали:
А>> Мне известно два варианта заполнения объекта из базы данных. А>> а. Использование меппера, который заполняет и редактирует объект. А>> б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
IT>Принципиальный вопрос, но с мапперами он связан весьма опосредованно. Mapping — это процесс отображения чего-либо на что-либо. В данном контексте — построение соответствий между полями таблиц базы данных и полями объекта. Твой же вопрос в большей степени относится к Object.Save() vs Save(Object).
Но ето двухсторонняя связь, сохранение ето тоже своего рода отображения полей объекта на поля таблицы.
IT>В первом случае мы добавляем к связям, которые уже имеет объект ещё одну — связь с источником данных, в котором этот объект хранится, связь с внешним по отношению к объекту миром. Результат — если мы захотим использовать объект повторно, то мы получим в нагрузку и эту связь. Так например, если мы имеем толстого клиента и сервер приложений и хотим использовать объект и там и там, то нам придётся тащить на клиента практически весь бизнес код сервера. В общем, добавление к объекту внешних по отношению к нему связей всегда приводит к куче ограничений и проблем в дальнейшем.
IT>Проблема второго варианта в том, что он выгладит некошерно, не очень объекто ориентированно
Здравствуйте, <Аноним>, Вы писали:
IT>>Проблема второго варианта в том, что он выгладит некошерно, не очень объекто ориентированно
А>А как сделать кошерно?
Тут либо кошерно либо правильно
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
03.05.05 19:00
Оценка:
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, <Аноним>, Вы писали:
IT>>>Проблема второго варианта в том, что он выгладит некошерно, не очень объекто ориентированно
А>>А как сделать кошерно?
IT>Тут либо кошерно либо правильно
Тогда по отдельности, как сделать кошерно и как сделать правильно?
Здравствуйте, <Аноним>, Вы писали:
А>Тогда по отдельности, как сделать кошерно и как сделать правильно?
Моё ИМХО — правильно по возможности не порождать внешних по отношению к объекту связи. Например, имеется объект Company. Он инкапсулирует только то, что касается самого объекта: вычисления для которых достаточно данных самого объекта, навигацию по дочерним объектам, базовую валидацию и т.п. Если для выполнения какой-либо операции, типа CalcCreditRisk, требуется вовлечение внешних по отношению к объекту данных или использование других объектов, то такая операция должна выполняться другим объектам. Неважно как он называется, manager, service, controller, whatever. Т.е. в данном конкретном случае мы должны получить что-то типа:
public class Company
{
...
}
public class CompanyManager
{
public Company GetCompanyByID(int id)
{
}
public void AddCompany(Company company)
{
}
public void UpdateCompany(Company company)
{
}
public void DeleteCompany(Company company)
{
}
public CreditRiskResult CalcCreditRisk(Company company, ...)
{
}
}
Весь маппинг выполняется в соответствующих методах менеджера, в идеале в специальном слое — DAL.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
03.05.05 19:58
Оценка:
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, <Аноним>, Вы писали:
А>>Тогда по отдельности, как сделать кошерно и как сделать правильно?
IT>Моё ИМХО — правильно по возможности не порождать внешних по отношению к объекту связи. Например, имеется объект Company. Он инкапсулирует только то, что касается самого объекта: вычисления для которых достаточно данных самого объекта, навигацию по дочерним объектам, базовую валидацию и т.п. Если для выполнения какой-либо операции, типа CalcCreditRisk, требуется вовлечение внешних по отношению к объекту данных или использование других объектов, то такая операция должна выполняться другим объектам. Неважно как он называется, manager, service, controller, whatever. Т.е. в данном конкретном случае мы должны получить что-то типа:
IT>
IT>public class Company
IT>{
IT> ...
IT>}
IT>public class CompanyManager
IT>{
IT> public Company GetCompanyByID(int id)
IT> {
IT> }
IT> public void AddCompany(Company company)
IT> {
IT> }
IT> public void UpdateCompany(Company company)
IT> {
IT> }
IT> public void DeleteCompany(Company company)
IT> {
IT> }
IT> public CreditRiskResult CalcCreditRisk(Company company, ...)
IT> {
IT> }
IT>}
IT>
IT>Весь маппинг выполняется в соответствующих методах менеджера, в идеале в специальном слое — DAL.
Понятно, только по-поводу функции CalcCreditRisk хотелось бы прояснить, такой подход правильный если весь процесс расчёта происодит в БД, а как ето будет выглядеть если расчёт производит обработку информации полученной с БД, т.е ета функция имеет свою логику, ето значит она должна находится не в ДАЛ слое, ибо ДАЛ слой может содержать только логику доступа к БД.
Здравствуйте, <Аноним>, Вы писали:
А>Понятно, только по-поводу функции CalcCreditRisk хотелось бы прояснить, такой подход правильный если весь процесс расчёта происодит в БД, а как ето будет выглядеть если расчёт производит обработку информации полученной с БД, т.е ета функция имеет свою логику, ето значит она должна находится не в ДАЛ слое, ибо ДАЛ слой может содержать только логику доступа к БД.
Бизнес логике в БД вообще нечего делать. По многим причинам.
DAL — это слой изолирующий базу данных от нашего приложения. Его задача — переводить термины базы данных в термины приложения. Т.е. из полей таблиц сконструировать объекты и наоборот. Опять же, никакой бизнес логики кроме конструирования объектов в нём быть не должно.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
04.05.05 08:53
Оценка:
Здравствуйте, IT, Вы писали:
IT>Бизнес логике в БД вообще нечего делать. По многим причинам. IT>DAL — это слой изолирующий базу данных от нашего приложения. Его задача — переводить термины базы данных в термины приложения. Т.е. из полей таблиц сконструировать объекты и наоборот. Опять же, никакой бизнес логики кроме конструирования объектов в нём быть не должно.
А допустимо ли иметь у Company коллекцию Employess?
Здравствуйте, IT, Вы писали:
А>> Мне известно два варианта заполнения объекта из базы данных. А>> а. Использование меппера, который заполняет и редактирует объект. А>> б. Объект сам себя заполняет и редактирует при помощи DAL объекта который взаимодействует с БД.
IT>Принципиальный вопрос, но с мапперами он связан весьма опосредованно. Mapping — это процесс отображения чего-либо на что-либо. В данном контексте — построение соответствий между полями таблиц базы данных и полями объекта. Твой же вопрос в большей степени относится к Object.Save() vs Save(Object).
IT>В первом случае мы добавляем к связям, которые уже имеет объект ещё одну — связь с источником данных, в котором этот объект хранится, связь с внешним по отношению к объекту миром. Результат — если мы захотим использовать объект повторно, то мы получим в нагрузку и эту связь. Так например, если мы имеем толстого клиента и сервер приложений и хотим использовать объект и там и там, то нам придётся тащить на клиента практически весь бизнес код сервера. В общем, добавление к объекту внешних по отношению к нему связей всегда приводит к куче ограничений и проблем в дальнейшем.
IT>Проблема второго варианта в том, что он выгладит некошерно, не очень объекто ориентированно
Здравствуйте, GarryIV, Вы писали:
GIV>А как ты смотришь на сочетание этих подходов?
Отрицательно.
GIV>Вроде и выглядит кошерно и особых связей не плодится...
Даже две связи. Первая с IObjectMapper. Вторая со статическим методом MapperFactory.GetMapper. Причём, если первую связь ещё можно как-то пережить, то вторая порождает бинарную зависимость класса Object от MapperFactory, т.е. Object нельзя использовать без MapperFactory.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Даже две связи. Первая с IObjectMapper. Вторая со статическим методом MapperFactory.GetMapper. Причём, если первую связь ещё можно как-то пережить, то вторая порождает бинарную зависимость класса Object от MapperFactory, т.е. Object нельзя использовать без MapperFactory.
Что бы разорвать эту связь нужно при создании или во время инициализации Object каким-то образом передать ему ссылку на IObjectMapper. Что-нибудь типа:
interface IObjectMapper
{
void Save(Object o);
}
class Object
{
public Object(IObjectMapper mapper)
{
_mapper = mapper;
}
IObjectMapper _mapper;
public void Save()
{
_mapper.Save(this);
}
}
В принципе, вариант более менее рабочий. Связь только с абстрактным интерфейсом, который может быть реализован по разному в разных случаях. Но проблема в том, что этот вариант довольно громоздкий. Предположим IObjectMapper имеет не один, а десять методов связанных с Object. При использовании Object в другом окружении нам нужно будет реализовать, пусть даже как throw new NotImplementedException, все десять методов. В случае использования внешнего по отношению к Object объекта ObjectManager, нам нужно будет реализовать в новом окружении только то, что необходимо в этом окружении. И как правило это совершенно другой набор методов.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Действительно вариант очень громоздкий.
Хотел бы вернуться к начальному вопросу, который я спросил вначале, о реализации CalcCreditRisk — расчтёта риска, определённой фирмы.
Не знаю как лучше всё связать, вот упрощённая логика етого расчёта, хотелось бы услышать совета опытных людей.
Логика расчёта такова :
1. Получают всю негативную информацию о компании собранную за 5 лет (отдельная таблица).
2. Потом бегают по выбранной информации и делают определённый расчёт, в сависимости когда полученна ета информация. Расчёт производят на основе специальной матрицы, которая находится в базе данных.
3. В зависимости от расчёта проверяют надо ли проверять счета проверяемой компании, если да, то выбирают все счета которые когда либо были ограниченны в чём-то. Так-же производят определённый расчёт.
4. В зависимости от расчёта проверяют все дочерние фирмы, а так-же зависимые фирмы и производят для них такой-же расчёт, как и для основной компании, после етого выводится значение "риска".
Вот такая упрощённая логика. Для расчёта требуется дополнительная информация, но в зависимости от промежуточных результатов. Каким образом построить меппары, бизнес объекты, что-бы зависимость между ними была минимальна.
При етом хотелось бы, что бы и тестировать было легко.
Здравствуйте, igor_fle, Вы писали:
_>Вот такая упрощённая логика. Для расчёта требуется дополнительная информация, но в зависимости от промежуточных результатов. Каким образом построить меппары, бизнес объекты, что-бы зависимость между ними была минимальна.
Всё очень просто.
Бизнес сущности. Классы описывающие предметную область: Company, CompanyNegativeInfo и т.п. Желательно, что бы эти классы совпадали со структурой таблиц БД. В этом случае маппинг можно сдлать абсолютно примитивным, что существенно упростит DAL. В зависимости от общей архитектуры бизнес сущности могут быть вынесены в отдельный проект.
Бизнес логика. Сервисы или менеджеры (как больше нравится). Всё взаимодействие с БД только через DAL. Никаких исключений. На этот уровень можно вынести только контроль транзакций. Классы BL строго stateless, никакого сохранения состояния между вызовами.
DAL — Data Access. Никакой логики, кроме конструирования объектов из рекордсетов и наоборот. Весь маппинг делается здесь.
Методы BL и DAL вообще можно сделать статическими, но в этом случае мы теряем некоторые возможности по повторному использованию т.к. лишаемся виртуальных вызовов. Классы BL могут использовать DAL либо как агрегированные объекты, либо, опять же, как статические методы, либо создавать их всякий раз при необходимости. Ещё один (не очень кошерный) способ — использование наследования, т.е. когда класс бизнес логики наследуется от соответствующего ему DAL класса. Такая схема неплохо работает, когда имеется много pass-through методов.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
IT>Бизнес сущности. Классы описывающие предметную область: Company, CompanyNegativeInfo и т.п. Желательно, что бы эти классы совпадали со структурой таблиц БД. В этом случае маппинг можно сдлать абсолютно примитивным, что существенно упростит DAL. В зависимости от общей архитектуры бизнес сущности могут быть вынесены в отдельный проект.
Если обобщить, то бизнес сущности должны максимально быть похоже на свой источник данных.
Никаким образом не должны пересекаться с DAL, не должны знать о своём происхождении.
Бизнес сущности должны быть самодостаточными, т.е недопустимо чтобы за какой-то порцией данных было обращение к DAL, интересно а как-же с lozy load?
В моём случае получается, что функцию расчёта надо вынести из БО Company и перенести её в CompanyManager, который имеет отношение бизнес логике.
Правильно ли расматривать БО, как плоский объект, который должен иметь самую примитивную логику.
Каждый БО должен иметь объект БЛ который оперирует им (CompanyManager <---> Company)
Если у меня запрос состоит из нескольких таблиц, то как надо загружать БО? На каждую таблицу по БО или БО общий на запрос?
IT>Бизнес логика. Сервисы или менеджеры (как больше нравится). Всё взаимодействие с БД только через DAL. Никаких исключений. На этот уровень можно вынести только контроль транзакций. Классы BL строго stateless, никакого сохранения состояния между вызовами.
У меня есть объект DataManager, который абстрагирует работу с базой, правильно ли его создавать в етом слое и передабать объекту ДАЛ, или объект ДАЛ должен сам его создавать.
IT>DAL — Data Access. Никакой логики, кроме конструирования объектов из рекордсетов и наоборот. Весь маппинг делается здесь.
IT>Методы BL и DAL вообще можно сделать статическими, но в этом случае мы теряем некоторые возможности по повторному использованию т.к. лишаемся виртуальных вызовов. Классы BL могут использовать DAL либо как агрегированные объекты, либо, опять же, как статические методы, либо создавать их всякий раз при необходимости. Ещё один (не очень кошерный) способ — использование наследования, т.е. когда класс бизнес логики наследуется от соответствующего ему DAL класса. Такая схема неплохо работает, когда имеется много pass-through методов.
Здравствуйте, igor_fle, Вы писали:
_>Если обобщить, то бизнес сущности должны максимально быть похоже на свой источник данных.
Да. Упрощается мапинг.
_>Никаким образом не должны пересекаться с DAL, не должны знать о своём происхождении.
Пересекаться они будут, но с другой стороны. DAL о них будет знать всё.
_>Бизнес сущности должны быть самодостаточными, т.е недопустимо чтобы за какой-то порцией данных было обращение к DAL, интересно а как-же с lozy load?
Это не так. Самодостаточность необязательное условие. Этак можно всю базу через одну сущность вытянуть. К тому же, если я вывожу списко из 1000 ордеров, то одновременное поднятие деталей без необходимости только нагрузит сервера и трафик. Сущности надо поднимать по мере необходимости. У меня обычно получается набор методов типа GetOrderByID, GetOrderDetailsByID, GetOrderListByCustomer и т.п. Первого метода может и не быть, но если есть, то он возвращает только одну записть из таблицы Order, второй метод поднимает Order и все его детали, Items, Addresses и т.п., третий деталей тоже не возвращает, только главные записи. Если мне нужны детали для конкретного ордера, то я вызову потом GetOrderDetailsByID. Но всё это, конечно же, зависит от задачи. Lazy loading я не использую. Красивая идея, но таит в себе множество подвохов. К тому же LL применяется в основном в системах построенных в стиле объектной модели (точнее в стиле пьяной обезъяны, по другому не назовёшь), я же здесь пропогандирую совершенно другой стиль
_>В моём случае получается, что функцию расчёта надо вынести из БО Company и перенести её в CompanyManager, который имеет отношение бизнес логике.
Точно.
_>Правильно ли расматривать БО, как плоский объект, который должен иметь самую примитивную логику.
Самую примитивную да. Что такое 'плоский' я плохо себе представляю.
_>Каждый БО должен иметь объект БЛ который оперирует им (CompanyManager <---> Company)
Интересный вопрос. Иногда это понимается именно так: один Manager — один БО. Тогда лучше думать о таких объектах как о сервисах: один Service — одна подсистема. Как правило такая подсистема обслуживает одну или несколько высокоуровневых сущностей и кучу вспомогательных. Например, OrderingService, всё о заказах.
_>Если у меня запрос состоит из нескольких таблиц, то как надо загружать БО? На каждую таблицу по БО или БО общий на запрос?
Что имеется ввиду, несколько таблиц в одном запросе (JOIN) или несколько запросов за один раз?
В случае с заказами (GetOrderDetailsByID) можно было бы написать такой спрок:
CREATE PROCEDURE GetOrderDetailsByID
@OrderID int
AS
SELECT
Все_поля
FROM
Order
WHERE
OrderID = @OrderID
SELECT
Все_поля
FROM
OrderItem
WHERE
OrderID = @OrderID
GO
Далее DAL при использовании RFD получается примерно такой:
public Order GetOrderDetailsByID(int id)
{
using (DbManager db = new DbManager())
using (IDataReader dr = db
.SetSpCommand("GetOrderDetailsByID", id)
.ExecuteReader())
{
if (rd.Next())
{
Order order = (Order)Map.ToObject(rd, typeof(Order));
rd.NextResult();
Map.ToList(order.Items, typeof(OrderItem));
return order;
}
}
}
BL метод вырождается в pass-through.
IT>>Бизнес логика. Сервисы или менеджеры (как больше нравится). Всё взаимодействие с БД только через DAL. Никаких исключений. На этот уровень можно вынести только контроль транзакций. Классы BL строго stateless, никакого сохранения состояния между вызовами.
_>У меня есть объект DataManager, который абстрагирует работу с базой, правильно ли его создавать в етом слое и передабать объекту ДАЛ, или объект ДАЛ должен сам его создавать.
В случае с транзакциями его необходимо создавать в BL и передавать как параметер в DAL.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
IT wrote: > _>Если обобщить, то бизнес сущности должны максимально быть похоже на свой источник данных. > Да. Упрощается мапинг.
При этом либо кривеет модель предметной области (что понижает
понимабельность кода, расширяемость и простоту поддержки) либо модель
данных (что понижает производительность). Ищите, друзья, золотую
середину: крайности как правило приводят к геморрою
По всему остальному. Человеку нужно проанализировать общение с компанией
за несколько лет, потом поднять ее счета и т.д. Я продозреваю, что это:
1) большой объем данных
2) он носит исторический (не рабочий) характер (то есть этих данных в
памяти для текущей работы нет), скорее всего на них нет и модели классов
Из этого делаем совершенно тривиальный вывод, что имеет смысл вынести
этот расчет в БД, как говорится "move processing to data, not data to
processing". Вот вопрошающий и принял это решение.
Теперь давайте забудем о мепперах, ибо это понятие всех путает. Меппер
предназначен для того, что ОТОБРАЗИТЬ данные БД в модель предметной
области. Сам объект остается В ПОЛНОМ НЕВЕДЕНИИ о существовании этого
меппера. Об этом знает прикладной код, который загружает объект по
необходимости, сервисный слой (как у IT) и прочая. БО ничего не знает о
DAL, совсем, я думаю и о сервисном слое тоже, разве что о реестре
каком-нибудь, но это отдельная песня. Если LL, то пожалуйста через
посредников, обертки и т.п.: не надо захламлять объект предметной
области, это не его задача, а вопрос реализации оптимизации.
Далее. БО нужна эта функциональность (для каких-нибудь вычислений)? Если
да — то я уже предложил дать ему стратежку, которая будет принадлежать
DAL, ее интерфейс будет определен в модели предметной области и от нее
будет зависеть этот DAL (а он и так зависит, иначе как мапить). Если нет
— вынеси это в отдельный класс DAL, накрой сервисным слоем и пользуйся:
так будет понятнее и спокойнее всем.
Есть конкретные вопросы — милости просим. Тащить эти исторические данные
в память, организовывать для них модель классов не сильно хорошо ИМХО.
Здравствуйте, QwErTys, Вы писали:
IT>>Коллекцию иметь можно, но её заполнение — вопрос спорный. QET>Можно объяснить почему?
Если я закачиваю 1000 ордеров, то заполнение в каждом ордере коллекции айтемов увеличит объём данных в несколько раз, при том, что эта информация может оказаться абстолютно не нужной.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Козьма Прутков, Вы писали:
КП>При этом либо кривеет модель предметной области (что понижает понимабельность кода, расширяемость и простоту поддержки) либо модель данных (что понижает производительность). Ищите, друзья, золотую середину: крайности как правило приводят к геморрою
Весьма распространённое и в то же время ошибочное мнение, которым обычно прикрывается либо кривой дизайн базы либо объектной модели. В процессе разработки модель данных и структура базы могу и должны соответствовать друг другу. Вот ты мне можешь привести живой хороший пример, когда различия в структуре базы и модели заложены в дизайне? Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой.
КП>Из этого делаем совершенно тривиальный вывод, что имеет смысл вынести этот расчет в БД, как говорится "move processing to data, not data to processing".
К сожалению, автор не предоставил нам достаточной информации что бы делать столь однозначные выводы. Выносить логику в БД имеет смысл только если это даёт явные преимущества, как-то повышение произодительности в десятки раз. Но даже и здесь очень часто можно обойтись комбинированными решениями.
КП>Теперь давайте забудем о мепперах, ибо это понятие всех путает. Меппер предназначен для того, что ОТОБРАЗИТЬ данные БД в модель предметной области. Сам объект остается В ПОЛНОМ НЕВЕДЕНИИ о существовании этого меппера. Об этом знает прикладной код, который загружает объект по необходимости, сервисный слой (как у IT) и прочая. БО ничего не знает о DAL, совсем, я думаю и о сервисном слое тоже, разве что о реестре каком-нибудь, но это отдельная песня.
Здесь мы тоже имеем терминологическую путаницу. БО в классическом понимании ООП — это объект несущий в себе как данные, так и логику. Если эти две вещи разделять, то нам нужны новые термины, иначе мы можем начать называть одним термином разные вещи, ты будешь подразумевать под этим бизнес-сущность, а я сервисный объект.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
IT wrote: > Весьма распространённое и в то же время ошибочное мнение, которым обычно прикрывается либо кривой дизайн базы либо объектной модели. В процессе разработки модель данных и структура базы могу и должны соответствовать друг другу. Вот ты мне можешь привести живой хороший пример, когда различия в структуре базы и модели заложены в дизайне? Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой.
ну например не будешь же ты связь БД много-на-много через промежуточную
сущность отображать отдельным объектом? Не будешь.
Допустим, для оптимизации каких-нибудь отчетов ты денормализуешь схему,
что, и модель так же денормализовывать? Нет. Естественно, они будут
похожи, но не всегда один в один: представь, что ты уже имеешь чужую
базу и тебе надо на ней что-то построить. Я не думаю, что твоя модель
предметной области будет идентична наследию, ей богу
> К сожалению, автор не предоставил нам достаточной информации что бы
делать столь однозначные выводы. Выносить логику в БД имеет смысл только
если это даёт явные преимущества, как-то повышение произодительности в
десятки раз. Но даже и здесь очень часто можно обойтись комбинированными
решениями.
Алгоритм довольно сложный, проверяющий всю поднаготную самой компании,
дочерних и родительских компаний. Нужна скорость, поетому перенесли её в
прцедуру.
Это раз. Затем, мои тезисы можно считать своеобразными предположениями,
на которые я опираюсь, и если они не соответствуют действительности —
это сразу станет очевидно и автор меня поправит.
> Здесь мы тоже имеем терминологическую путаницу. БО в классическом понимании ООП — это объект несущий в себе как данные, так и логику. Если эти две вещи разделять, то нам нужны новые термины, иначе мы можем начать называть одним термином разные вещи, ты будешь подразумевать под этим бизнес-сущность, а я сервисный объект.
Да, верно. Я имею в виду бизнес-сущность. При этом, насколько я понимаю
слова вопрошающего, у него приложение построено на domain model и
смущает только то, что бизнес-сущность должна лезть в БД.
Ладно, спорить с пеной у рта тут бессмысленно: все равно мы имеем
довольно скромные сведения о всей задаче.
Вот пусть вопрошающий сам скажет, как у него уже сделано и к чему он
хочет прийти, тогда нам всем будет проще: не будем тащить человека
переписывать уже сделанное и лишь поможем ему принять правильное решение
для той конкретной проблемы, с которой он к нам обратился. Свое
понимание ситуации я уже излагал, так что есть материал для расстановки
акцентов и приоритетов.
Здравствуйте, Козьма Прутков, Вы писали:
КП>ну например не будешь же ты связь БД много-на-много через промежуточную сущность отображать отдельным объектом? Не будешь.
Если таблица содержит только ссылки, то не буду. Хотя если указатель на объект воспринимать как объект сам по себе, то вот тебе и мапинг
К тому же такие таблицы очень легко превращаются в обычные объекты. Стоит только нагрузить запись какими-нибудь данными.
Но это плохой пример. Мы говорим о бизнес-сущностях. То что в БД ссылки хранятся тоже в виде полей таблиц — это детали имплементации. Как я уже сказал выше, такие ссылки мапятся в указатели.
КП>Допустим, для оптимизации каких-нибудь отчетов ты денормализуешь схему, что, и модель так же денормализовывать? Нет. Естественно, они будут похожи, но не всегда один в один:
Чаще как раз расширяется модель, а не база. В модели могут присутствавать какие-нибудь агрегированные значения. Если же денормализуется база, то скорее всего это необходимо и модели.
КП>представь, что ты уже имеешь чужую базу и тебе надо на ней что-то построить. Я не думаю, что твоя модель предметной области будет идентична наследию, ей богу
Легаси код — это отдельная песьня. Иногда лучшим решением оказывается введение дополнительного слоя для изоляции это дела.
КП>
КП>Алгоритм довольно сложный, проверяющий всю поднаготную самой компании, дочерних и родительских компаний. Нужна скорость, поетому перенесли её в прцедуру.
КП>Это раз.
Сложность вижу, громадные объёмы данных не вижу.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[12]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
11.05.05 17:53
Оценка:
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, QwErTys, Вы писали:
IT>>>Коллекцию иметь можно, но её заполнение — вопрос спорный. QET>>Можно объяснить почему?
IT>Если я закачиваю 1000 ордеров, то заполнение в каждом ордере коллекции айтемов увеличит объём данных в несколько раз, при том, что эта информация может оказаться абстолютно не нужной.
Так а что ж тогда не пойти по пути частичной загрузки этих самых айтемов? Одно большое множество. По мере надобности поступают элементы в него. А уж коллекции — это лишь частное преобразование на множество (Employess, FiredEmployess, ActiveEmployess и т.п.)
Здравствуйте, <Аноним>, Вы писали:
IT>>Если я закачиваю 1000 ордеров, то заполнение в каждом ордере коллекции айтемов увеличит объём данных в несколько раз, при том, что эта информация может оказаться абстолютно не нужной.
А>Так а что ж тогда не пойти по пути частичной загрузки этих самых айтемов? Одно большое множество. По мере надобности поступают элементы в него. А уж коллекции — это лишь частное преобразование на множество (Employess, FiredEmployess, ActiveEmployess и т.п.)
Против кеширования по мере необходимости никто не возражает.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Я хочу поблагодарить вас за ваше участие, для меня важно понять принципы и выроботать для себя определённые правила, поскольку с таким подходом почти не имел дело. У нас все работают по принципу transaction script и в самом плохом его смысле, где логика и доступ к данным перемешаны, так мы работали с VB, а на C# так работать не хочется. Прочитал Фаулера, думал будет понятней, а наоборот ещё больше запутался.
По поводу примера, который я привёл, то причиной переноса логики в базу данных, стала производительность.
Объём обрабатыбаемой информации зависит от самой фирмы, насколько она большая, есть компании у которых более 200 компаний, что сказывается на объём. Ещё добавлю, что изначально ты даже не знаешь сколько и какой тебе потребуется информации, ибо ето зависит от промежуточных данных. Промежуточный объём не большой, но частое обращение к базе данных сказывается. Етот модуль изначально был написан на клипере, потом на VB, а сейчас на T-SQL, разница в скорости изменилась на несколько порядков. Хотя лично я считаю, что ето не самый лучший выбор. Во первых Т-SQL, сам по себе бедный, сложность в отладке, и конечно не дай бог если наш заказчик захочет перейти на ORACLE.
Я пытаюсь для себя выработать определённые правила, но пока только получается или всё белое или чёрное.
В принципе мне нравится идея БО, которые ничего не должны знать о свём происхождении, не должны взимодействовать с источником данных, пока у меня не выробаталась своя точка зрения на то, как поступать с такого рода функциями, которые должны взаимодействовать с дополнительными источниками данными.
Я уже писал, что думаю её место в CompanyManager, который будет оперировать с БО Company, и всем другим что ему понадобится. Но считаю, что идея со стратегией тоже правильная, хотя мы добавляем дополнительную зависимость БО от стратегии, Может ету стратегию надо передать в CompanyManager, ето было бы более правильно.
У меня есть ещё парочка вопросов на которые я не знаю однозначного ответа :
1. Для каждого ли запроса надо создавать БО или использование датаридера ето преступление с точки зрения архитектуры.
2. Предположим у меня есть много разных запросов к таблице Company, но в каждом запросе используются разное количество полей етой таблицы, надо использовать БО Company частично заполненный или создавать разные вариации БО.
3. Уточню ранее заданый мной вопрос по поводу сложных запросов, я имел виду JOIN. При таком запросе надо создавать БО по каждой таблице или можно сделать один БО содержащий все поля.
4. Как лучше заполнять БО который имеет больше 20 полей, через свойства или конструктор, который имеет все поля.
5. Есть много разных проектов, в которых есть разные вариации поиска, предположим таблицы Company.
Ети запросы разбросаны по разным проектам, должны ли все запросы находится в одном CompanyMapper или ето нормально, что запросы разбросаны. Вот пример из жизни. Есть вебсервис который возвращает список фирм, етот список содержит только адреса и телефоны, где должен находится етот запрос в CompanyMapper или в каком-то модуле вебсервиса.
Есть вероятность того, что кто еще захочет использовать етот запрос и добавит что-то.И компания использующая вебсервис по ошибке получит больше информации чем ей хотят дать.
Ну вообщем пока всё, большое спасибо Вам за ваше терпение, я понимаю что мои вопросы наивны и не всегда логичны, но ето отображает сегодняшний мой уровень понимания архитектуры приложения.
> мы добавляем дополнительную зависимость БО от стратегии, Может ету стратегию надо передать в CompanyManager, ето было бы более правильно.
ну, елки палки, я по-моему 2 раза написал, что БО зависит от ИНТЕРФЕЙСА
этой стратегии, определенном там же, где и БО. От него же зависит слой
данных, в котором присутствует реализация этого интерфейса. Так что
дополнительных зависимостей между слоями не добавляется.
> 1. Для каждого ли запроса надо создавать БО или использование датаридера ето преступление с точки зрения архитектуры.
я сейчас наблюдаю, как подрядчиком пишется приложение, которое выводит
список (результат поиска) путем загрузки коллекции БО. Это страшно
тормозит: вместо 1-го обращения к БД целых 80! И это только отладочные
данные, на несколько порядков меньшие по объему нежели рабочие. Так что
применить ридер с умом не считаю крамолой, вот только винформовый грид
им не умеет пользоваться
> 2. Предположим у меня есть много разных запросов к таблице Company, но в каждом запросе используются разное количество полей етой таблицы, надо использовать БО Company частично заполненный или создавать разные вариации БО.
вот этого ни в коем случае не надо! БО (то есть бизнес-сущность) ОДИН.
Он содержит все свои данные. Не надо никаких вариаций пока не появится
что-то типа классификации (наследования то есть) или чего-то еще.
> 3. Уточню ранее заданый мной вопрос по поводу сложных запросов, я имел виду JOIN. При таком запросе надо создавать БО по каждой таблице или можно сделать один БО содержащий все поля.
по сути, соответсвующий таблице. Надо тебе подчиненный объект потрогать
— лезь к нему по ссылке (Order.Customer.Name, а не Order.CustomerName).
> 4. Как лучше заполнять БО который имеет больше 20 полей, через свойства или конструктор, который имеет все поля.
не готов ответить. Зависит от обстоятельств. Я бы сделал конструктор с
критическими данными (то есть обязательными), а остальное — через свойства.
> 5. Есть много разных проектов, в которых есть разные вариации поиска, предположим таблицы Company. > Ети запросы разбросаны по разным проектам, должны ли все запросы находится в одном CompanyMapper или ето нормально, что запросы разбросаны. Вот пример из жизни. Есть вебсервис который возвращает список фирм, етот список содержит только адреса и телефоны, где должен находится етот запрос в CompanyMapper или в каком-то модуле вебсервиса.
насколько я понимаю, твое приложение умеет взять эти данные из разных
источников? Ну тогда меппер (менеджер тоже кстати) должен это скрывать,
иначе обо всех этих источниках, их назначении и взаимоотношениях узнает
все приложение. Не думаю, что это предел мечтаний
> Есть вероятность того, что кто еще захочет использовать етот запрос и добавит что-то.И компания использующая вебсервис по ошибке получит больше информации чем ей хотят дать.
ну, брат, это описание интерфейса и не более того. Надо слать 2 поля —
один интерфейс, надо 5 — другой.
> Ну вообщем пока всё, большое спасибо Вам за ваше терпение, я понимаю что мои вопросы наивны и не всегда логичны, но ето отображает сегодняшний мой уровень понимания архитектуры приложения.
Это хорошо: высказывая свое мнение и споря об истине мы все набираемся
бесценного опыта. А поднятая тема весьма актуальна.
Хочу подчекнуть еще раз, что все написанное ИМХО и не претендует на
непреложную истинность.
Здравствуйте, igor_fle, Вы писали:
_>У меня есть ещё парочка вопросов на которые я не знаю однозначного ответа : _>1. Для каждого ли запроса надо создавать БО или использование датаридера ето преступление с точки зрения архитектуры.
Нельзя создавать на каждый запрос новый тип БО. У каждого БО есть некоторая описательная часть (пускай даже не физические метаданные, а в описании постановки). Для датасетов согласованность типов в основном достигается автоматическим добавлением схемы конкретного БО в общую схему и генерации части запросов (например полей select) через метаданные или вручную. Для entity, согласование с помощью DAL объектов, или с выделение общего механизма маппинга объектов на БЛ и автоматической генерации поисковых запросов. _>2. Предположим у меня есть много разных запросов к таблице Company, но в каждом запросе используются разное количество полей етой таблицы, надо использовать БО Company частично заполненный или создавать разные вариации БО.
Опиши какую транзакционную систему ты будешь использовать. Это важно. Но скажу сразу, что нельзя один и те же данные использовать в разных бизнес-объектах. Причин много (от системы транзакций и согласования данных, до проблем с версионностью). _>3. Уточню ранее заданый мной вопрос по поводу сложных запросов, я имел виду JOIN. При таком запросе надо создавать БО по каждой таблице или можно сделать один БО содержащий все поля.
БО в каждой таблице это наиболее простой путь. Но более эффективный путь когда структура бизнес-объекта никак не зависит от хранения. Вот тогда это также вопрос настройки производительности. При выделенном DAL ты спокойно можешь делать как тебе удобнее. Сама бизнес-логика от этого не пострадает. Тогда и таблицы можно рефакторить. А это уже очень большой плюс. И в зависимости от типа основного использования, ты можешь выбрать тот, или иной компромисс. _>4. Как лучше заполнять БО который имеет больше 20 полей, через свойства или конструктор, который имеет все поля.
По фигу. Иногда даже есть смысл заполнять их через reflection. _>5. Есть много разных проектов, в которых есть разные вариации поиска, предположим таблицы Company.
Выдели метаданные, и сделай единый поисковый механизм который работает во всех случаях. _>Ети запросы разбросаны по разным проектам, должны ли все запросы находится в одном CompanyMapper или ето нормально, что запросы разбросаны. Вот пример из жизни. Есть вебсервис который возвращает список фирм, етот список содержит только адреса и телефоны, где должен находится етот запрос в CompanyMapper или в каком-то модуле вебсервиса. _>Есть вероятность того, что кто еще захочет использовать етот запрос и добавит что-то.И компания использующая вебсервис по ошибке получит больше информации чем ей хотят дать.
Запросы не должны быть разбросаны, а лежать в едином DAL слое. Иначе система будет практически открытой и придется писать парсер запросов для обеспечения безопасности. Общение клиентов должно происходить через некоторый выделенные слой, в котором уже определяется кошерность клиента и достоен ли он его выполнить. Также на нем должна лежать задача уменьшения гранулярности запроса (возможно даже с помощью механизма запросов, а ля command паттерн). Но клиент ни в коем случае не должен знать не то, что про хранение, но и даже про бизнес-логику (неважно что это, некоторая сервисная модель, или объектная).
Что касается данного случая, то тут может быть два варианта. Вариант 1 — в каждом webservice находится компоненты представляющие данный бизнес-объект, которые уже общаются с БД. Вариант 2 — webservice обращается в единый центр, на котором и находится вся логика для данного бизнес объекта. Второй вариант значительно лучше.
Вообще, попробуй описать примерный механизм обеспечения транзакционности и согласованности данных который будет реализован. Тогда тебе многое станет более понятным.
Здравствуйте, IT, Вы писали:
IT>Весьма распространённое и в то же время ошибочное мнение, которым обычно прикрывается либо кривой дизайн базы либо объектной модели. В процессе разработки модель данных и структура базы могу и должны соответствовать друг другу. Вот ты мне можешь привести живой хороший пример, когда различия в структуре базы и модели заложены в дизайне? Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой.
До фигищи. Из последнего. Большинство объектов наследуется от класса типа MyObject где лежит некоторая системная информация. Для всех объектов в наследовании лучше работать без join, кроме данного MyObject, поскольку оказалось что большинство достаточно много частых важных запросов проходит только по MyObject. Вот и выделяем MyObject в отдельную таблицу. И это не замазывание дыр. Это просто настройка производительности работы БД. И скорость от такой нормализации и денормалиции возросла на некоторых процессах на порядки.
Здравствуйте, IT, Вы писали:
IT>Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой.
Если бы все было так просто, думается создатели RDBMS давно уже бы предоставили свое собственное решение, а не выдавали наружу интерфейс наподобии ExecuteScalar ExecureReader и т.п.
И еще. Маппер как раз для того и нужен, если структура сложная. При просто городить огород нечего.
Здравствуйте, GlebZ, Вы писали:
GZ>До фигищи. Из последнего. Большинство объектов наследуется от класса типа MyObject где лежит некоторая системная информация. Для всех объектов в наследовании лучше работать без join, кроме данного MyObject, поскольку оказалось что большинство достаточно много частых важных запросов проходит только по MyObject. Вот и выделяем MyObject в отдельную таблицу. И это не замазывание дыр. Это просто настройка производительности работы БД. И скорость от такой нормализации и денормалиции возросла на некоторых процессах на порядки.
Информация о типе объекта как в базе хранится?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Mika Soukhov, Вы писали:
IT>>Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой.
MS>Если бы все было так просто,
Можно пример сложного?
MS> думается создатели RDBMS давно уже бы предоставили свое собственное решение, а не выдавали наружу интерфейс наподобии ExecuteScalar ExecureReader и т.п.
Для чего? Для UNIX, Windows, .NET, Java, C++? Или сразу для всего?
MS>И еще. Маппер как раз для того и нужен, если структура сложная. При просто городить огород нечего.
Mapper — это деталь имплементации, ничего более. Хелпер для DAL. Как ты думаешь, DAL вообще для чего нужен?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
IT>Если я закачиваю 1000 ордеров, то заполнение в каждом ордере коллекции айтемов увеличит объём данных в несколько раз, при том, что эта информация может оказаться абстолютно не нужной.
Я применял для такого случая спциальную коллкцию позволяющею получать данные страницами.
Здравствуйте, IT, Вы писали:
IT>Информация о типе объекта как в базе хранится?
В xml файле. Хранятся описания объектов — свойства, отношения наследования, ссылки и их отношения к БД. Тип в базе определяется либо по обязательным ссылкам (например обязательно должен быть связанные объект (класс потомок в объектой модели) в определенной таблице, либо по явному полю TypeID(в том числе и потому, что некоторые типы нельзя определить предыдущим способом).
Много написано, но всё равно для меня эти вещи абстрактные, нету до конца понимания, a что спросить не знаю. Тут наверное дело в опыте, пока сам не споткнёшся не поймёшь.
Может кто-нибудь знает какой-нибудь пример, что-бы можно было скачать и посмотреть,
на "правильную" архитектуру, желательно на C#.
_>>У меня есть ещё парочка вопросов на которые я не знаю однозначного ответа : _>>1. Для каждого ли запроса надо создавать БО или использование датаридера ето преступление с точки зрения архитектуры. GZ>Нельзя создавать на каждый запрос новый тип БО. У каждого БО есть некоторая описательная часть (пускай даже не физические метаданные, а в описании постановки). Для датасетов согласованность типов в основном достигается автоматическим добавлением схемы конкретного БО в общую схему и генерации части запросов (например полей select) через метаданные или вручную. Для entity, согласование с помощью DAL объектов, или с выделение общего механизма маппинга объектов на БЛ и автоматической генерации поисковых запросов.
Как быть в случаях, когда БО в разных проектах могут иметь разную форму.
Есть проект администрации (интранет), где всё идёт через XML. У нас есть своя библиотека, которая генерит ХМЛ из запроса в определённом формате, этот xml поступает на html клиент, где этим хмл бандятся контроли, тоже разработанные на нашей фирме( очень много javascript ), потом для сохранения генерится общий ХМЛ,
содержащий старую запись и измененную, забрасывается на сервер и при помощи той-же библиотеки меппируется на таблицы. Есть другой проект интернет, где по политическим соображениям не используют нашу замечательную библиотеку и там ты должен работать с теми-же таблицами, не ипользуя ХМЛ, и не очень хочется использовать dataset, а значит ты должен использовать БО как классы, вот и получаются различии. Правильно ли называть ХМЛ содержащий данные из базы данных БО или это уже DTO.
_>>2. Предположим у меня есть много разных запросов к таблице Company, но в каждом запросе используются разное количество полей етой таблицы, надо использовать БО Company частично заполненный или создавать разные вариации БО. GZ>Опиши какую транзакционную систему ты будешь использовать.
Что Вы имете ввиду.
GZ>Это важно. Но скажу сразу, что нельзя один и те же данные использовать в разных бизнес-объектах. Причин много (от GZ>системы транзакций и согласования данных, до проблем с версионностью). _>>3. Уточню ранее заданый мной вопрос по поводу сложных запросов, я имел виду JOIN. При таком запросе надо создавать БО по каждой таблице или можно сделать один БО содержащий все поля. GZ>БО в каждой таблице это наиболее простой путь. Но более эффективный путь когда структура бизнес-объекта никак не зависит от хранения. Вот тогда это также вопрос настройки производительности. При выделенном DAL ты спокойно можешь делать как тебе удобнее. Сама бизнес-логика от этого не пострадает. Тогда и таблицы можно рефакторить. А это уже очень большой плюс. И в зависимости от типа основного использования, ты можешь выбрать тот, или иной компромисс.
Согласен, что предназначение меппара, как раз и состоит в абстрагировании между БО и источником данных, но чем больше они похоже, тем проще DAL слой. Наверное различая появляются, только при довольно сложной логике и связях, но в большинстве они могут быть очень похоже, хотя всё зависит от нагрузки которую несёт БО.
Предположим если меняется структура в базе данных, есть дилемма, поменять ДАЛ слой не трогая БО, или поменять БО, что более логичней, при етом ты должен сделать рефакторинг всего своего кода, где он применяется. Но знаете иногда, когда смотришь на код, где-то через годик, ты уже не помнишь почему у тебя структура БО и базы данных разная, а DAL так извращается что-бы наложить БО на базу данных.
_>>4. Как лучше заполнять БО который имеет больше 20 полей, через свойства или конструктор, который имеет все поля. GZ>По фигу. Иногда даже есть смысл заполнять их через reflection.
Reflection это интересная тема, тут главное правильно поставить вопрос : в каких случаях её надо применять из-за производительности или в каких случаях её не надо применять,может не так чёрт страшен, как его рисуют.
_>>5. Есть много разных проектов, в которых есть разные вариации поиска, предположим таблицы Company. GZ>Выдели метаданные, и сделай единый поисковый механизм который работает во всех случаях.
А как эти слова преобразовать в код?
_>>Ети запросы разбросаны по разным проектам, должны ли все запросы находится в одном CompanyMapper или ето нормально, что запросы разбросаны. Вот пример из жизни. Есть вебсервис который возвращает список фирм, етот список содержит только адреса и телефоны, где должен находится етот запрос в CompanyMapper или в каком-то модуле вебсервиса. _>>Есть вероятность того, что кто еще захочет использовать етот запрос и добавит что-то.И компания использующая вебсервис по ошибке получит больше информации чем ей хотят дать. GZ>Запросы не должны быть разбросаны, а лежать в едином DAL слое. Иначе система будет практически открытой и придется писать парсер запросов для обеспечения безопасности.
Что такое парсер запросов в этом контексте?
GZ>Общение клиентов должно происходить через некоторый выделенные слой, в котором уже определяется кошерность клиента и достоен ли он его выполнить. Также на нем должна лежать задача уменьшения гранулярности запроса (возможно даже с помощью механизма запросов, а ля command паттерн). Но клиент ни в коем случае не должен знать не то, что про хранение, но и даже про бизнес-логику (неважно что это, некоторая сервисная модель, или объектная).
Написано хорошо, как это преобразовать в код не совсем понимаю.
Извините за не компетентность. Я не то что не умею писать классы, просто эти слова у меня не ассоциируются с чем-то реальным, абстракция.
GZ>Что касается данного случая, то тут может быть два варианта. Вариант 1 — в каждом webservice находится компоненты представляющие данный бизнес-объект, которые уже общаются с БД. Вариант 2 — webservice обращается в единый центр, на котором и находится вся логика для данного бизнес объекта. Второй вариант значительно лучше.
Это значит, что у меня есть отдельный общий проект, где хранятся все меппары или DAL объекты( как кому нравится ), в CompanyMapper будет функция GetCompanyForWebService(), GetCompanyForAdminSite(), GetCompanyForWebSite(),
GetCompanyForBatch() ....
Что-то вроде этого?
GZ>Вообще, попробуй описать примерный механизм обеспечения транзакционности и согласованности данных который будет реализован. Тогда тебе многое станет более понятным.
Можно по подробней, что вы имеете ввиду?
GZ>С уважением, Gleb.
Здравствуйте, Козьма Прутков, Вы писали:
>> мы добавляем дополнительную зависимость БО от стратегии, Может ету стратегию надо передать в CompanyManager, ето было бы более правильно.
КП>ну, елки палки, я по-моему 2 раза написал, что БО зависит от ИНТЕРФЕЙСА КП>этой стратегии, определенном там же, где и БО. От него же зависит слой КП>данных, в котором присутствует реализация этого интерфейса. Так что КП>дополнительных зависимостей между слоями не добавляется.
>> 1. Для каждого ли запроса надо создавать БО или использование датаридера ето преступление с точки зрения архитектуры.
КП>я сейчас наблюдаю, как подрядчиком пишется приложение, которое выводит КП>список (результат поиска) путем загрузки коллекции БО. Это страшно КП>тормозит: вместо 1-го обращения к БД целых 80! КП>И это только отладочные
КП>данные, на несколько порядков меньшие по объему нежели рабочие. Так что КП>применить ридер с умом не считаю крамолой, вот только винформовый грид КП>им не умеет пользоваться
А можно как сформировать ввиде каких-то общих правил, когда применять, а когда не применять.
>> 5. Есть много разных проектов, в которых есть разные вариации поиска, предположим таблицы Company. >> Ети запросы разбросаны по разным проектам, должны ли все запросы находится в одном CompanyMapper или ето нормально, что запросы разбросаны. Вот пример из жизни. Есть вебсервис который возвращает список фирм, етот список содержит только адреса и телефоны, где должен находится етот запрос в CompanyMapper или в каком-то модуле вебсервиса.
КП>насколько я понимаю, твое приложение умеет взять эти данные из разных КП>источников? Ну тогда меппер (менеджер тоже кстати) должен это скрывать, КП>иначе обо всех этих источниках, их назначении и взаимоотношениях узнает КП>все приложение. Не думаю, что это предел мечтаний
>> Есть вероятность того, что кто еще захочет использовать етот запрос и добавит что-то.И компания использующая вебсервис по ошибке получит больше информации чем ей хотят дать.
КП>ну, брат, это описание интерфейса и не более того. Надо слать 2 поля — КП>один интерфейс, надо 5 — другой.
Здравствуйте, QwErTys, Вы писали:
QET>Я применял для такого случая спциальную коллкцию позволяющею получать данные страницами.
Не использовать подобный подход мы договорились в самом начале топика. Это намертво гвоздями прибивает твою бизнес сущность к источнику данных.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[14]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
13.05.05 15:50
Оценка:
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, QwErTys, Вы писали:
QET>>Я применял для такого случая спциальную коллкцию позволяющею получать данные страницами.
IT>Не использовать подобный подход мы договорились в самом начале топика. Это намертво гвоздями прибивает твою бизнес сущность к источнику данных.
Здравствуйте, <Аноним>, Вы писали:
IT>>Не использовать подобный подход мы договорились в самом начале топика. Это намертво гвоздями прибивает твою бизнес сущность к источнику данных.
А>Из чего такое следует?
LoadPage откуда данные берёт?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, igor_fle, Вы писали:
_>Может кто-нибудь знает какой-нибудь пример, что-бы можно было скачать и посмотреть, _>на "правильную" архитектуру, желательно на C#.
А никто и не скажет, что такое "правильная" архитектура. Архитектура очень зависит от конкретного решения. Существует несколько шаблонов по которым строятся многозвенные и распределенные приложения. Все остальное творчество, или использование готовых решений.
_>Как быть в случаях, когда БО в разных проектах могут иметь разную форму. _>Есть проект администрации (интранет), где всё идёт через XML. У нас есть своя библиотека, которая генерит ХМЛ из запроса в определённом формате, этот xml поступает на html клиент, где этим хмл бандятся контроли, тоже разработанные на нашей фирме( очень много javascript ), потом для сохранения генерится общий ХМЛ, _>содержащий старую запись и измененную, забрасывается на сервер и при помощи той-же библиотеки меппируется на таблицы. Есть другой проект интернет, где по политическим соображениям не используют нашу замечательную библиотеку и там ты должен работать с теми-же таблицами, не ипользуя ХМЛ, и не очень хочется использовать dataset, а значит ты должен использовать БО как классы, вот и получаются различии. Правильно ли называть ХМЛ содержащий данные из базы данных БО или это уже DTO.
Это DTO. Всего лишь протокол обмена данными между сервером и клиентами. После прихода данных, из них уже формируются реальные бизнес-объекты. Таким образом, бизнес логика не зависит от клиента, и сервер приложений может работать с несколькими типов протоколов обмена не изменяя бизнес логику.
_>Согласен, что предназначение меппара, как раз и состоит в абстрагировании между БО и источником данных, но чем больше они похоже, тем проще DAL слой. Наверное различая появляются, только при довольно сложной логике и связях, но в большинстве они могут быть очень похоже, хотя всё зависит от нагрузки которую несёт БО. _>Предположим если меняется структура в базе данных, есть дилемма, поменять ДАЛ слой не трогая БО, или поменять БО, что более логичней, при етом ты должен сделать рефакторинг всего своего кода, где он применяется. Но знаете иногда, когда смотришь на код, где-то через годик, ты уже не помнишь почему у тебя структура БО и базы данных разная, а DAL так извращается что-бы наложить БО на базу данных.
Проясню. Полная независимость в принципе бывает только в сказке. Но! Все изменения связанные с хранилищем бывают двух видов:
1. Изменение связанные с изменениями в логике работы приложения. Тогда изменения(в большинстве случаев) идут вертикально по всем слоям.
2. Изменения связанные с улучшениями характеристик приложения. Вот тут, сколько не изменяй, любой нормальный базовед сразу скажет что где и как вяжется. Процесс нормализации-денормализации отнюдь не изменяют сами свойства системы. Они просто адаптируют хранилище для более эффективного использования. А реляционная модель достаточно архаична и ее связь с объектной моделью всегда легко понять.
_>Reflection это интересная тема, тут главное правильно поставить вопрос : в каких случаях её надо применять из-за производительности или в каких случаях её не надо применять,может не так чёрт страшен, как его рисуют.
Дело в том, что на фоне работы с базой данных падение производительности практически незаметны. Поэтому, это всего лишь вопрос удобства.
_>>>5. Есть много разных проектов, в которых есть разные вариации поиска, предположим таблицы Company. GZ>>Выдели метаданные, и сделай единый поисковый механизм который работает во всех случаях. _>А как эти слова преобразовать в код?
По всей структуре данных, строятся метаданные (свойства, ссылки и их типы). По этим метаданным выделяется строка запроса в базу данных.
Советую посмотреть (или лучше воспользоваться) готовыми ORM решениями типа Hibernate(NHibernate). Существует также огромное количество коммерческих решений (DataObjects, Versant).
GZ>>Запросы не должны быть разбросаны, а лежать в едином DAL слое. Иначе система будет практически открытой и придется писать парсер запросов для обеспечения безопасности. _>Что такое парсер запросов в этом контексте?
Насколько я понял твое сообщение, вы пересылаете SQL запрос с клиента. Так делать нельзя. Точнее можно, но при этом надо проверять саму SQL строку на момент того, что злоумышленники дописали ее чтобы получить чужие данные.
GZ>>Общение клиентов должно происходить через некоторый выделенные слой, в котором уже определяется кошерность клиента и достоен ли он его выполнить. Также на нем должна лежать задача уменьшения гранулярности запроса (возможно даже с помощью механизма запросов, а ля command паттерн). Но клиент ни в коем случае не должен знать не то, что про хранение, но и даже про бизнес-логику (неважно что это, некоторая сервисная модель, или объектная). _>Написано хорошо, как это преобразовать в код не совсем понимаю. _>Извините за не компетентность. Я не то что не умею писать классы, просто эти слова у меня не ассоциируются с чем-то реальным, абстракция.
Два подхода:
1. Сервер приложений глядит наверх некоторым интерфейсом с методами.
например(пишу примерно):
Таким образом, клиент даже не знает о существовании документа. Он видит только интерфейс предоставленный сервером приложений и DTO который получит как результат.
2. Запросы типа Command. На сервер передается коммандная строка (или набор командных объектов) , которые на сервере распарсиваются и преобразуются в команды выполняемые сервером приложений. Удобный (но достаточно сложный) механизм для работы сразу с пакетом команд в рамках одного запроса.
_>GZ>>Что касается данного случая, то тут может быть два варианта. Вариант 1 — в каждом webservice находится компоненты представляющие данный бизнес-объект, которые уже общаются с БД. Вариант 2 — webservice обращается в единый центр, на котором и находится вся логика для данного бизнес объекта. Второй вариант значительно лучше.
_>Это значит, что у меня есть отдельный общий проект, где хранятся все меппары или DAL объекты( как кому нравится ), в CompanyMapper будет функция GetCompanyForWebService(), GetCompanyForAdminSite(), GetCompanyForWebSite(), _>GetCompanyForBatch() .... _>Что-то вроде этого?
Немного не понял что ты имеешь ввиду. У сервиса должен быть процесс идентификации пользователя в котором он определяет какие объекты и бизнес логику имеет права задействовать тот, или иной пользователь. Система прав едина для всей системы. И в зависимости от прав конкретного пользователя, можно как задействовать процессы бизнес логики(см Principals если мы говорим о Net), и определенные бизнес объекты (которые действительно могут отсекаться на уровне Mappers или(и) вообще на уровне запросов к хранилищу).
Бизнес логика на сервере приложений работают только с одним видом бизнес объектов. А вот предоставление результатов(что касается первого твоего вопроса про DTO), можно делать на любом протоколе. Например, в примерном коде (тот что наверху) можно сделать так, что DTOAssembler будет создавать DTO по объектам в зависимости от типа клиента (точнее протокола по которому клиент работает). Или можно сделать для каждого вида клиента, свой Remoting Facade. Но бизнес логика при этом остается независимой от клиента. И о мапперах, клиент тем более не знает.
GZ>>Вообще, попробуй описать примерный механизм обеспечения транзакционности и согласованности данных который будет реализован. Тогда тебе многое станет более понятным.
_>Можно по подробней, что вы имеете ввиду?
Оптимистические пессимистические транзакции. Типы блокировок — жесткие, нежесткие. Всемя жизни бизнес транзакции (один запрос, несколько запросов). Механизм согласованности данных(Unit of work и Identity Map в терминах Фаулера).
За терминологией — Фаулер и например:здесьЗдесь перевод. Еще можешь это Re: Транзакции
Здравствуйте, IT, Вы писали:
IT>>>Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой.
MS>>Если бы все было так просто,
IT>Можно пример сложного?
MS>> думается создатели RDBMS давно уже бы предоставили свое собственное решение, а не выдавали наружу интерфейс наподобии ExecuteScalar ExecureReader и т.п.
IT>Для чего? Для UNIX, Windows, .NET, Java, C++? Или сразу для всего?
Универсальных инструментов не существует. Гоняться за ними — себе дороже. Это лирическое отступление. Насчет того, как бы развивались RDBMS, то Sql Server пощел бы по линейке .NET + Windows. Собственно, он уже это сделал. Oracle — по своей (Java). Для С++ нужно лишь сделать выбор (.NET или не .NET).
MS>>И еще. Маппер как раз для того и нужен, если структура сложная. При просто городить огород нечего.
IT>Mapper — это деталь имплементации, ничего более.
Утверждение настолько размыто, что ни согласиться, ни опровергнуть я не могу. Перефразируй данное высказывание, пожалуйста.
IT>Хелпер для DAL.
Если в общем случае — то не правильно. Если в контексте RFD, то возможно.
IT>Как ты думаешь, DAL вообще для чего нужен?
Лучше я скажу, в чем я не согласен в твоих высказываниях. Ты говоришь, что при правильной архитектуре все должно быть просто, и соответствие между таблицами в БД и сущностями должно быть взаимооднозначно. В простых системах это и так. Но есть такое понятие, как интеграция систем, где в работе участвуют разношерстные базы данных. Могут сюда даже складские программы входить со своими хранилищами (или часть данные по Web Services получать). Взаимооднозначное соответствие тут исчезает (сущности уже конструируются по агрегирующим состояниям и нет четкой границы). Вот здесь и может пригодиться маппер. Описывая в нем схему, что, как и откуда мы получаем в итоге готовенькую бизнес-сущность, которую можно сразу подавать к столу.
Твоя идея мне понятно. Но ты исходишь со стороны своего проекта. Твой проект покрывает не всю необходимую функциональность, для того, чтобы быть маппером. Как я уже описал, маппинг должен быть настраиваемым, а не производить простейшие вещи, то как маппинг из таблицы в сущность и обратно. Собственно, поэтому я сказал, что будь все так просто, придумали бы этот маппер еще до выхода .NET 1.0.
Здравствуйте, GlebZ, Вы писали:
GZ>В xml файле. Хранятся описания объектов — свойства, отношения наследования, ссылки и их отношения к БД. Тип в базе определяется либо по обязательным ссылкам (например обязательно должен быть связанные объект (класс потомок в объектой модели) в определенной таблице, либо по явному полю TypeID(в том числе и потому, что некоторые типы нельзя определить предыдущим способом).
Т.е. на начала процесса маппинга мы можем узнать какой бизнес объект конструировать и какие правила маппинга применять? Так? Т.е. усложнение самого процесса у нас только в этом месте, сам же маппинг может оставаться таким же простым. Т.е. мимо пока мимо кассы. Ещё варианты будут?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
GZ>>В xml файле. Хранятся описания объектов — свойства, отношения наследования, ссылки и их отношения к БД. Тип в базе определяется либо по обязательным ссылкам (например обязательно должен быть связанные объект (класс потомок в объектой модели) в определенной таблице, либо по явному полю TypeID(в том числе и потому, что некоторые типы нельзя определить предыдущим способом).
IT>Т.е. на начала процесса маппинга мы можем узнать какой бизнес объект конструировать и какие правила маппинга применять? Так?
Не понял. Вот вам void*, вот вам схема dbo, теперь хочу коммунизм? IT>Т.е. усложнение самого процесса у нас только в этом месте, сам же маппинг может оставаться таким же простым. Т.е. мимо пока мимо кассы. Ещё варианты будут?
Теперь я уже в полных непонятках. Что ты имеешь ввиду под усложнением процесса при том что маппинг является простым?
QET>>Я применял для такого случая спциальную коллкцию позволяющею получать данные страницами. IT>Не использовать подобный подход мы договорились в самом начале топика. Это намертво гвоздями прибивает твою бизнес сущность к источнику данных.
Но у меня всегда один тип данных, это база данных. В качестве хранилища файлы не используются.
Для доступа к данным у меня используется DAL. У каждой BEntity есть свой класc DAL`a. Задача при построении коллекции правильно задать критерии DAL`у ,а он уже сам генерирует SQL запрос.
IT wrote: > Здравствуйте, QwErTys, Вы писали: > > QET>Я применял для такого случая спциальную коллкцию позволяющею получать данные страницами. > > Не использовать подобный подход мы договорились в самом начале топика. Это намертво гвоздями прибивает твою бизнес сущность к источнику данных.
ну, не скажи. Да, он требует, чтобы было подключение (а, возможно, и
транзакция), с которого можно прочитать порцию данных. Но если коллекция
(базовая) инкапсулирует в себе такую логику, почему бы и нет. Так
например сделано в DevExpress Persistent Objects, есть там такая
коллекция XPCursor. Не хочу сказать, что это хорошо, но вариант
igor_fle wrote: >>>Есть вероятность того, что кто еще захочет использовать етот запрос и добавит что-то.И компания использующая вебсервис по ошибке получит больше информации чем ей хотят дать. > КП>ну, брат, это описание интерфейса и не более того. Надо слать 2 поля — > КП>один интерфейс, надо 5 — другой. > А можно примерчик
ну, как. Ты выставляешь наружу веб-сервис. Он по запросу возвращает
адрес и телефон компании. Допустим, кому-то надо больше, например,
название и факс. Тогда тебе ничего не остается, как выставить другой
веб-сервис, который возвращает эти данные, возможно в другом фомате и
т.д.: с SOAP не все так гладко как кажется. И нет тут дублирования: это
всего лишь разные, очень тонкие интерфейсы к той инфраструктуре, которую
ты наваял: бизнес-сущности, сервисный слой или что-то еще. Внутри они
могут иметь одну реализацию (например, механизма поиска), но наружу
будет вылетать то, что описано интерфейсом, и не более того.
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, igor_fle, Вы писали:
_>>Может кто-нибудь знает какой-нибудь пример, что-бы можно было скачать и посмотреть, _>>на "правильную" архитектуру, желательно на C#. GZ>А никто и не скажет, что такое "правильная" архитектура. Архитектура очень зависит от конкретного решения. Существует несколько шаблонов по которым строятся многозвенные и распределенные приложения. Все остальное творчество, или использование готовых решений.
Это понятно, что никто не скажет, что такое правильная архитектура,
но всегда полезно посмотреть на разные примеры "правильной" реализации для конкретного случая.
_>>Как быть в случаях, когда БО в разных проектах могут иметь разную форму. _>>Есть проект администрации (интранет), где всё идёт через XML. У нас есть своя библиотека, которая генерит ХМЛ из запроса в определённом формате, этот xml поступает на html клиент, где этим хмл бандятся контроли, тоже разработанные на нашей фирме( очень много javascript ), потом для сохранения генерится общий ХМЛ, _>>содержащий старую запись и измененную, забрасывается на сервер и при помощи той-же библиотеки меппируется на таблицы. Есть другой проект интернет, где по политическим соображениям не используют нашу замечательную библиотеку и там ты должен работать с теми-же таблицами, не ипользуя ХМЛ, и не очень хочется использовать dataset, а значит ты должен использовать БО как классы, вот и получаются различии. Правильно ли называть ХМЛ содержащий данные из базы данных БО или это уже DTO. GZ>Это DTO. Всего лишь протокол обмена данными между сервером и клиентами. После прихода данных, из них уже формируются реальные бизнес-объекты. Таким образом, бизнес логика не зависит от клиента, и сервер приложений может работать с несколькими типов протоколов обмена не изменяя бизнес логику.
Да, вот этого слоя у нас как раз и нету.
У нас DTO --> БД, при этом у нас нет заморочек с БО, бросил ХМЛ и никакой головной боли, хотя я и не говорю, что это правильно.
_>>>>5. Есть много разных проектов, в которых есть разные вариации поиска, предположим таблицы Company. GZ>>>Выдели метаданные, и сделай единый поисковый механизм который работает во всех случаях. _>>А как эти слова преобразовать в код? GZ>По всей структуре данных, строятся метаданные (свойства, ссылки и их типы). По этим метаданным выделяется строка запроса в базу данных. GZ>Советую посмотреть (или лучше воспользоваться) готовыми ORM решениями типа Hibernate(NHibernate). Существует также огромное количество коммерческих решений (DataObjects, Versant).
Что мне не нравится в подобных продуктах, что они навязывают свой стиль работы, мне больше нравятся продукты, похожие на РФД, он больше хелпер, чем чёрный ящик.
GZ>>>Запросы не должны быть разбросаны, а лежать в едином DAL слое. Иначе система будет практически открытой и придется писать парсер запросов для обеспечения безопасности. _>>Что такое парсер запросов в этом контексте? GZ>Насколько я понял твое сообщение, вы пересылаете SQL запрос с клиента. Так делать нельзя. Точнее можно, но при этом надо проверять саму SQL строку на момент того, что злоумышленники дописали ее чтобы получить чужие данные.
Да нет, я совсем не это имел ввиду, никто SQL запрос не передаёт.
Просто на данный момент у нас не существует слоя БО, есть разные проэкты с различными вариациями запросов к одним и тем-же таблицам, которые возвращают datareader или dataset. Вопрос стоит в том, стоит ли их всех объединить в один общий проект или нет. Если же их соеденить, то есть вероятность, что программист Вася решил, что запрос, кторый написал Вова для вебсервиса, ему тоже подходит, но вот только он добавит пару полей, при етом вебсервис который сделал Вова начнёт возвращать не множко больше данных, чем надо.
GZ>>>Общение клиентов должно происходить через некоторый выделенные слой, в котором уже определяется кошерность клиента и достоен ли он его выполнить. Также на нем должна лежать задача уменьшения гранулярности запроса (возможно даже с помощью механизма запросов, а ля command паттерн). Но клиент ни в коем случае не должен знать не то, что про хранение, но и даже про бизнес-логику (неважно что это, некоторая сервисная модель, или объектная). _>>Написано хорошо, как это преобразовать в код не совсем понимаю. _>>Извините за не компетентность. Я не то что не умею писать классы, просто эти слова у меня не ассоциируются с чем-то реальным, абстракция. GZ>Два подхода: GZ>1. Сервер приложений глядит наверх некоторым интерфейсом с методами. GZ>например(пишу примерно): GZ>
Всё красиво, вот только я не найду достаточно веских аргументов на работе, что бы всех убедить, зачем я строю сначала БО документы, а потом ими заполняю dataset, ведь можно сразу это сделать
GZ>Таким образом, клиент даже не знает о существовании документа. Он видит только интерфейс предоставленный сервером приложений и DTO который получит как результат. GZ>2. Запросы типа Command. На сервер передается коммандная строка (или набор командных объектов) , которые на сервере распарсиваются и преобразуются в команды выполняемые сервером приложений. Удобный (но достаточно сложный) механизм для работы сразу с пакетом команд в рамках одного запроса.
_>>GZ>>Что касается данного случая, то тут может быть два варианта. Вариант 1 — в каждом webservice находится компоненты представляющие данный бизнес-объект, которые уже общаются с БД. Вариант 2 — webservice обращается в единый центр, на котором и находится вся логика для данного бизнес объекта. Второй вариант значительно лучше.
_>>Это значит, что у меня есть отдельный общий проект, где хранятся все меппары или DAL объекты( как кому нравится ), в CompanyMapper будет функция GetCompanyForWebService(), GetCompanyForAdminSite(), GetCompanyForWebSite(), _>>GetCompanyForBatch() .... _>>Что-то вроде этого? GZ>Немного не понял что ты имеешь ввиду.
Твой пример снял этот вопрос.
Вот только получается, что в БО всегда закачивается вся информация, даже которую ты не планируешь использовать, что-бы потом каждый взял оттуда что ему надо, наверное для одного БО это не так существенно, но для коллекции может быть не много тяжеловато, а если запрос к нескольким таблицам( с JOIN ), то вообще убийственно.
Или я не правильно что-то понял.
Здравствуйте, Козьма Прутков, Вы писали:
КП>igor_fle wrote: >>>>Есть вероятность того, что кто еще захочет использовать етот запрос и добавит что-то.И компания использующая вебсервис по ошибке получит больше информации чем ей хотят дать. >> КП>ну, брат, это описание интерфейса и не более того. Надо слать 2 поля — >> КП>один интерфейс, надо 5 — другой. >> А можно примерчик
КП>ну, как. Ты выставляешь наружу веб-сервис. Он по запросу возвращает КП>адрес и телефон компании. Допустим, кому-то надо больше, например, КП>название и факс. Тогда тебе ничего не остается, как выставить другой КП>веб-сервис, который возвращает эти данные, возможно в другом фомате и КП>т.д.: с SOAP не все так гладко как кажется. И нет тут дублирования: это КП>всего лишь разные, очень тонкие интерфейсы к той инфраструктуре, которую КП>ты наваял: бизнес-сущности, сервисный слой или что-то еще. Внутри они КП>могут иметь одну реализацию (например, механизма поиска), но наружу КП>будет вылетать то, что описано интерфейсом, и не более того.
Реализации этих интерфейсов будут, обращатся к DAL слою который, мне вернёт БО Company, и заполнит им какой-то DTO необходимой информацией, при етом каждый берёт свою порцию информации, значит мне надо любой БО всегда заполнять всеми полями из таблицы, что мне очень нравится, но ведь для каждого случая надо разное количество информации, а если будет сложный запрос с коллекциями, то это убъёт производительность.
igor_fle wrote: > Здравствуйте, Козьма Прутков, Вы писали: > Реализации этих интерфейсов будут, обращатся к DAL слою который, мне вернёт БО Company, и заполнит им какой-то DTO необходимой информацией, при етом каждый берёт свою порцию информации, значит мне надо любой БО всегда заполнять всеми полями из таблицы, что мне очень нравится, но ведь для каждого случая надо разное количество информации, а если будет сложный запрос с коллекциями, то это убъёт производительность.
это уже из разряда "и на елку влезть и попу не поцарапать"
никто же не говорит о том, что по запросу на загрузку кастомера надо
тащить в память полбазы? Ну, загрузил часть реально нужных коллекций, а
остальное — lazy. Хотя, тут всем не угодишь, компромисс треба.
Если так важна производительность и на использовании этих средств она
неприемлемо провисает, то флаг в руки, грузи кусок данных другими путями
(это никто не запрещает) и передавай, деваться некуда. Менять данные так
не стоит, иначе получишь неизвестно-как-работающее месево.
Здравствуйте, Козьма Прутков, Вы писали:
КП>это уже из разряда "и на елку влезть и попу не поцарапать" КП>никто же не говорит о том, что по запросу на загрузку кастомера надо КП>тащить в память полбазы? Ну, загрузил часть реально нужных коллекций, а КП>остальное — lazy. Хотя, тут всем не угодишь, компромисс треба. КП>Если так важна производительность и на использовании этих средств она КП>неприемлемо провисает, то флаг в руки, грузи кусок данных другими путями КП>(это никто не запрещает) и передавай, деваться некуда. Менять данные так КП>не стоит, иначе получишь неизвестно-как-работающее месево.
Я не говорю, что-бы пол базы данных вытащить. Мы подходим к кастомизации DAL слоя, в зависимости от использования, для одной аппликации мне надо первых 20 полей таблицы, для второй мне другие нужны 20, а для 3 надо только одно поле, при сложных запросах комбинации возрастают, как в этих случаях правильно поступить?
igor_fle wrote: > Я не говорю, что-бы пол базы данных вытащить. Мы подходим к кастомизации DAL слоя, в зависимости от использования, для одной аппликации мне надо первых 20 полей таблицы, для второй мне другие нужны 20, а для 3 надо только одно поле, при сложных запросах комбинации возрастают, как в этих случаях правильно поступить?
ок. у тебя получается, что есть несколько приложений, шарящих одну базу
и больше никак не связанных? То есть у каждого свой набор БО, DAL и
т.д.? Интересно... Это уже про интеграцию тогда надоть почитать, а не
рассуждать о мепперах и организации DAL и иже с ним.
Здравствуйте, igor_fle, Вы писали:
_>Да, вот этого слоя у нас как раз и нету. _>У нас DTO --> БД, при этом у нас нет заморочек с БО, бросил ХМЛ и никакой головной боли, хотя я и не говорю, что это правильно.
Иногда это правильно. Особенно, когда на сервере практически нет бизнес-логики. Правда не в вышеописанном случае. В данном случае, выделенный Remote Facade и DTO обязательны.
GZ>>По всей структуре данных, строятся метаданные (свойства, ссылки и их типы). По этим метаданным выделяется строка запроса в базу данных. GZ>>Советую посмотреть (или лучше воспользоваться) готовыми ORM решениями типа Hibernate(NHibernate). Существует также огромное количество коммерческих решений (DataObjects, Versant). _>Что мне не нравится в подобных продуктах, что они навязывают свой стиль работы, мне больше нравятся продукты, похожие на РФД, он больше хелпер, чем чёрный ящик.
Потому что его функциональность достаточно невелика, поэтому кажется что он простой. Что касается стиля работы, то не забывай что это правильный стиль работы проверенный на реальных приложениях. Делать те же самые вещи самому, нужно угрохать достаточно много времени на постановку и продумывание + достаточные знания.
_>Да нет, я совсем не это имел ввиду, никто SQL запрос не передаёт. _>Просто на данный момент у нас не существует слоя БО, есть разные проэкты с различными вариациями запросов к одним и тем-же таблицам, которые возвращают datareader или dataset. Вопрос стоит в том, стоит ли их всех объединить в один общий проект или нет.
Соединить, и не плодить практически одинаковый код всегда стоит. Невыполнение этого условия платится повышенными затратами на разработку и сопровождение. Две — три реализации и синхронизация их работы очень неприятная вещь ведущая к большим затратам.
_>Если же их соеденить, то есть вероятность, что программист Вася решил, что запрос, кторый написал Вова для вебсервиса, ему тоже подходит, но вот только он добавит пару полей, при етом вебсервис который сделал Вова начнёт возвращать не множко больше данных, чем надо.
Могу предложить два способа. Первый способ, версионификация интерфейсов. Программист Вася написал клиента под интерфейс 1.1. Программисту Коле потом не хватило интерфейса 1.1 и он решил создать интерфейс 1.2 с измененными параметрами вызова. В результате, внутри сервера приложений, он изменил логику так, чтобы она работала как с интерфейсом 1.1, так и с интерфейсом 1.2.(обычно это легко проходит). И как бы, все остались при своем. В зависимости от заказанного интерфейса — бизнес-логика адаптируется под него. А чаще всего даже интерфейс 1.2 содержит(наследует) интерфейс 1.1 как свое подмножество.
Второй способ, введение как параметра функции — список полей которые хочется получить в том, или ином случае. Но я бы сказал это полумера которая была бы хороша в дополнение к первому способу. Чтобы плодить меньше версий. Ессно, если бизнес-объекты в данном виде используются только на сервере.
Ну и третий, это то что xml формату на фиг сдались лишние поля. Есть они или нет, клиенту по фигу. Ему важно лишь то, чтобы там были именно его поля.
_>Всё красиво, вот только я не найду достаточно веских аргументов на работе, что бы всех убедить, зачем я строю сначала БО документы, а потом ими заполняю dataset, ведь можно сразу это сделать
Можно. Любое решение должно быть достаточным. Аргументация может быть такой. Для сложных систем при реализации в схеме без явного разделения на слои, и в том числе на слой независимости от клиента, затраты на разработку новой функциональности и сопровождение растет экспотенциально. Но не забудь, что именно для сложных систем. Для простых существует принцип достаточности функционала.
_>Твой пример снял этот вопрос.
_>Вот только получается, что в БО всегда закачивается вся информация, даже которую ты не планируешь использовать, что-бы потом каждый взял оттуда что ему надо, наверное для одного БО это не так существенно, но для коллекции может быть не много тяжеловато, а если запрос к нескольким таблицам( с JOIN ), то вообще убийственно. _>Или я не правильно что-то понял.
Нет ты правильно понял, кроме слова убийственно. Давай поговорим о том, какая логика существует на сервере приложений. Если логика достаточно сложна и у нее прогнозировать какие свойства понадобятся в той, или иной процедуре невозможно, то тут выхода нет. Если говорить о затратах на БД, то чтение полностью строки, и чтение даже одного поля (не из индекса) по затратам в большинстве случаев вполне сопоставимы. Что касается JOIN, то правильно и хорошо построенный уровень мапперов сводит их влияние на достаточный уровень. Это уже вопрос оптимизации физического хранения.
Здравствуйте, Козьма Прутков, Вы писали:
КП>ну, не скажи. Да, он требует, чтобы было подключение (а, возможно, и транзакция), с которого можно прочитать порцию данных. Но если коллекция (базовая) инкапсулирует в себе такую логику, почему бы и нет. Так например сделано в DevExpress Persistent Objects, есть там такая коллекция XPCursor. Не хочу сказать, что это хорошо, но вариант
Я не против коллекции, я против того чтобы в таком виде она была частью объекта.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, GlebZ, Вы писали:
IT>>Т.е. на начала процесса маппинга мы можем узнать какой бизнес объект конструировать и какие правила маппинга применять? Так? GZ>Не понял. Вот вам void*, вот вам схема dbo, теперь хочу коммунизм?
Мда... void* — это мрачно. Ты хочешь сказать, что ты без понятия какой объект собираешься конструировать?
IT>>Т.е. усложнение самого процесса у нас только в этом месте, сам же маппинг может оставаться таким же простым. Т.е. мимо пока мимо кассы. Ещё варианты будут? GZ>Теперь я уже в полных непонятках. Что ты имеешь ввиду под усложнением процесса при том что маппинг является простым?
Усложняется процесс создания объекта, т.е. по данным из рекордсета ты должен определить какого типа объект создавать. Но сам мапинг после этого остаётся таким же.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Mika Soukhov, Вы писали:
IT>>>>Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой. MS>>>Если бы все было так просто, IT>>Можно пример сложного?
MS>Универсальных инструментов не существует....
[лирические отступления поскипаны]
Ты мне так и не дал пример сложного.
MS>>>И еще. Маппер как раз для того и нужен, если структура сложная. При просто городить огород нечего. IT>>Mapper — это деталь имплементации, ничего более. MS>Утверждение настолько размыто, что ни согласиться, ни опровергнуть я не могу. Перефразируй данное высказывание, пожалуйста. IT>>Хелпер для DAL. MS>Если в общем случае — то не правильно. Если в контексте RFD, то возможно.
При чём тут RFD? Мы говорим о маппинге в контексте топика. Автор топика может вообще будет делать маппинг ручками.
IT>>Как ты думаешь, DAL вообще для чего нужен?
MS>Лучше я скажу, в чем я не согласен в твоих высказываниях.
Опять ты уходишь от вопроса.
MS>Ты говоришь, что при правильной архитектуре все должно быть просто, и соответствие между таблицами в БД и сущностями должно быть взаимооднозначно.
Точно. При правильной архитектуре всё должно быть просто.
MS>В простых системах это и так.
Можешь дать нам определение "простой системы", а заодно и "сложной"?
MS>Но есть такое понятие, как интеграция систем, где в работе участвуют разношерстные базы данных. Могут сюда даже складские программы входить со своими хранилищами (или часть данные по Web Services получать). Взаимооднозначное соответствие тут исчезает (сущности уже конструируются по агрегирующим состояниям и нет четкой границы).
Если бы ты знал для чего нужен DAL, то и с интеграцией у тебя было бы меньше проблем
MS>Вот здесь и может пригодиться маппер. Описывая в нем схему, что, как и откуда мы получаем в итоге готовенькую бизнес-сущность, которую можно сразу подавать к столу.
У меня есть подозрение, что ты путаешь понятия мапинг и ORM. Это не совсем одно и тоже.
MS>Твоя идея мне понятно. Но ты исходишь со стороны своего проекта. Твой проект покрывает не всю необходимую функциональность, для того, чтобы быть маппером. Как я уже описал, маппинг должен быть настраиваемым, а не производить простейшие вещи, то как маппинг из таблицы в сущность и обратно. Собственно, поэтому я сказал, что будь все так просто, придумали бы этот маппер еще до выхода .NET 1.0.
Что значит "маппинг должен быть настраиваемым"? Настраиваемым кем, пользователем или программистом? Поясни пожалуйста.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Усложняется процесс создания объекта, т.е. по данным из рекордсета ты должен определить какого типа объект создавать. Но сам мапинг после этого остаётся таким же.
Не только по данным рекордсета, но и по метаданным и самому объектному запросу. У меня значительно все сложней. Маппер один и содержит в себе все метаданные. Существует механизм — некоторая поисковая машина. Поисковая машина работает по некоторому объектному запросу. Она берет этот объектный запрос, формирует из него SQL, создает объекты и заполняет их и их связи. Самое вкусное и интересное, система наследования. Дело в том, что родители могут лежать как в специальном классе-таблице, так и в таблице потомка. Объектный запрос и сам объект об этом даже не догадывается, все реализуется в самом едином маппере. И в объектном запросе, можно спокойно заказать некоторые абстрактные классы, которые вернуться инстанцирумыми потомками. SQL запросов при этом получается больше одного. И собственно как создание объекта, формирование и выполнение SQL запросов, заполнение объекта — это один сильно связанный механизм. Впрочем, в Фаулере, насколько я помню, мапперы также занимались именно этими вещами. Мне кажется, что тут у нас какая-то путаница в терминологии получилась. Поэтому я тебя и не понял. Может ты имел ввиду просто заполнение объекта?
Здравствуйте, GlebZ, Вы писали:
GZ>Мне кажется, что тут у нас какая-то путаница в терминологии получилась. Поэтому я тебя и не понял. Может ты имел ввиду просто заполнение объекта?
Да. Простое переливание из пустого в порожнее.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
MS>>Универсальных инструментов не существует....
IT>[лирические отступления поскипаны]
IT>Ты мне так и не дал пример сложного.
Мне кажется, что вообще не бывает простых систем. В каждой есть свои заморочки и сложности. А говорить, что у меня все просто и легко — пионерство
IT>>>Хелпер для DAL. MS>>Если в общем случае — то не правильно. Если в контексте RFD, то возможно.
IT>При чём тут RFD? Мы говорим о маппинге в контексте топика. Автор топика может вообще будет делать маппинг ручками.
Мне показалось, что ты рассматриваешь проблему автора топика в контексте своей системы (собственно, подходы, которые ты предалгал авторы, более или менее схожи с решением RFD).
IT>>>Как ты думаешь, DAL вообще для чего нужен?
MS>>Лучше я скажу, в чем я не согласен в твоих высказываниях.
IT>Опять ты уходишь от вопроса.
DAL — Data Access Layer. Уровень, через который система должна получать данные из источников. Данные в этм уровни должны преобразовываться в пригодные для программы вид, с целью отделения бизнес-логики и логики персистентности данных.
MS>>Но есть такое понятие, как интеграция систем, где в работе участвуют разношерстные базы данных. Могут сюда даже складские программы входить со своими хранилищами (или часть данные по Web Services получать). Взаимооднозначное соответствие тут исчезает (сущности уже конструируются по агрегирующим состояниям и нет четкой границы).
IT>Если бы ты знал для чего нужен DAL, то и с интеграцией у тебя было бы меньше проблем
Гуд. Давай тогда распиши свое видение, как бы ты здесь с маппером решил проблему (в принципе, я уже написал, как это делать — хотелось бы послушать твой вариант).
MS>>Вот здесь и может пригодиться маппер. Описывая в нем схему, что, как и откуда мы получаем в итоге готовенькую бизнес-сущность, которую можно сразу подавать к столу.
IT>У меня есть подозрение, что ты путаешь понятия мапинг и ORM.
Странно, про object-relation я и словом не обмолвился
MS>>Твоя идея мне понятно. Но ты исходишь со стороны своего проекта. Твой проект покрывает не всю необходимую функциональность, для того, чтобы быть маппером. Как я уже описал, маппинг должен быть настраиваемым, а не производить простейшие вещи, то как маппинг из таблицы в сущность и обратно. Собственно, поэтому я сказал, что будь все так просто, придумали бы этот маппер еще до выхода .NET 1.0.
IT>Что значит "маппинг должен быть настраиваемым"? Настраиваемым кем, пользователем или программистом? Поясни пожалуйста.
Я думаю, программистом (вряд ли это будет интересно конечному пользователю).
Здравствуйте, Mika Soukhov, Вы писали:
IT>>Ты мне так и не дал пример сложного.
MS>Мне кажется, что вообще не бывает простых систем. В каждой есть свои заморочки и сложности. А говорить, что у меня все просто и легко — пионерство
Среди законов Мерфи есть один очень мудрый закон — закон Мейера "Усложнять — просто, упрощать — сложно". Системы сложны не потому что они такие, а потому что мы их такими делаем, потому что нам так проще. Я сторонник именно такой точки зрения. И подтверждением моих слов в этом топике может служить то, что никто мне так и не дал примера когда бизнес модель должна принципиально отличатся от структуры БД. В основном только бла-бла-бла на тему как всё бывает в этой жизни не просто.
IT>>При чём тут RFD? Мы говорим о маппинге в контексте топика. Автор топика может вообще будет делать маппинг ручками.
MS>Мне показалось, что ты рассматриваешь проблему автора топика в контексте своей системы (собственно, подходы, которые ты предалгал авторы, более или менее схожи с решением RFD).
RFD — это просто удобный хелпер, рапер над ADO.NET + тупая перекладывалка из пустого в порожнее. Ни на какие принципиальные архитектурные решения RFD претендовать не собирается. Скажем так, именно это и является основным архитектурным решением в RFD — помогать, а не говорить как.
MS>DAL — Data Access Layer. Уровень, через который система должна получать данные из источников. Данные в этм уровни должны преобразовываться в пригодные для программы вид, с целью отделения бизнес-логики и логики персистентности данных.
Ключевое слово — изоляция. DAL изолирует приложение от источника данных путём перевода терминов базы данных в термины приложения и обратно.
IT>>Если бы ты знал для чего нужен DAL, то и с интеграцией у тебя было бы меньше проблем
MS>Гуд. Давай тогда распиши свое видение, как бы ты здесь с маппером решил проблему (в принципе, я уже написал, как это делать — хотелось бы послушать твой вариант).
Здесь у нас тоже самое ключевое слово — изоляция. Для этих вещей вводятся лэйеры (agents в терминах Microsoft), которые в принципе по своей природе ничем не отличаются от DAL. Та же самая изоляция приложения от источника данных, сервиса или что там у нас. При таком подходе нет необходимости тащить всё старьё из легаси кода в новое приложение, новый код можно удерживать чистым и простым.
IT>>У меня есть подозрение, что ты путаешь понятия мапинг и ORM. MS>Странно, про object-relation я и словом не обмолвился
Тогда я тем более не понимаю о каких супер сложностях ты говоришь.
IT>>Что значит "маппинг должен быть настраиваемым"? Настраиваемым кем, пользователем или программистом? Поясни пожалуйста.
MS>Я думаю, программистом (вряд ли это будет интересно конечному пользователю).
Тогда что такое "настраиваемым"? Настраиваемым посредством чего?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Козьма Прутков, Вы писали:
КП>igor_fle wrote: >> Я не говорю, что-бы пол базы данных вытащить. Мы подходим к кастомизации DAL слоя, в зависимости от использования, для одной аппликации мне надо первых 20 полей таблицы, для второй мне другие нужны 20, а для 3 надо только одно поле, при сложных запросах комбинации возрастают, как в этих случаях правильно поступить? КП>ок. у тебя получается, что есть несколько приложений, шарящих одну базу КП>и больше никак не связанных? То есть у каждого свой набор БО, DAL и КП>т.д.? Интересно... Это уже про интеграцию тогда надоть почитать, а не КП>рассуждать о мепперах и организации DAL и иже с ним.
Ну почему интеграция. Есть администрация, которая заносит, редактирует данные ит.д.
Есть сайт для юзеров, на нём можно увидеть всё, что делает администрация. Есть разные другие аппликации, которые согдают файлы в разных форматах, по интересующей юзера информации и занимаются рассылкой, есть разные batch, которые делают разную работу то подсчётам и обработке различной информации. Но все они работают с одной базой, значит и БО у всех должны быть одинаковые, и быть доступными для всех. Интеграция нужна если разные источники, базы ит.д.
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, igor_fle, Вы писали:
GZ>>>Советую посмотреть (или лучше воспользоваться) готовыми ORM решениями типа Hibernate(NHibernate). Существует также огромное количество коммерческих решений (DataObjects, Versant). _>>Что мне не нравится в подобных продуктах, что они навязывают свой стиль работы, мне больше нравятся продукты, похожие на РФД, он больше хелпер, чем чёрный ящик. GZ>Потому что его функциональность достаточно невелика, поэтому кажется что он простой. Что касается стиля работы, то не забывай что это правильный стиль работы проверенный на реальных приложениях. Делать те же самые вещи самому, нужно угрохать достаточно много времени на постановку и продумывание + достаточные знания.
Я не очень сильно вникал, но по моему, у всех етих продуктов, БО генерятся по таблицам. Т.е они максимально похоже на саму таблицу.
_>>Если же их соеденить, то есть вероятность, что программист Вася решил, что запрос, кторый написал Вова для вебсервиса, ему тоже подходит, но вот только он добавит пару полей, при етом вебсервис который сделал Вова начнёт возвращать не множко больше данных, чем надо. GZ>Могу предложить два способа. Первый способ, версионификация интерфейсов. Программист Вася написал клиента под интерфейс 1.1. Программисту Коле потом не хватило интерфейса 1.1 и он решил создать интерфейс 1.2 с измененными параметрами вызова. В результате, внутри сервера приложений, он изменил логику так, чтобы она работала как с интерфейсом 1.1, так и с интерфейсом 1.2.(обычно это легко проходит). И как бы, все остались при своем. В зависимости от заказанного интерфейса — бизнес-логика адаптируется под него. А чаще всего даже интерфейс 1.2 содержит(наследует) интерфейс 1.1 как свое подмножество. GZ>Второй способ, введение как параметра функции — список полей которые хочется получить в том, или ином случае. Но я бы сказал это полумера которая была бы хороша в дополнение к первому способу. Чтобы плодить меньше версий. Ессно, если бизнес-объекты в данном виде используются только на сервере.
Иногда дополнительное поле тянет за собой и таблицу, так что одним списком полей неотделаешся.
Но смысл понял.
GZ>Ну и третий, это то что xml формату на фиг сдались лишние поля. Есть они или нет, клиенту по фигу. Ему важно лишь то, чтобы там были именно его поля.
Не совсем так. То что можно видеть одному юзеру, то нельзя другому.
_>>Всё красиво, вот только я не найду достаточно веских аргументов на работе, что бы всех убедить, зачем я строю сначала БО документы, а потом ими заполняю dataset, ведь можно сразу это сделать GZ>Можно. Любое решение должно быть достаточным. Аргументация может быть такой. Для сложных систем при реализации в схеме без явного разделения на слои, и в том числе на слой независимости от клиента, затраты на разработку новой функциональности и сопровождение растет экспотенциально. Но не забудь, что именно для сложных систем. Для простых существует принцип достаточности функционала.
Здравствуйте, IT, Вы писали:
MS>>Мне кажется, что вообще не бывает простых систем. В каждой есть свои заморочки и сложности. А говорить, что у меня все просто и легко — пионерство
IT> Среди законов Мерфи есть один очень мудрый закон — закон Мейера "Усложнять — просто, упрощать — сложно".
Не только Мерфи принадлежит такая мысль. Ну да не об этом.
IT>Системы сложны не потому что они такие, а потому что мы их такими делаем, потому что нам так проще. Я сторонник именно такой точки зрения.
Понял твою позицию. Только ты подходишь со стороны разработчика. Я же стараюсь решать проблемы со стороны бизнеса. Поэтому я считаю, что системы бывают легко реализуемые и сложно реализуемые. Измерить сложность можно по человеко-месяцам (или сразу в деньгах).
IT>Здесь у нас тоже самое ключевое слово — изоляция. Для этих вещей вводятся лэйеры (agents в терминах Microsoft), которые в принципе по своей природе ничем не отличаются от DAL. Та же самая изоляция приложения от источника данных, сервиса или что там у нас. При таком подходе нет необходимости тащить всё старьё из легаси кода в новое приложение, новый код можно удерживать чистым и простым.
Ok. Только я предлагаю делать это в маппере.
IT>>>Что значит "маппинг должен быть настраиваемым"? Настраиваемым кем, пользователем или программистом? Поясни пожалуйста.
MS>>Я думаю, программистом (вряд ли это будет интересно конечному пользователю).
IT>Тогда что такое "настраиваемым"? Настраиваемым посредством чего?
В идеале — через конфигурационный файл. В нем через некую метаинфомарцию мы указываем, откуда и как брать. Затем как произвести трансформацию в наш формат, и заполнить нашу бизнес-сущность.
Не в идеале — через Data Access Components, расширающие наш маппер.
IT>И подтверждением моих слов в этом топике может служить то, что никто мне так и не дал примера когда бизнес модель должна принципиально отличатся от структуры БД. В основном только бла-бла-бла на тему как всё бывает в этой жизни не просто.
Приводу во второй и последний раз ситуацию (больше приводить нет желания и времени). Есть ситуация с интеграцией программы в уже существующую и успешно функционирующую среду. Среда работает с сущностями Товар и Заказчик. Программа — Товар (+ новое поле поставщики), Заказчик (+ новое поле поставщики), Поставщик. В целях экономии места и производительности (да и ради здравого смысла) база данных интегрируемого приложения содержит лишь информацию о поставщиках, и связи между поставщиками и другими сущностями. Все, уже не соответствие.
Переделывать базу данных под новое приложение — полный абсурд. Другие программы не работают с типом Поставщик — им этого и не нужно.
Перезаливать постоянно данные из основного хранилища в хранилище приложения тоже не имеет смысла. Проблемы с синхронизацией + дубляжом информации очень, очень не приемлимо для хорошего качества ПО.
Мне кажется, что ты не улавливаешь сути базы данных. База данных — это хранилище (+ на него постоянно нагружают логику АПП). Но никак это не хранилище для данных, приспособленных под мапперы. Здесь должны храниться данных в таком виде и формате, в котором быстрее с ними работать. Как я уже говорил, если бы это было так, то сделали эти мапперы лет эдак 40 назад, и не было бы всяких там NHibernate, ORM.NET, RFD и т.п.
Здравствуйте, Mika Soukhov, Вы писали:
IT>> Среди законов Мерфи есть один очень мудрый закон — закон Мейера "Усложнять — просто, упрощать — сложно".
MS>Не только Мерфи принадлежит такая мысль. Ну да не об этом.
Простите, Михаил, я вас забыл упомянуть
IT>>Системы сложны не потому что они такие, а потому что мы их такими делаем, потому что нам так проще. Я сторонник именно такой точки зрения.
MS>Понял твою позицию. Только ты подходишь со стороны разработчика. Я же стараюсь решать проблемы со стороны бизнеса.
Ууу... как всё запущено
MS>Поэтому я считаю, что системы бывают легко реализуемые и сложно реализуемые. Измерить сложность можно по человеко-месяцам (или сразу в деньгах).
Правильно. Бывают. Ещё раз закон Мейера перечитай. Может быть ты хочешь сказать, что системы бывают большие и маленькие? Согласен. Но сложность, ещё раз повторяю, в наших головах. И некоторым головам, действительно, порой удаётся из самого простого сделать суперсложное. А уж измерение сложности в деньгах так это вообще смешно. Закажи 10 веб-страничек IBM'овскуму консалтингу и ты узнаешь что такое настоящая сложность Обещаю тебе, ты получишь настоящие солюшены с большой буквы СЫ
IT>>Здесь у нас тоже самое ключевое слово — изоляция. Для этих вещей вводятся лэйеры (agents в терминах Microsoft), которые в принципе по своей природе ничем не отличаются от DAL. Та же самая изоляция приложения от источника данных, сервиса или что там у нас. При таком подходе нет необходимости тащить всё старьё из легаси кода в новое приложение, новый код можно удерживать чистым и простым.
MS>Ok. Только я предлагаю делать это в маппере.
Да всё равно где. Маппер — это тул, хелпер, что бы ручками не перекладывать. Но тот же маппинг можно спокойно делать в рукопашную, только это больше похоже на валить лобзиком Беловежскую Пущу, но можно. Может ты всё таки имеешь ввиду ORM систему?
IT>>Тогда что такое "настраиваемым"? Настраиваемым посредством чего?
MS>В идеале — через конфигурационный файл. В нем через некую метаинфомарцию мы указываем, откуда и как брать. Затем как произвести трансформацию в наш формат, и заполнить нашу бизнес-сущность.
Конфиги — это конечно хорошо, только работы они добавляют раза в два. В RFD для них поддержка есть, сделал как-то по просьбе бывших джавистов. Но сколько я не пытался не приживаются они. Сложно всё. Реализация на атрибутах на порядок проще.
MS>Не в идеале — через Data Access Components, расширающие наш маппер.
Всё таки я больше и больше склоняюсь к тому, что то о чём ты говоришь уже давно перерасло маппер.
IT>>И подтверждением моих слов в этом топике может служить то, что никто мне так и не дал примера когда бизнес модель должна принципиально отличатся от структуры БД. В основном только бла-бла-бла на тему как всё бывает в этой жизни не просто.
MS>Приводу во второй и последний раз ситуацию (больше приводить нет желания и времени). Есть ситуация с интеграцией программы в уже существующую и успешно функционирующую среду. Среда работает с сущностями Товар и Заказчик. Программа — Товар (+ новое поле поставщики), Заказчик (+ новое поле поставщики), Поставщик. В целях экономии места и производительности (да и ради здравого смысла) база данных интегрируемого приложения содержит лишь информацию о поставщиках, и связи между поставщиками и другими сущностями. Все, уже не соответствие.
MS>Переделывать базу данных под новое приложение — полный абсурд. Другие программы не работают с типом Поставщик — им этого и не нужно.
MS>Перезаливать постоянно данные из основного хранилища в хранилище приложения тоже не имеет смысла. Проблемы с синхронизацией + дубляжом информации очень, очень не приемлимо для хорошего качества ПО.
MS>Мне кажется, что ты не улавливаешь сути базы данных.
Да это понятно, куда нам деревенским. Тем более что я и сейчас уловить не могу... проблема где? В чём проблема? В том что у тебя три таблицы лежат в двух разных базах данных? Ну и что здесь делает сложным маппинг? Или твой маппер не умеет одновременно коннектится сразу к двум БД? Тогда да... В чём проблема, я правда не понял.
MS>База данных — это хранилище (+ на него постоянно нагружают логику АПП).
Вот за это надо сразу к стенке.
MS>Но никак это не хранилище для данных, приспособленных под мапперы. Здесь должны храниться данных в таком виде и формате, в котором быстрее с ними работать.
Блин. Я наверное и правда тупею на чужбине... И как это отражается на сложности маппинга? Вот хранение данных в двух базах — это да, замедлит работу и усложнит реализацию доступа к данным, но при чём тут быстродействие и маппинг? Быстродействие — это ключи и индексы, маппинг — это построение соответствий между полями таблиц и полями и свойствами классов. В чём противоречие?
MS>Как я уже говорил, если бы это было так, то сделали эти мапперы лет эдак 40 назад, и не было бы всяких там NHibernate, ORM.NET, RFD и т.п.
Для маппинга нужно откуда-то брать метадату. 40 лет назад не было ещё ни рефлекшина, ни даже XML'я. Да и сам по себе маппинг был не актуален. Он делался с помощью простого кастинга void* к типизированному указателю. Я такое ещё лет 10-12 назад умел. А теперь ты фиг чего откастишь, надо перекладывать из резалтсета в поля класса. Вот чтобы эту вновь образовавшуюся дырку заткнуть и придумали маппинг.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[17]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
17.05.05 05:06
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>Два подхода: GZ>1. Сервер приложений глядит наверх некоторым интерфейсом с методами. GZ>например(пишу примерно): GZ>
Есть маленький вопрос по этому примеру. Если предположим надо вернуть часть данных
из БО document, то где должна сидеть логика, что дать, а что нет. В DTOAssembler ?
igor_fle wrote: > Здравствуйте, Козьма Прутков, Вы писали: > > КП>igor_fle wrote: > >>>Я не говорю, что-бы пол базы данных вытащить. Мы подходим к кастомизации DAL слоя, в зависимости от использования, для одной аппликации мне надо первых 20 полей таблицы, для второй мне другие нужны 20, а для 3 надо только одно поле, при сложных запросах комбинации возрастают, как в этих случаях правильно поступить? > > КП>ок. у тебя получается, что есть несколько приложений, шарящих одну базу > КП>и больше никак не связанных? То есть у каждого свой набор БО, DAL и > КП>т.д.? Интересно... Это уже про интеграцию тогда надоть почитать, а не > КП>рассуждать о мепперах и организации DAL и иже с ним. > > Ну почему интеграция. Есть администрация, которая заносит, редактирует данные ит.д. > Есть сайт для юзеров, на нём можно увидеть всё, что делает администрация. Есть разные другие аппликации, которые согдают файлы в разных форматах, по интересующей юзера информации и занимаются рассылкой, есть разные batch, которые делают разную работу то подсчётам и обработке различной информации. Но все они работают с одной базой, значит и БО у всех должны быть одинаковые, и быть доступными для всех. Интеграция нужна если разные источники, базы ит.д.
ну, на самом деле, паттерн интеграции Shared Database никто не отменял
Да, в данном случае, я абсолютно согласен с тем, что эти приложения
должны иметь один набор бизнес-сущностей, иначе можно погрязнуть в
дублировании. Читаем у Фаулера:
Often you'll run into situations where different use cases work best
with different varieties of laziness. Some need one subset of the object
graph; others need another subset. For maximum efficiency you want to
load the right subgraph for the right use case.
The way to deal with this is to have separate database interaction
objects for the different use cases. Thus, if you use Data Mapper (165),
you may have two order mapper objects: one that loads the line items
immediately and one that loads them lazily. The application code chooses
the appropriate mapper depending on the use case. A variation on this is
to have the same basic loader object but defer to a strategy object to
decide the loading pattern. This is a bit more sophisticated, but it can
be a better way to factor behavior.
Здравствуйте, IT, Вы писали:
IT>>> Среди законов Мерфи есть один очень мудрый закон — закон Мейера "Усложнять — просто, упрощать — сложно".
MS>>Не только Мерфи принадлежит такая мысль. Ну да не об этом.
IT>Простите, Михаил, я вас забыл упомянуть
Забавно Вообще, посмотри в дополнение к высказываниям Эйнштейна (например, "Делай как можно проще, но не проще, чем нужно"). Много чего можно узнать. Например, прийдти к выводу, что высказывания популярных людей — есть аккумированная мудрость некоторых народов. А вообще фраза с подобным смыслом принадлежала еще какому-то русскому писателю. К сожалению, не помню его имя. И точно это был не Мерфи, так как тогда учился я в классе пятом (если еще не раньше).
На маппинг и прочее отвечу позднее (хотя явно идет процесс "толочь воду в ступе").
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Козьма Прутков, Вы писали:
КП>>ну, не скажи. Да, он требует, чтобы было подключение (а, возможно, и транзакция), с которого можно прочитать порцию данных. Но если коллекция (базовая) инкапсулирует в себе такую логику, почему бы и нет. Так например сделано в DevExpress Persistent Objects, есть там такая коллекция XPCursor. Не хочу сказать, что это хорошо, но вариант
IT>Я не против коллекции, я против того чтобы в таком виде она была частью объекта.
Частью объекта может быть не сама коллекция, а некий фасад, который выглядит как коллекция. Как уже не раз обсуждалось, коллекции подчиненных связей лучше хранить/управлять отдельно от объектов. А самим объектам предоставлять сервисы доступа, которые объект может рассматривать как коллекции.
Например (схематично):
public class Product {
int _key;
private IDetailCollection _versions;
public Product(int key) {
_key = key;
_versions = MyDb.Links.Product_Versions.GetDetail(_key);
}
}
Здравствуйте, igor_fle, Вы писали:
_>Если обобщить, то бизнес сущности должны максимально быть похоже на свой источник данных.
Зайди с другой стороны.
ПО — суть лишь модель происходящего. Ты выбираешь эту модель, уточняешь свои абстракции и т.д. Разумно ли в рамках одной системы городить несколько моделей, дублирующих друг-друга? И клиентские объекты, и серверные и их представление в БД должны быть максимально близки к модели приложения, тогда получишь меньше ненужных преобразований м/у моделями.
_>Никаким образом не должны пересекаться с DAL, не должны знать о своём происхождении.
Это полезно во многих случаях. Не знать о своем происхождении — очень удобная фича, порой развязывает руки и способствует повторному использованию.
_>Бизнес сущности должны быть самодостаточными, т.е недопустимо чтобы за какой-то порцией данных было обращение к DAL, интересно а как-же с lozy load?
Есть такой паттерн — прокси.
_>В моём случае получается, что функцию расчёта надо вынести из БО Company и перенести её в CompanyManager, который имеет отношение бизнес логике.
Речь идет о самодостаточности. От нее отталкивайся и принимай решения. Хотя, неплохим аргументом так же является некое единообразие элементов твоей модели. При прочих равных условиях идентичная организация элементов модели способствует дальнейшему сопровождению/изменению.
_>Правильно ли расматривать БО, как плоский объект, который должен иметь самую примитивную логику. _>Каждый БО должен иметь объект БЛ который оперирует им (CompanyManager <---> Company)
Им могут оперировать несколько БЛ. Легче делить на сервисы. В принципе, ты можешь наделить некий выделенный БЛ объект ф-ю CRUD. Тогда сервисы будут представлять из себя объекты более высокого уровня. Я в своей модели вынес интерфейс IObjectStore для этих нужд (CRUD). В "простых" случаях (таких большинство) его реализует БЛ, который суть сервис для задач, связанных с БО (обычно с БО, который сам находится на вершине иерархии подчинения/владения)
_>Если у меня запрос состоит из нескольких таблиц, то как надо загружать БО? На каждую таблицу по БО или БО общий на запрос?
Желательно на каждый БО по таблице.
От чего отталкиваемся? База данных дана или мы ее разрабатываем? Если второе, то и карты в руки. При использовании объектных технологих надо макимально заточить БД на задачи персистенции объектов. Все.
Здравствуйте, Козьма Прутков, Вы писали:
КП>IT wrote: >> Весьма распространённое и в то же время ошибочное мнение, которым обычно прикрывается либо кривой дизайн базы либо объектной модели. В процессе разработки модель данных и структура базы могу и должны соответствовать друг другу. Вот ты мне можешь привести живой хороший пример, когда различия в структуре базы и модели заложены в дизайне? Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой. КП>ну например не будешь же ты связь БД много-на-много через промежуточную КП>сущность отображать отдельным объектом? Не будешь.
Буду, и отображаю
ManyToManyLink у нас называется, объект заточен на предоставление сервисов выборки связанных объектов.
КП>Допустим, для оптимизации каких-нибудь отчетов ты денормализуешь схему, КП>что, и модель так же денормализовывать? Нет. Естественно, они будут КП>похожи, но не всегда один в один: представь, что ты уже имеешь чужую КП>базу и тебе надо на ней что-то построить. Я не думаю, что твоя модель КП>предметной области будет идентична наследию, ей богу
"Чужая база" — это действительно совершенно отдельный вопрос. Замечание IT насчет дыр и замазываний как раз лучше всего относится к такому случаю. Универсального решения этой проблемы нет. Решение надо вырабатывать на месте с учетом большого количества параметров (в общем случае).
Здравствуйте, vdimas, Вы писали:
IT>>Я не против коллекции, я против того чтобы в таком виде она была частью объекта.
V>Частью объекта может быть не сама коллекция, а некий фасад, который выглядит как коллекция. Как уже не раз обсуждалось, коллекции подчиненных связей лучше хранить/управлять отдельно от объектов. А самим объектам предоставлять сервисы доступа, которые объект может рассматривать как коллекции.
А кто будет инициализировать этот фасад? К тому же надо будет на каждый тип коллекции создавать интерфейс :xz;
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
vdimas wrote: > КП>IT wrote: >>>Весьма распространённое и в то же время ошибочное мнение, которым обычно прикрывается либо кривой дизайн базы либо объектной модели. В процессе разработки модель данных и структура базы могу и должны соответствовать друг другу. Вот ты мне можешь привести живой хороший пример, когда различия в структуре базы и модели заложены в дизайне? Примеров замазывания дыр полно, но мне бы хотелось увидеть именно правильное решение, не by кривой design, а by прямой. > КП>ну например не будешь же ты связь БД много-на-много через промежуточную > КП>сущность отображать отдельным объектом? Не будешь. > Буду, и отображаю > ManyToManyLink у нас называется, объект заточен на предоставление сервисов выборки связанных объектов.
Ну, это вопрос реализации. Я бы, например, завел симметричные коллекции
у связанных объектов, аналогично как для связей 1:N частенько заводится
с одной стороны коллекция, а с другой — свойство (типа
заказ-коллекция_пунктов, пункт-заказ). Вот внутри — ради бога, пользуйся
чем угодно. Но в домене это понятие отсутствует, посему не надое его
навязывать.
> КП>Допустим, для оптимизации каких-нибудь отчетов ты денормализуешь схему, > КП>что, и модель так же денормализовывать? Нет. Естественно, они будут > КП>похожи, но не всегда один в один: представь, что ты уже имеешь чужую > КП>базу и тебе надо на ней что-то построить. Я не думаю, что твоя модель > КП>предметной области будет идентична наследию, ей богу > > "Чужая база" — это действительно совершенно отдельный вопрос. Замечание IT насчет дыр и замазываний как раз лучше всего относится к такому случаю. Универсального решения этой проблемы нет. Решение надо вырабатывать на месте с учетом большого количества параметров (в общем случае).
С тем, что это отдельный вопрос я нисколько не спорю. Надеюсь, с
утверждением о денормализации то ты согласен? Но по большому счету, если
уж тебе и надо вырасти на чужой базе, то скорее всего ты сделаешь
удобную себе модель, нежели создашь полное отображение того, что есть.
База данных — это средство хранения и получения информации. То, как ты
представляешь ее для работы приложения ну никак не обязано
соответствовать тому, как все это хранится. Типичный пример. Пусть есть
пара сущностей, между которыми есть логическая связь 1:N, но она
инициализируется крайне редко. Чтобы не расходовать место (в том числе в
индексах) вводится промежуточная сущность — связь (типа как для N:N,
только с некоторыми ограничениями, чтобы она работала только как 1:N).
Что, для нее тоже сущность заводить? Так это не соответствует модели
предметной области! Там не коллекция вторых сущностей, тем более не
странный ManyToManyLink, а именно ссылка одной сущности на другую. А как
это в БД — дело десятое.
Я могу согласиться в отношении соответствия с вами только в одном: на
начальных этапах разработки модель данных соответствует модели
предметной области, так уж процесс устроен, что сначала анализируется
домен (с его моделированием, результаты которого вырастают в модель
предметной области), а потом проектируется база. Но никак не наоборот.
Далее, по мере детализации проектирования, разработки и тем более
поддержки и развития эти модели расходятся.
Здравствуйте, Козьма Прутков, Вы писали:
КП>Я могу согласиться в отношении соответствия с вами только в одном: на КП>начальных этапах разработки модель данных соответствует модели КП>предметной области, так уж процесс устроен, что сначала анализируется КП>домен (с его моделированием, результаты которого вырастают в модель КП>предметной области), а потом проектируется база. Но никак не наоборот. КП>Далее, по мере детализации проектирования, разработки и тем более КП>поддержки и развития эти модели расходятся.
Ни в коем случае не расходятся, а уточняются детали имплементации. Модели не могут расходится. Если у нас в БД выделена отдельная таблица под хранения связей, а в коде нет соответствующей сущности, то ведь это не означает, что в приведенном тобой примере при изменении данных целевых сущностей (ссылка на 1 со стороны N) содержимое таблицы связей остается неизменным. Оно должно как-то синхронизироваться, либо через триггера, либо через открытие доступа к целевым таблицам посредством лишь SP. Т.е. налицо тонкости реализации, не более того. (точно так же, как данные одной сущности могут хранится в нескольких таблицах при отображении коллекции некой иерархии по наследованию... мне не нравится подобное отображение, но встречается регулярно)
Кстати, в моей модели у нас как отдельная сущность выступает и MasterDetailLink тоже
И предназначен именно для решения такого вопроса, как отделение связей м/у сущностями от способа представления этих связей в персинстентном блоке. Твой пример весьма удачен для моей модели.
Более того, я "агрессивно" занимаюсь кешированием данных, подобное отделение связей в отдельные сущности открывает мне широкий простор для повышения эффективности кеширования без значительных трудозатрат.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, vdimas, Вы писали:
IT>>>Я не против коллекции, я против того чтобы в таком виде она была частью объекта.
V>>Частью объекта может быть не сама коллекция, а некий фасад, который выглядит как коллекция. Как уже не раз обсуждалось, коллекции подчиненных связей лучше хранить/управлять отдельно от объектов. А самим объектам предоставлять сервисы доступа, которые объект может рассматривать как коллекции.
IT>А кто будет инициализировать этот фасад?
Этот фасад инициаизирует внешний клиент связи. Он ее запрашивает у провайдера. Например, у меня так:
И что характерно, зачастую объект со стороны Master не запрашивает свой detail. Чаще всего его запрашивают адаптеры с GUI или адаптеры-деревья на стороне сервера.
Если же требуется выполнять какие-либо алгоритмы в самом БО со стороны Master, то ради бога — он запросит Detail для выбранной связи. Если эта штука не одноразового использования, я инкапсулирую в св-ва, т.е. проблем нет.
(по числу строк кода это не больше чем использование всяких Nhibernate или SPO, или еще каких, и гораздо проще, чем самому обслуживать подобные коллекции, где, кстати, неизбежно возникнет дублирование ссылок, или того хуже — объектов со стороны detail)
IT>К тому же надо будет на каждый тип коллекции создавать интерфейс :xz;
Пока юзаю обощенный интерфейс, потом перейду на генерики.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, GlebZ, Вы писали:
GZ>>Мне кажется, что тут у нас какая-то путаница в терминологии получилась. Поэтому я тебя и не понял. Может ты имел ввиду просто заполнение объекта?
IT>Да. Простое переливание из пустого в порожнее.
Все в мире относительно Если говорить о заполнении конкретного объекта, то да. А вот если говорить уже о коллекции, то не обязательно. Коллекция может состоять из инстансов объектов разных типов объединенными одним классом предка.
Или система из 1С(где-то Serginio1 описывал). Там строки хранятся по разбитые частям.
А>Есть маленький вопрос по этому примеру. Если предположим надо вернуть часть данных А>из БО document, то где должна сидеть логика, что дать, а что нет. В DTOAssembler ?
Тут вопрос в том, зачем это нужно. Если это логика безопасности, то это отдельный механизм, который обычно реализуется как на уровне базы (вьюхи, хранимки, импесонализация (хотя и не очень приятный процесс), или просто добавление условий на select), так и на уровне бизнес логики (проверка могу ли я сохранить данный тип объекта). Однако я не советую делать безопасность на поля. Лучше разделить объекты.
Второй вопрос, если это нужно чтобы уменьшить оверхед трафика. В данном случае советую просто делать при переносе бизнес-объекта в формат DTO.
Делать полузаполненный бизнес-объект (и вообще трогать права суперпользователя) не стоит. Никогда не разберешься что этот объект содержит, и какие из полей понадобятся. Что касается суперпользователя, то во многих случаях нужно иметь информацию об объектах, на которые прав у текущего пользователя нет. Особенно в агрегирующих отчетах.
Здравствуйте, igor_fle, Вы писали:
_>Я не очень сильно вникал, но по моему, у всех етих продуктов, БО генерятся по таблицам. Т.е они максимально похоже на саму таблицу.
Нет. Это только один из способов. Бывает и класс-таблица. Иногда, если объект слишком большой, то его надо разбивать на разные таблицы (в силу ограничений размера на строку в БД), хотя такого я не слышал. Бывает система, когда строка текста разбивается на несколько строк (как это в 1С).
GZ>>Ну и третий, это то что xml формату на фиг сдались лишние поля. Есть они или нет, клиенту по фигу. Ему важно лишь то, чтобы там были именно его поля.
_>Не совсем так. То что можно видеть одному юзеру, то нельзя другому.
Это задача уже другого плана. Это задача безопасности, что есть отдельный механизм. Только что написал.Re[18]: Несколько вопросов по Меппарам.
_>Что это за принцип достаточности функционала.
В разных источниках описывается по разному. Просто нужно делать только тот функционал, который достаточен для выполнения задачи на данной итерации разработки.
Здравствуйте, GlebZ, Вы писали:
А>>Есть маленький вопрос по этому примеру. Если предположим надо вернуть часть данных А>>из БО document, то где должна сидеть логика, что дать, а что нет. В DTOAssembler ? GZ>Тут вопрос в том, зачем это нужно. Если это логика безопасности, то это отдельный механизм, который обычно реализуется как на уровне базы (вьюхи, хранимки, импесонализация (хотя и не очень приятный процесс), или просто добавление условий на select), так и на уровне бизнес логики (проверка могу ли я сохранить данный тип объекта). Однако я не советую делать безопасность на поля. Лучше разделить объекты. GZ>Второй вопрос, если это нужно чтобы уменьшить оверхед трафика. В данном случае советую просто делать при переносе бизнес-объекта в формат DTO.
GZ>Делать полузаполненный бизнес-объект (и вообще трогать права суперпользователя) не стоит. Никогда не разберешься что этот объект содержит, и какие из полей понадобятся. Что касается суперпользователя, то во многих случаях нужно иметь информацию об объектах, на которые прав у текущего пользователя нет. Особенно в агрегирующих отчетах.
GZ>С уважением, Gleb.
Дело не безопасности, а желании клиента.
Каждый клиент заинтересован в какой-то определенной информации.
Вот и получается, что одному надо все поля БО, а кому-то всего 2 поля.
Сейчас у меня есть следующая ситуация : есть БО Company, которая агрегирует CompanyFinancialDetailes. Мой меппер возвращает заполненный БО Company и CompanyFinancialDetailes(отношения у них 1-1). Есть юзер который хочет пару полей из БО Company и адреса. Адреса хранятся в отдельной таблице, значит надо составлять новый запрос под клиента с адресами. Т.е вариаций много, но как всё построить, что-бы не было неразберихи, какая функция меппара что подгружает.
Re[19]: Несколько вопросов по Меппарам.
От:
Аноним
Дата:
18.05.05 18:08
Оценка:
А можно не много по-подробней о твоей реализации, ты описал всё на очень специфическом языке, я почти ничего не понял. Извините но я только новичёк.
Здравствуйте, Аноним, Вы писали:
А>А можно не много по-подробней о твоей реализации, ты описал всё на очень специфическом языке, я почти ничего не понял. Извините но я только новичёк.
В моем профайле мыло есть, могу кинуть часть доки с описанием.
Выкладывать сюда пока не могу по понятным причинам.
Здравствуйте, GlebZ, Вы писали:
GZ>Все в мире относительно Если говорить о заполнении конкретного объекта, то да. А вот если говорить уже о коллекции, то не обязательно. Коллекция может состоять из инстансов объектов разных типов объединенными одним классом предка.
Я тебе поэтому и задавал наводящие вопросы типа можешь ли ты по записи определить тип объекта. Если да, то опять же, вопрос только в создании объекта правильного типа, а дальше обычный маппинг.
GZ>Или система из 1С(где-то Serginio1 описывал). Там строки хранятся по разбитые частям.
К сожалению, кривой дизайн ещё не считается преступление и Right Design Police Department не создан.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, vdimas, Вы писали:
V>И что характерно, зачастую объект со стороны Master не запрашивает свой detail. Чаще всего его запрашивают адаптеры с GUI или адаптеры-деревья на стороне сервера.
Против этого возражений нет. Клиентский код как правило лучше всех знает что ему надо.
V>Если же требуется выполнять какие-либо алгоритмы в самом БО со стороны Master, то ради бога — он запросит Detail для выбранной связи. Если эта штука не одноразового использования, я инкапсулирую в св-ва, т.е. проблем нет.
Здесь я позволю себе возразить. В данном случае ты перенёс связь с источником данных из одного места объекта в другое, но эта связь всё равно осталась в объекте.
IT>>К тому же надо будет на каждый тип коллекции создавать интерфейс :xz;
V>Пока юзаю обощенный интерфейс, потом перейду на генерики.
Да уж... скорей бы
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
V>>Здесь я позволю себе возразить. В данном случае ты перенёс связь с источником данных из одного места объекта в другое, но эта связь всё равно осталась в объекте.
Ради бога, вопрос был в эффективности (GetDetail() — блокирующий метод), и в синтаксическом сахарке путем инкапсуляции повторного действия в проперти и запоминания результата.
V>>Пока юзаю обощенный интерфейс, потом перейду на генерики.
IT>Да уж... скорей бы
Microsoft подводит сильно. У нас релиз в середине лета, в конце прошлой осени я строил планы выпуска на 2.0
Придется толкать первую версию на 1.1
------
Как там с RFD, кстати?
Может пора начать переводить совместными усилиями на 2.0? Очень нада будет скоро , в долгу не останемся, свои надстройки выложу рядом.
Здравствуйте, IT, Вы писали:
IT>Бизнес логике в БД вообще нечего делать. По многим причинам.
Угу. Есть только одна веская причина, по которой БЛ имеет смысл перетащить в БД: производительность на больших массивах. Но она находится в жёстком противоречии с гибкостью.
IT>DAL — это слой изолирующий базу данных от нашего приложения. Его задача — переводить термины базы данных в термины приложения. Т.е. из полей таблиц сконструировать объекты и наоборот. Опять же, никакой бизнес логики кроме конструирования объектов в нём быть не должно.
+1
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Геннадий Васильев, Вы писали:
IT>>Бизнес логике в БД вообще нечего делать. По многим причинам. ГВ>Угу. Есть только одна веская причина, по которой БЛ имеет смысл перетащить в БД: производительность на больших массивах. Но она находится в жёстком противоречии с гибкостью.
Абсолютно верно. Но в этом случае мы точно знаем за что платим.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Наконец руки дошли.
Что-то мне это не сильно нравится все это. Кому-то надо, кому-то не надо. Если нельзя объединять усилия по достижению общей цели, то менеджеров к стенке надо ставить. (или в сортире мочить как учит одно небезызвестное лицо) . Унифицировать интерфейсы(и состояние бизнес объектов) архиважная задача на пути к коммунизму и снижения издержек при буржуазном строе. Решить это политически значительно дешевле чем реализацию(с постановкой и тестированием). Это по количеству данных(состоянию) в возвращаемом объекте. Что касается самих объектов, то тот кому нужны адреса, должен заказывать адреса. Тому кому нужно companies тот заказывает companies. Это нормально.
Теперь по решению.
Самое простое решение описанное во все книжках. Каждый заказывает то что ему нужно. То бишь:
Каждый берет столько сколько нужно. Правда маленький недостаток. Оверхед количества вызовов. Проверено на практике, что кроме криминальных случаев, некоторый оверхед по объему дешевле чем оверхед по количеству вызовов. Поэтому дополнительно предлагаю следующий вариант.
Клиент:
Finder finderCompany=new Finder();
finderCompany.ObjectName="Company";//имя заказываемого объекта
finder.AddEqualPredicate("id", 1000);//получить те объекты у которого поле id=1000
Finder finderAddress=new Finder();
finderAddress.ObjectName="Address";
finderCompany.AddJoin(finderAddress, "AddressId", "Id");//добавляем связку показывающую что также нужны адреса.
server.GetCompanies(finder);
На сервере. Тут нужно всегда знать что если работаешь c layer'ами, изволь ими пользоваться. Поэтому тут задача передать заказ из внешнего слоя в нижний решается с помощью сервиса(если конечно это не Domain Model), допустим это объект ObjectGetter.
public DTO MyInterface.GetObjects(Finder finder)
{
IList companies=ObjectGetter.GetByFinders(finder);
return FormatDTO.FormatDTOFromObjects(companies);//форматируем в формат протокола пересылки бизнес объектов
}
//здесь у нас описывается запрос уже в терминах SQL.public struct SelectDescription
{
string _selectFields;//строка для селектовstring _from;//строка для from (но без joins)string _predicates; // строка для where
Join[] _joins;//описываем с кем связаныstring _alias;//алиас таблицы в запросе для данного маппера
IMapper _mapper; //ссылка на того, кто будет собирать результаты из него
}
//отдельно описываем джоиныpublic struct Join
{
string _predicate;//предикат связываения
EnumTypeJoin _typeJoin;//по какому joinу (внешний, внутренний)
SelectDescription _joinedDescription;//кого приджоиним
}
//само получение данныхpublic IList ObjectGetter.GetByFinder(Finder finder)
{
SelectDescription selectDescriptor=GenerateDescriptor(finder);
//из полученных данных генерируем запросstring sqlSelect=GenerateCommandString(selectDescription);
ArrayList result=new ArrayList();
//естественно, если нужна независимость от базы данных, или транзакции то операции БД в отдельные классыusing (SqlConnection connection=new SqlConnection(connectionString))
{
myConnection.Open();
using(SqlDataReader myReader = new SqlCommand(sqlSelect, myConnection).ExecuteReader(CommandBehavior.CloseConnection))
{
while(myReader.Read())
{
ReadFromReader(result, myReader, selectDescription);
}
myReader.Close();
}
}
return result;
}
//заполняем структуру SelectDescription уже SQL данными public SelectDescription ObjectGetter.GenerateDesciptor()
{
//обязательно пытаемся делать через маппер для конретного типа.
//Тогда мы можем управлять поведением заполнения и языка запросов
//в случае наличия универсального хранилища метаданных(и следовательно управления языком запросов)
// это можно сделать через один объект
IMapper mapper=GetMapperByObjectName(finder.ObjectName);
//создаем дескриптор для построение select
//второй параметр важен. алиас должен быть уникальным.
SelectDescription descriptor=mapper.GetSelectDescription(mapper, GenerateAlias());
//рекурсивно делаем joinsforeach(Finder finderJoined in finder.Joins)
{
SelectDescription joinedDescriptor=ObjectGetter.GenerateDescriptor(finder, GenerateAlias());
AppendJoin(desciption, joinedDescription);//заполняем структуры Join
}
return descriptor;
}
//чтение объекта из строкиpublic void ReadFromReader(ArrayList arrayResult, SqlDataReader myReader, SelectDescription descriptor)
{
//создают и заполняют объекты безусловно мапперы
descriptor.Mapper.LoadObjects(arrayResult, description, myReader);
//заполняем по рекурсии joinsforeach (Join join in descriptor.Joins)
ReadFromReader(arrayResult, myReader, join.SelectDescriptor);
return arrayResult;
}
Код написан только примерно и сходу. Поэтому там должно быть множество ошибок (я так думаю). Просто описано достаточно, чтобы понять само решение. Result может быть (а обычно бывает) не просто ArrayList, а более сложным.
Очень интересно, что такая длинная полемика по одному вопросу
Не смог удержаться от комментария.
Собственно, мой подход в принципе — это упрощенная модель БО — без
знания про источник данных(БД)
Например ситуация: при SOA(service oriented architecture) уже никак
нельзя хранить в БО объекты доступа к источнику даных, тк сборка со всеми
БО должна быть отдельной для использования на:
— серверной стороне наряду с функциональностью доступа к БД;
— и на клиенте(отображение), чтобы не плодить лишних сущностей.
Еще замечание про ПРОКСИ. Всем известно, что проксииспользуется для:
— lazy loading,
— code security,
— remote communication.
Но, его использование — требует кодирования, при чем однотипного
Сразу оговорюсь, я давно уже это не пису, ибо EMIT как раз мне и помогает,
конечно не сырой, а в прикольной реализации пришлось...
Собственно, всякие такие штуки должны использоваться в контексте системы
генерации кода, если даная ситуация происходит часто и решается через
копирование и подправление. А кто потом менять в 100 местах будет, уж если
поменять захочется.
Еще, есть отличные ОРМ помощнички, которые неплохо работают. В том, что
я использую ВСЕГДА есть 2 режима генерации
— SelfServicing — объект сам отвечает за вычитку себя из базы (активный можно так сказать)
— Adapter — работа через адаптер (пасивный)
И напоследок, для меня самым важным моментом проектирования является разбиение на модули и
ПРАВИЛЬНАЯ их ссылочнотсь друг на друга — такой себе граф (конечно без зацикливаний).
Рисунок очень наглядноотражает основные подходы: low coupling & high cohesion, а сдесь и
переносимость, и и универсальность, и еще куча всего приятного
Здравствуйте, Damat, Вы писали:
D>И напоследок, для меня самым важным моментом проектирования является разбиение на модули и D>ПРАВИЛЬНАЯ их ссылочнотсь друг на друга — такой себе граф (конечно без зацикливаний). D>Рисунок очень наглядноотражает основные подходы: low coupling & high cohesion, а сдесь и D>переносимость, и и универсальность, и еще куча всего приятного
А каким ORM средством ты пользуешся
Здравствуйте, IDL, Вы писали:
IDL>Здравствуйте, Damat, Вы писали:
D>>И напоследок, для меня самым важным моментом проектирования является разбиение на модули и D>>ПРАВИЛЬНАЯ их ссылочнотсь друг на друга — такой себе граф (конечно без зацикливаний). D>>Рисунок очень наглядноотражает основные подходы: low coupling & high cohesion, а сдесь и D>>переносимость, и и универсальность, и еще куча всего приятного IDL>А каким ORM средством ты пользуешся