WEB форумы на jedi
[Форум] [Помощь] [Поиск] [Выйти]
Добро пожаловать, [info]User

WEB форумы на jedi [ПОИСК] [Архив до 03.2006]

Тема Такая вот программка К предыдущему сообщению На следующее сообщение Программирование

Отправил Patrol в 22:10 23.01.2005[Ответить]
Господа программисты!
В новогодние праздники вспомил свою некогда любимую игрушку - CodeDom. Ну, и решил соорудить что-нибудь.
На данный момент есть штучка, которая может быть будет кому-то полезна, может - нет, однако у меня свой интерес ;)

Словом, я наваял утилитку, которая по указанным таблицам (и View) базы данных MS SQL умеет геренировать бизнес-логику..
Ну, там, генерится класс объекта, класс коллекции данного объекта, хранимые процедуры для работы с этим объектом (Get, Insert, Update, GetList, Delete)..

Прога поддерживает Generation Gap (паттерн такой, если кто забыл)...

Но что хотелось реализовать (как любителю CodeDom) - независимость от языка программирования генерируемого кода.
В настоящий момент я имею C# и VB, с ними все ОК.
Тут, как я вижу, немерено любителей Дельфи (почему-то ;)), хотелось бы, чтобы кто-нить попробовал добавить в конфиг строчку и попробовать сгенерить код на паскале.NET.
Оно вообще работать будет? :)

Ну и вообще, баги мне интересны.. И, как я сказал, может кому полезно будет..

Словом, сайтик я вчера сваял тоже: http://codegen.perignator.com/

:) Буду благодарен :)


Отправил Patrol в 22:40 24.01.2005[Ответить]
Мдя, облажался я конкретно.
Спасибо ErrNo, который, собственно, и вразумил :)
Словом, прошлая версия, которую я выкладывал, была случайно собрана под мой домашний environment и запуститься нигде больше просто не могла физически (в том числе и у меня на работе :))

Словом, пофиксено, пересобрано под общие нужды :)
Извиняюсь, если кто лишние 80 килобайт стянул :(


Отправил Dushes в 14:27 31.01.2005[Ответить]
Вообще, конечно, забавное название игрушки...
В .net под этим как-то совсем другое понимается ;)

чтото вроде этого:
The .NET Framework includes a mechanism called the Code Document Object Model (CodeDOM) that enables developers of programs that emit source code to generate source code in multiple programming languages at run time, based on a single model that represents the code to render.


угу...догнал...чтото не сразу первой топ понял (не геймер sorry), а по урлу сходить поленился...
респект



Отправил Dushes в 16:38 31.01.2005[Ответить]
вдогонку
расскажи в двух словах, для чего-это, насколько понял, для генерации кода подключения к датасетам...некогда смотреть, может быть, весчь хорошая..:)
а что, стандартной генерации кода не хватает, SqlDataProvider на форму, типизированный датасет, получил XSD, сгенерил код и методы Update, Insert, Delete, Select? этого не достаточно...



Отправил CAHbKA в 17:41 31.01.2005[Ответить]
оно только выглядит так, что массовые операции делает поштучно или на самом деле так и есть?

а вот фотки нельзя ли отдельно в приличном качестве на сайте поместить, которые вставлены в инсталлятор. и другие, остальные :-)


Отправил Patrol в 18:26 02.02.2005[Ответить]
Извиняюсь, давно тут не был.

>>расскажи в двух словах, для чего-это, насколько понял, для генерации кода подключения к датасетам...некогда смотреть, может быть, весчь хорошая..:)

Нет, DataSet вообще тут ни при чем. Во-первых, работать с ним (даже и с типизированным) не очень-то и приятно. По понятным причинам (разжевывать не буду, ты человек, видимо, грамотный, судя по топику описания .NET).

Если кому-то станет интересно, почему неудобно работать с типизированным DataSet - могу рассказать, спрашивайте :)

Генератор генерит (сорри за сентенцию) набор объектов (НЕ DataSet/DataTable), которые отображаются в базу данных. Например по таблице Products с полями ProductID и ProductName будет сгенерирован класс Products с одноименными свойствами и методами Save, Get, GetList, Delete. Будет сгенерирована так же коллекция данных объектов. Что делают методы Save, Get, Delete с объектом понятно из названия ;) GetList как раз возвращает коллекцию данных объектов.

При этом код расчитан на Generation Gap.

Объясняю:
Для каждой сущности генерится класс и базовый класс-предок. Базовый класс содержит всю сгенерированную логику, то есть как раз свойства и методы мною описанные.
Класс-наследник - пустой и предназначен для того, чтобы с ним работал программист. Это ведь естественно, что для решения клнкретных задач потребуется придать классам конкретную функциональность. Например, классу Product приделать еще пару методов: SaveToFile и SendByEmail.. Зачем - не знаю, это пример :) Или, например, GenerateProductReport какой-нибудь. Ну, классы обычно имеют свойство инкапсулировать логику, отличную от логики работы с базой данных.
Так вот, для того, чтобы программист реализовывал нужную ему функциональность, предлагается использовать класс-наследние.
Почему не ограничиться одним классом и зачем нужно разбиение?
Объясняю. Структура таблицы может измениться. И тогда вы скажете генератору перегенери-ка мне базовые классы. Он и перегенерит только то, что нагенерил сам. Ваш код в классах-наследниках останется нетронутым, вы не потеряете его при перегенерации. :)

Таким образом, на слой базовых классов можно вообще внимания не обращать и работать только с классами-наследниками, так как они, разумеется, наследуют всю логику работы с БД от базовых :)
А в генератора вам генерит базовые классы и хранимые процедуры, вам не надо писать их ручками.

>>а что, стандартной генерации кода не хватает, SqlDataProvider на форму, типизированный датасет, получил XSD, сгенерил код и методы Update, Insert, Delete, Select? этого не достаточно...

Не то. Я не о создании Strongly Typed Dataset говорю, а о создании бизнес-объектов. А на DataSet далеко не уедешь ;) Тем более с подходом Кинул на форму и поехал ;)
Все-таки какой-никакой а Data Access Layer советую делать.

Декларативный двесторонний dataBinding будет, но только в 2.0 :) И то для сколь-нибудь серьеных приложений этот подход не очень-то применим, я думаю...


Отправил Patrol в 18:31 02.02.2005[Ответить]
>>оно только выглядит так, что массовые операции делает поштучно или на самом деле так и есть?

О чем речь? Какие массовые операции? Если ты говоришь о генерации кода - то нет, ты можешь указать полсотни таблиц и разом сгенерить код для них.

Если ты говоришь о работе сгенерированного кода, то да, там нет массовых операций Delete, Update или Save. Каждый объект отвечает за себя сам, другое поведение.. Хм, либо специфично и зависит от проекта, либо приведи примеры.. Я могу добавить функционал сгенерированного кода, это не сложно, просто идеи.. ;)

>> вот фотки нельзя ли отдельно в приличном качестве на сайте поместить, которые вставлены в инсталлятор. и другие, остальные :-)
Которые Остальные - если про те, что в моей галерее - то я ее починил :) Дошли руки :) Долго она ждала, на самом деле..
Которые скриншоты.. Ну нафиг ;) скачай и наскриншоть себе ;) Оно какое-то большое тогда становится, не красиво ;)


Отправил Patrol в 18:58 02.02.2005[Ответить]
А вообще, народ ;)
У кого есть дельфи с .NET-поддержкой.. Там же должен быть CodeDom, попробуйте генерилку запустить чтобы код на дельфе сгенерила.. Мне интересно что получится и какие будут баги ;)


Отправил CAHbKA в 19:03 02.02.2005[Ответить]
а тогда практическая польза от этого какая, кроме зарядки для ума? вот, к примеру, как буде(у)т выглядеть запрос(ы) к базе, который(е) вернё(у)т все красные, переднеприводные, кузов ля-ля, не дороже 3000 кары?

а! что это за SQL Stored Procedures? это еще один зачем-то уровень логики и call'ов или как раз где-то тут собака порылась?

p.s.
а галерея то где? :)


Отправил Patrol в 00:10 03.02.2005[Ответить]
Хм. Над этим я много думал.
Объясню очень коротко: стоит 2 проблемы, точнее - возможности
1) SQL-Server'ный paging данных. Это когда для того, чтобы показать 59-ю страницу выборки из 1000 записей с 10 записями на странице, нужно тянуть все данные на уровень приложения и показывать только требуемую страницу. Имхо, маразмматично, особенно, если тянуть все в DataSet :)

Наиболее простое принципиальное решение: ADO.NET умеет это делать. Производительность несколько (несколько, а не катострофически, как когда тянешь все в dataSet) хуже, чем просто на уровне DB, но зато логика проста и прозрачна и не нужно делать страшных и сильно заточенных запросов или хранимых процедур.
Решение с помощью PT Codegen Lite: В генераторе отсутствует логика генерации пейджинга на стороне SQL-сервера. Просто потому, что это Lite-версия :) Дорисовывать пейджингующиеся хранимые процедуры было бы можно, но этого нет.
Возможно появится, как только я вернусь к этому и если я решу, что это нужно в Lite :) Вообще весьма вероятно, ибо задача общая :)
В настоящий момент никто не может помешать просто приделать соответствующий метод в сгенерированный класс и радоваться успеху :) Потому как ни сам класс, ни остальную логику работы с ним (например, update значений) делать уже не придется - оно уже есть :) Словом, нужно просто самому написать один метод типа GetList(int pageSize, int pageNumber) - и все :)
Но в целом это можно переложить на генератора.

2) То, о чем пишешь ты - фильтрация данных. Сомневаюсь, что можно достаточно эффективно переложить это дело на плечи генератора в том виде, в котором он задумывался ибо:
- Изначально хотелось избежать формирования SQL-запросов внутри кода. В хранимую процедуру это вынести будет.. ну, будем считать, что невозможно, ибо логика фильтрации весьма неоднозначна (так как кроме все синие могут быть все не синие у которых пробег меньше 20000 или красные, но новые - это уже свой маленький интерпретатор получится. И его придется включать в сгенерированный код.
- Фильтрация подобного рода обычно весьма специфична от проекта к проекту и включать в код пользователя некий универсальный механизм было бы излишне - будет большой объем редкоиспользуемого кода, который, ко всему прочему, еще и нужно научиться использовать.
Решение: Данный генератор (по крайней мере Lite его версия) задумывался как инструмент, быстро выполняющий рутинную работу, которую нужно делать практически в каждом проекте (который не настолько велик, чтобы проектировать его в UML). То есть, с чего часто начинаешь работать? С того, что после проектирования у тебя вырисовывается схема базы данных, в которую отображаются сущности (бизнес-объекты) твоего приложения. При этом тебе нужно писать эти самые сущности - создавать класс и те его методы, без которых никуда (базовые, так сказать) - чтение из БД, изменение, сохранение, удаление. И так каждый класс. И хранимые процедуры к ним. Это скучная рутина, на нее уходит много времени. В то же время процесс достаточно однообразен.

Именно эту задачу и должен по идее решать PT Codegen Lite - создать сущности с базовой функциональностью. Он НЕ претендует на то, что кнопку нажал - и у тебя уже все приложение заработало ;) Это уже потом стараниями программиста они будут обростать специфичным для приложения функционалом (у класса User, например, появится метод SendPasswordByEmail(bool generateNew) и т.д.). Как оно бы и происходило, не будь никакого генератора.. Просто начальная фаза создания базовой функциональности, которая все равно понадобится, будет гораздо дольше :) Сгенерить 50 классов быстрее, чем написать их :)

>>а! что это за SQL Stored Procedures? это еще один зачем-то уровень логики и call'ов или как раз где-то тут собака порылась?
Ну знаешь.. Я мало видел программистов-сторонников писать код SQL-запроса в коде приложения. Хотя сам был однажды уличен в этом (но там случай был особый) ;) На моей текущей работе, например, на такое бы просто сказали, что для того, чтобы сильно ударить по голове, требуется всего 4 мышцы напрячь ;) Bad practice, короче. Для этого и используются хранимые процедуры. О том, что это такое, можно почитать в интернете, но еще одним уровнем я бы не стал их называть.

Что касается остального, того, что есть в не-Lite версии и чего в Lite по идее не появится:
1) Связи между таблицами. Это когда у класса Order появляется метод GetProducts (или свойство, не суть), возвращающее коллекцию всех продуктов, имеющих отношение к этому ордеру. Генератор ориентируется на связях в БД.
2) Возможность генерации простого UI. Актуально особенно для Web-приложений. Ибо, честно говоря, задалбывает делать формы изменения, просмотра и списка этих самых продуктов, расставлять все эти лейблы, присваивать им значения, потом обратно считывать и обновлять, да еще и валидацию производить :) Для Windows Forms рутины меньше, но лишь немногим. Гораздо приятнее, когда генератор генерит все это дело, а тебе потом остается добавить специфическую логику (если она есть) да навести дизайн (либо просто CSS подключить).
3) Возможность сохранять проект генератора. Сознательно не добавлена в Lite :) При перегенерации сейчас нужно заново выбирать таблицы, задавать свойства и т.д. В не-Lite версии можно сохранить файлик проекта, а потом просто подгрузить его.
4) Генерация проектного файла для Visual Studio 2003. Чтобы потом просто мышкой кликнуть и открыть :)

P.S. Так на http://www.perignator.com/ :)


Отправил Dushes в 09:57 03.02.2005[Ответить]
To:Patrol - респект, будем смотреть...
маленький совет - сделать на сайте раздел faq, куда можно поместить вот такие вопросы/ответы, да и русскую версию сайта неплохо было бы поиметь...;)


Отправил Patrol в 10:27 03.02.2005[Ответить]
Зачем тебе русская версия, когда ты мне даже тут, в русском форуме, по-английски отвечаешь (пример про CodeDom) ;)
И в соседнем, на тему Framework, тоже половина сообщения на английском ;) Да и лень мне..

Про FAQ подумаю.. Но тут пока не было вопросов по собственно программе и ее использованию.. Все, что я тут писал, есть на сайте.. И назначение и фичи..


Отправил CAHbKA в 04:26 04.02.2005[Ответить]
так а где sql-код то? вот где пример того, _что_ надо не забыть, чтобы работали Vehicle.Create(15) и т.п.?


Отправил Patrol в 10:43 04.02.2005[Ответить]
SQL-код, Саш, там, где ему и положено быть - в утробе SQL-сервера ;)

Хранимые процедуры (иногда - сохраненные процедуры), иначе - Stored Procedures, потому и Stored, что сохраняются в базе данных вместе с таблицами, вьюсами, триггерами и прочими страшными штуками :) Создав там хранимую процедуру GetSuperObject, которая делает что-то вроде

SELECT * FROM SuperObjects WHERE Id = @SuperId

можно потом из кода обращаться к ней просто по имени, например

GetSuperObject 15 или GetSuperObect @SuperId=15

:) При этом мы имеем массу плюсов начиная от того, что код приложения иначе не связан с логикой БД и работает только с предоставленными данными независимо от того, каким они путем там в недрах SQL Server получаются и заканчивая тем, что план выполнения этого запроса (процедуры) сохраняется сервером, процедура проходит предкомпиляцию и т.д. и т.п., что позволяет увеличить скорость ;)

>>вот где пример того, _что_ надо не забыть, чтобы работали Vehicle.Create(15) и т.п.?

Генератор генерит SQL-файл. Или несколько файлов (по одному на каждую процедуру), как укажете, как удобнее.
Нужно просто выполнить его в своей базе данных. Эти запросы выполняют создание всех процедур, то есть содержат набор SQL-команд типа
CREATE PROCEDURE GetMyObject (
@SuperId int
)
SELECT * FROM SuperObjects WHERE Id = @SuperId

:)


Отправил Dushes в 11:10 04.02.2005[Ответить]
>... заканчивая тем, что план выполнения этого запроса (процедуры) сохраняется сервером, процедура проходит предкомпиляцию и т.д. и т.п., что позволяет увеличить скорость ;)

реально mssql начиная с 2000 выражения sql-запросов (не Stored procedures) тоже проходят этап компиляции, при повторном использовании такого же запроса с такой же симантикой реально будет запущен откомпилированный запрос..так что разницы большой в производительности никак не получишь (если сравнивать использования Stored procedures и clients text query)///
Реальный выйгрыш в производительности можно получить, используя batch пакеты запросов и обрабатывать их ридером (можно получить сразу несколько рекордсетов за одно обращение к серверу), опять же лучше часть логики самого sql-выражения перенести на сторону самого клиента...т.е. такие операции как order by выполнять на клиенте...




Отправил Patrol в 12:08 04.02.2005[Ответить]
>>реально mssql начиная с 2000 выражения sql-запросов (не Stored procedures) тоже проходят этап компиляции

Для того, чтобы производительность хоть как-то сравнялась, нужно делать параметризованные запросы.
Хранимые же процедуры обычно делают много чего. Например, в последних проектах, в которых я работал, тексты процедур иногда занимали пару страниц SQL-кода. Сложно представить такой код в виде строки в файле :)
Кроме того, существует такая вещь, как архитектура. И Model-View-Controller. Дело в том, что нормально сделанное приложение не должно зависеть от того, как SQL-сервер поставляет ему данные (в идеале). Его (приложения) дело сказать серверу дай мне то-то или удали то-то, и уже сервера работа знать как это делать, что еще нужно удалить при удалении такого-то объекта, куда записать лог и хистори при этой операции, не откатить ли транзакцию в случае чего.
Код, находящийся в SP легко администрировать, управлять им, изменять его. Как и в любом другом случае, когда обязанности сущностей разделены, а не свалены в одну кучу. При этом изменения на уровне Data по большому счету не должны касаться приложения, оно о них и не знает ничего. И если вдруг таблицу продуктов разбили на 2, на 15, на 150 (утрирую, конечно, но, например - горизонтальный сплит по вендору), то приложение как запрашивало продукт с Id=15, так и должно... И уже дело SQL-сервера разобраться и отдать нужный продукт.. :)

>>опять же лучше часть логики самого sql-выражения перенести на сторону самого клиента...
И устроить зоопарк, размазать логику.. часть тут, часть там..

>> А почему на сервере их не выполнять? :-/ В тупик меня поставил..


Отправил Dushes в 12:28 04.02.2005[Ответить]
>>Для того, чтобы производительность хоть как-то сравнялась, нужно делать параметризованные запросы.
Ничто не мешает в выражении SQL запроса подставить значения параметров, (даже если CommandType.Text) - также подставляешь параметры в коллекцию Parametrs и получешь результат - SqlCommand сработает аналогично вызову хранимой процедуры (не веришь, попробуй;))) )

>>Хранимые же процедуры обычно делают много чего. Например, в последних проектах, в которых я работал, тексты процедур иногда занимали пару страниц SQL-кода. Сложно представить такой код в виде строки в файле :)....

да никто не спорит, что ХП ценная вешь и все такое - но если количество клиентов велико, то архитуктуру приложения можно разнести и на сторону клиента или на бизнесс-уровень...скажем, ту часть которая касается сортировки данных или фильтрации (к примеру, для случая если клиент получил какой-то большой рекордсет изначально и стоит уточнять уловия where - в таком случае не стоит сервер беспокоить на повторный запрос, если данные уже !!! на стороне клиента, клиент ведь сам сможет часть работы сделать вместо того чтобы лишний раз грузить сервер)

>>И устроить зоопарк, размазать логику.. часть тут, часть там..
В общем случае клиентское приложение все равно в той или иной степени зависит от того что ему возвращает сервер, так или иначе, отображает он в контролах или же привязана какая-либо логика их обработки - почему то это не называется зоопарком:-/ ...Если зоопарком называется получить данные с сервера (без разницы с какого, но зная структуру полученных данных, к примеру при помощи вызова ХП), а потом к примеру в dataview на стороне клиента сделать сортировку или наложить фильтр - то даже и не знаю что на это ответить :((((

>> А почему на сервере их не выполнять? :-/ В тупик меня поставил..
я не говорил о том что надо отказаться от использования ХП...бех них никуда






Отправил CAHbKA в 20:23 04.02.2005[Ответить]
Лёш, ты не издеваешься?

а если я снова про своё спрошу? :-) :

после твоих развесистых лекций видимо уже всем стало понятно, что собака таки в sql-коде. что основной уровень логики и кода в базе, где ему и положено быть.
эту логику и вызовы ложит туда твой lite. еще есть второй уровень логики и вызовов. то, что на страничке http://codegen.perignator.com/howtouse.html показано. Вот то, что там показано как-то совсем не вдохновляет. поэтому и пытаюсь выяснить - во что эти глупости обходятся? надо вопрос разворачивать? может проще sql-код показать?


Отправил Patrol в 17:41 07.02.2005[Ответить]
Саш, я правда не понимаю вопроса...
Какой SQL-код? Код Stored Procedure чтоли?

Вот, например, код, сгенерированный для Update объекта OrderDetails:

CREATE Procedure OrderDetails_Update
@OrderID int,
@ProductID int,
@UnitPrice money,
@Quantity smallint,
@Discount real
AS

UPDATE [Order Details]
SET

[UnitPrice] = @UnitPrice,
[Quantity] = @Quantity,
[Discount] = @Discount
WHERE
[OrderID] = @OrderID AND
[ProductID] = @ProductID

-- return the primary key fields, identity and computed fields
SELECT
[OrderID],
[ProductID]
FROM [Order Details]
WHERE
[OrderID] = @OrderID AND
[ProductID] = @ProductID

GO

Или что? Скажи конкретнее :)

А собака все-таки не в SQL-коде, а как раз в генерации _классов_ на языке программирования ;) Ну и некоторый функционал, как то загрузка/обновление тоже генерится автоматом как приложение.. Кстати, опционально..


Отправил Patrol в 18:55 07.02.2005[Ответить]
В общем, сделал я еще одну страничку:
http://codegen.perignator.com/sqlexample.html

Там пример SQL-кода, который был нагенерен по таблице Order Details. Эти процедуры и вызываются соответствующими методами.


Отправил CAHbKA в 21:35 07.02.2005[Ответить]
я правильно пытаюсь понять:
- есть sql
- строим логику вызовов используя процедурное расширение sql'я
- над ней строим логику вызовов из языка /тут надо думать нам где-то подсунули что-то универсальное вида execsql(...), что мы где-то там и вызываем, как результат=sqlexec(процедура(параметры))/

это для того, чтобы получить синтаксис myCar.Save() ?


Отправил Пaшкa в 22:21 07.02.2005[Ответить]
Это не просто синтаксис. Это нормализация объектной модели приложения.


Отправил Patrol в 11:08 08.02.2005[Ответить]
Почти верно.
В целом модель такая:

1) Есть слой базы данных. На этом слое находится логика БД (процедуры, триггеры, функции, словом, все, что обеспечивает целостность модели) и таблицы, вьюсы..

2) Есть DAL (Database Access Layer). На этом уровне инкапсулируется весь дотуп к слою БД, как то, получение Connection, выполнение команд и т.д.

3) Слой бизнес-логики. Этот слой взаимодействует с DAL для работы с БД. Соответственно, из DAL и только из него он получает Connection, через DAL и только через него производятся операции с БД.

В моем примере:
слой 1) представляет из себя собственно БД и сгенерированные хранимые процедуры.

слой 2) есть сгенеированный класс Connection, который представляет из себя Singleton и возвращает строку подключения, а так же либо стандартный набор .NET: SqlConnection, SqlCommand и иже с ними, либо инкапсулирующий их класс, написанный Microsoft, MS DB Helper, который выполняет всякие полезные штуки типа прозачного кеширования параметров хранимых процедур, верификацию их типов и тд., к тому же позволяя сильно упростить синтаксис работы с БД. (У меня такой классик тоже есть, но надо его доработать на предмет работы со сборщиком мусора, поэтому Extended DB Helper в генераторе пока не доступен).

слой 3) - сгенерированные объекты. Поскольку слои 1) и 2) фактически готовы на момент окончания генерации и логика работы с DAL тоже уже инкапсулирована, то программист может сосредоточиться на своей непосредственной задаче - реализации бизнес-логики приложения :)

Да, это все нужно для того, чтобы вызвать myCar.Save, чтобы он сработал так, как надо, чтобы при изменении любого элемента этой операции было совершенно однозначно ясно где и как это делать, чтобы код не дублировался и чтобы, как правильно сказал Паша, объектная модель была нормализована :)
Я даже больше скажу - в больших приложениях рекомендовано делать еще один слой бизнес-логики, тогда появляется отдельно класс myCar и отдельно класс myCarDB, который работает только с DAL и используется классом myCar ;) Но это - в больших приложениях и не всегда.. :)


Отправил CAHbKA в 13:23 08.02.2005[Ответить]
ну, тут всё обычно.
мозги сидят в базе, а вся возьня, чтобы вместо
public void CreateOperation()
{
//Create a new business object
param1 = Image.FromFile(@c:carsmy.jpg);
param2 = My primary car;
param3 = BMW M5;
//Save in the DB
execsql(save_preocedure(param1,param2,param3));
}

написать

public void CreateOperation()
{
//Create a new business object
Vehicle myCar = new Vehicle();
myCar.Photo = Image.FromFile(@c:carsmy.jpg);
myCar.Notes = My primary car;
myCar.Title = BMW M5;
//Save in the DB
//The primary key, identity and computed fields
//will be set up into myCar object automatically.
myCar.Save();
}

в целом это не интересно.


Отправил Пaшкa в 14:13 08.02.2005[Ответить]
Вся возня из-за этого, конечно, только цель совсем не в том, чтобы упростить синтаксис. Цель избавиться от повторяющихся кусков кода, уменьшить связанность отдельных объектов системы, для более простой модификации (если вдруг потребуется) и расширения.


Отправил Patrol в 14:40 08.02.2005[Ответить]
Да нет же...
Смешной на самом деле подход ты предлагаешь :)))
Вся возня для того, чтобы у тебя вообще БЫЛ класс myCar :)
Иначе тебе его руками писать придется.
Просто потому, что на param1, param2 и param3 далеко не уедешь.
У тебя тогда не будет объекта, понимаешь? Тогда тебе придется при работе с продуктом иметь кучу функций непонятно где и кучу переменных типа param1 .. param20.. И так в каждом месте, где тебе необходимо использовать... Это называется ПОМОЙКА, чтобы ее избежать люди и придумали инкапсулировать param1 .. param20 в один объект и делать так, чтобы этот объект САМ отвечал за себя.

Вот когда ты вместо new Vehice() будешь делать в 50 разных местах param1 =, patam2 =, param3= и т.д. - вот тогда ты и проклянешь все на свете :) Когда тебе понадобятся вычисляемые поля и ты будешь в тех 50 местах их вычислять.. когда у тебя появятся куча библиотек со статическими функциями типа СделатьТоТо()...
Когда тебе понадобится чуть-чуть изменить чего-нибудь.. ;)

Для этого люди и пидумали объектно-ориентированное программирование. Для справки скажу, что работая с .NET ты просто НЕ МОЖЕШЬ работать не объеъктами. Так, ты НЕ МОЖЕШЬ создать просто какой-то глобальный метод execsql и т.д.

Это уже не в целом неинтересно, а просто в мире нигде даже не обсуждается, использовать ли объектно-ориентированный подход или нет... Во многих языках и системах идет активное развитие в этом направлении (PHP, например), а другие - такие, как языки семейства .NET (для которых и предназначен генератор), и вообще исключают не-объектный подход.


Отправил CAHbKA в 01:17 09.02.2005[Ответить]
на сколько смешной? :)

наблюдай за руками:
сущность.
сущность лежит в базе.
сущностью лежащей в базе манипулируют процедурные расширения sql (лежащие в базе же).

остановка.
остановка называется выше перечислена вообще вся работа, которая нужна

поехали:
хотим делать эту работу из другого места, к примеру лепим GUI
рассматриваем два варианта:
1) sub1() - хороший
2) sub2() - плохой

____
sub1()
{
хитрый_тип переменная1;

переменная1.атрибут1 = значение1;
переменная1.атрибут2 = значение2;

переменная1.сохранить();
}
...
хитрый_тип.сохранить(){

реальная_работа_с_базой( sql_code %1 %2, переменная_из_которой_нас_вызвали.атрибут1, переменная_из_которой_нас_вызвали.атрибут2):
}
...

реальная_работа_с_базой(...){
// реализация зависит от БД
// тут вместо %1 подставляется значение первой переменной после запятой, и т.д.
// трансформируется во что угодно, от select * from %1 where %1.id=%2 до call_stored_proc(%1,%2)
}

_____
sub2(){
простой_тип1 переменная1 = значение1;
простой_тип2 переменная2 = значение2;

реальная_работа_с_базой( sql_code %1 %2, переменная1, переменная2):
}


У тебя тогда не будет объекта, понимаешь?
я не огорчился. объект это такая условность, принятая в рамках объектной методологии. а слова объект, класс, бизнес-объект в рамках дискуссии туман на мозги.

повтор еще раз:
это помойка:
{
char *s1 = My primary car;
char *s2 = BMW M5;
char *buf = redfile(c:carsmy.jpg);

sqlexec(call_stored_proc(%s, %s, %S);, s1,s2, buf);
}

а это НЕ ПОМОЙКА
{
Vehicle myCar = new Vehicle();
myCar.Photo = Image.FromFile(@c:carsmy.jpg);
myCar.Notes = My primary car;
myCar.Title = BMW M5;
myCar.Save();
}
(скрытый вопрос: найдите 10 отличий помойки от не)

И так в каждом месте, где тебе необходимо использовать...

вместо new Vehice()
а чем таким отличается вехикль от даже int i ? (риторический)
ровно столько же раз надо присвоить значения, в тех же 50 местах. считать будем? ;-)
последствия чуть-чуть изменить ровно те же ;)

объектно-ориентированное программирование это тоже туман, ОДНА из методологий и ОДИН ИЗ подходов, и только.

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


Отправил Patrol в 12:34 09.02.2005[Ответить]
Насколько смешной?
Настолько же, насколько в .NET невозможен процедурный подход.
Настолько же, насколько при предложенном тобою подходе работать просто НЕУДОБНО.
Как, например, будет неудобно в 50 местах, где нужно получить машину с идентификатором 15 вызывать процедуру, возвращающую 20 переменных и с ними работать. С именованным объеутом работать гораздо удобнее ;) Хотя, конечно, он и хранит внутри себя те же 20 переменных, но программировать становится проще, не нужно, например, каждый раз писать вызов процедуры sql_save(...) с 20-ю праметрами. Опять же, этот объект в другую функцию передавать удобнее, нежели 20 отдельных переменных, не боясь, что появится 21-я и тогда придется поменять штук 40 функций для его поддержки :) Опять же, все те же функции по работе с объектом будут, но уже внутри объекта - их проще понимать и искать, нежели полторы тысячи процедур типа product_save, order_save и т.д.. И каждая с охрененным числом параметров.. Причем, сделать универсавльную нельзя, потому что при сохарнении нужно еще делать разные зависящие т конкретной сущности вещи - кому-то значение проверить (vehicle), кому-то лог записать (order), кому-то имейл послать (invoice)...
Функции-то все те же будут, просто иначе организованные..

Найти 10 отличий? Нашел.
Например, в реализации метода Save, который внутри сделает примерно следующее:

this.FullName = String.Format({0} {1}, this.Vendor, this.Title);
//здесь должно сработать событие OnSave
OnSave();

Например, отличие в реализации свойства Photo, которое может принять на вход картинку, ресайзнуть ее, сделать иконку для превью и определенного размера большую картинку, сохранить это в объекте..

Например, в верификации значений.. Свойство объекта Title просто не может принимать пустое значение, возбуждая в этом случае событие OnTitleError()..

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

Тебе же придется в своем примере с
char *s2 = BMW M5;
везде делать изменения, ставить везде какие-то условия, как-то эмулировать события и т.д.

Т.о. фишка объектно-ориентированного подхода еще и в том, чтобы вся логика работы сущности Vehicle была зашита в самой сущности. И когда сущность меняет свою логику работы это никак не отражалось на других сущностях и на методах работы с этой сущностью :) И это не очень удобно, проверять каждый раз при задании
string param1 = value;
писать что-то типа:
if (value != ) param1 = value; else //do something else
на предмет допустимости значения и делать что-то в случае ошибки. Гораздо удобнее просто присваивать значение, реализовать проверку где-нибудь в другом месте. Ее и изменить тогда будет проще.
Паша тут уже говорил об умешьшении связанности сущностей между собой :)

Впрочем, давай обсудим процедурный подход vs объектный в соседнем топике ;) Я - с удовольствием :)
А пока считай, что генерилка предназначена для тех, кто использует объектный подход, поскольку она работает только для .NET и не использовать его там просто не представляется возможным :) Или, еще лучше, потому, что людей, использующих объектный подход при программировании на .NET гораздо больше, нежели не использующих оного :)

Теперь о том, что и зачем я сделал ;)
С учетом того, что .NET не предоставляет нам возможности использовать процедурный подход, ибо все, чем ты там располагаешь суть объект (даже элементарный int), то наличие самого объектного подхода неизбежно.

Кроме того, еще раз хочу уточнить: я не предланаю новых методов программирования. Я не предлагаю никакого кода, который что-то делает как-то уникально. Мой генератор не предназначен для того, чтобы нарисовать код, который был бы жутко круче чем тот, который ты можешь сделать руками.

Он предназначен, чтобы автоматически сделать то, что все равно делает каждый программист. Ибо в .NET каждый программист создает классы/объекты, наделяет их функциональностью.
И код, который генерирует мой генератор, в этом смысле самый-самый обычный. Посади любого писать - он примерно такой же напишет руками. И процедуры такие же сделает. Потому что другого пути в программировании на, скажем, C# просто нет. Тут выигрыша никакого.
Выигрыш лишь в скорости :) Этот достаточно простой код можно написать за 15-20 минут / 1 класс, либо сгенерить за 2 минуты / n классов.
Вот генератор и генерит класс и базовую логику. Такую же, как я и другие .NET-программисты пишем руками ежедневно. Ничего нового, более того - многое отсутствует.
Но если я экономлю хотя бы 10-15 минут с класса, то в обычном проекте с сущностями типа User, Model, Client, Product, Order, Invoice, OrderDetail это уже 70 минут рутинной работы сэкономлено ;)
А дальше, конечно, я открываю эти классы и добавляю остальное...

Так что это не костыль надо процедурной надстройкой просто потому, что процедурной надстройки в .NET просто нет - раз и потому, что это всего лишь обычная автоматизация рутинной работы - два. В самой методологии - ничего нового :)
Можно считать весь .NET таким костылем, тогда - да, я им пользуюсь. Это очень удобно. Ну, типа, как метро - костыль добраться на работу ;) Я могу сам, пешком, но это займет часа 3-4... Я усилий больше потрачу, я устану, я неэффективно потрачу время и буду неэффективным, если так выразиться, продуктом тогда, когда я дойду до цели :)
И даже шаблон Generation Gap был придуман лет 30 назад, меня еще не было на свете, я просто использовал его, как используют очень многие (возможно прозрачно для тебя) для того, чтобы можно было пересоздавать нечто без угрозы потери изменений :)


Отправил Пaшкa в 16:55 09.02.2005[Ответить]
Санька, а вы, к примеру, знаете что такое инкапсуляция? 'Знаете - это не знание опеределения, а знание подходов использования, которые заложены в этом понятии, и целей, которые преследует использование методов, заложенных в этом понятии. Что такое аггрегирование, и чем оно отличается от инкапсуляции? Что такое абстрагирование? И хотя бы раз задумывались ЗАЧЕМ ЭТО ВСЁ придумали? Наверняка ведь, не для тумана?

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


Отправил CAHbKA в 18:19 09.02.2005[Ответить]
Настолько же
это фантазия.
нет принципиальной разницы, в том, что бы брать значение так
a = var.a + Jr. или так a = a . Jr.
именованным объеутом
это фантазия.
не нужно, например, каждый раз
это фантазия.
я _твой_ пример комментировал ДВА раза.
тысячи процедур
это фантазия.
процедур ровно столько же.

Нашел.
это фантазия.
отличий нет.

если сделать
если делать, то в двух реализациях.
и извне это неизменно во всех случаях, потому, что сидит внутри.

и верификация делается 1 раз, если она внешняя.

в своем примере
char *s2 = BMW M5;
пример твой. и как только ты заменишь М5 на М6, пойдёшь в public void CreateOperation() менять М5 на М6

фишка
я не играю в фишки ;-), а логика работы с сущностями лежит в БД и заранее известны действия, все возможные действия, над сущностями (из SQLХХ и описания расширений)

конечно, удобнее просто присваивать неприсвояемое, кто же с этим будет спорить ;)

подход vs объектный :) это меня не интересует.
я неоднократно пытался понять пользу lite, но её не вижу.
поглядевши на примеры кода на C#, пользы я не увидел, заподозрил её наличие в sql-логике. там она наверняка когда-то и появится. а stored procedures с инсертами, селектами и апдейтами внутри несут очень смутную пользу. Выигрышь 1 часа кодинга, когда с другой стороны стоимость в два раза выше, не только сомнителен, но и просто проигрыш. ;)

процедурной надстройки в .NET просто
это малоинтересный момент. процедурная надстройка к базе, конечно. то, откуда берется в .нет процедура выполнить_любой_sql

30 лет
сначала думать, потом делать начали гораздо раньше, мне кажется


Отправил CAHbKA в 18:32 09.02.2005[Ответить]
Пашка, вы демагог.
я придерживаюсь в данном случае не методологии или идей, а оригинального вопроса.
морфология вопроса такова: из взгляда на пример кода (совсем не интересный код, к слову), родилось подозрение, что в единственном нужном месте (работа с БД) оно неэффективно. А когда выяснилось (так показали), что работа с базой, это не работа, а работа (разница в кавычках), вопрос трансформировался в пользу lite вообще. это случилось на второй итерации. это, мне кажется, естественная и ненадуманная трансформация. всё.


Отправил CAHbKA в 18:54 09.02.2005[Ответить]
э. предлагаю с моей стороны поставить точку в дискуссии (выйти:). поскольку варианты ответов на мой вопрос я в состоянии вылущить из текста сам. и можно записать меня в противники прогресса, в ретрограды, в ..., и т.д и т.п. на выбор желающих :)
однако по сю пору думаю - овчинка выделки не стоила


Отправил Patrol в 18:58 09.02.2005[Ответить]
>>(работа с БД) оно неэффективно
Вот это уже по теме ;)
Почему неэфективна? Можешь объяснить?


>>нет принципиальной разницы, в том, что бы брать значение так a = var.a + Jr. или так a = a . Jr.

Разницы как брать - нет :) А как использовать - есть.
Для того, чтобы получить информацию о продукте и передать ее дальше в одном случае программисту необходимо рисовать руками 20 переменных и дальше передавать в процедуру с 20-ю параметрами, где примать 20 параметров, изменять один и передавать снова в процедуру с 20-ю параметрами, которая их все сохранит.
Во втором случае все эти параметры в количестве инкапсулированы в объекте, код написан 1 раз, функции принимают 1 параметр типа этого объекта. Т.о. при каком-либо изменении (например, мы решим, что все тексты должны быть отображены ЧеРеДуЮщИмСя регистром), мы просто изменим реализацию необходимых свойств объекта. В противном случае, нам придется несколько мест поправить.

Но вопрос, как мы выяснили, не в процедурной/объектной ориентации. Ибо иной, чем объектная, в .NET не предусмотрена. Поэтому - только так ;)

>>не нужно, например, каждый раз
>>это фантазия.
Докажи?

>>это фантазия.
>>процедур ровно столько же.
Нет. Далеко и очень далеко не всегда.
Либо докажи обратное.

>>Нашел.
>>это фантазия.
>>отличий нет.
Это фантазия.
Отличия есть.
Либо аргументируй.

>>в своем примере
>>char *s2 = BMW M5;
>>пример твой. и как только ты заменишь М5 на М6, пойдёшь в public void CreateOperation() менять М5 на М6

Угу. Я сделаю следующее:


Vehicle Car = new Vehicle(id);
Car.Title = value;
Car.Save();

Вместо того, чтобы написать код типа:
char *s2;
if(value != null && value != ) {
exec_sql(UPDATE Vehicles SET Title=+value+ WHERE Id=+id);
}

>>откуда берется в .нет процедура выполнить_любой_sql
Ниоткуда. В .NET у программиста нет возможности сделать процедуру. Там нет такого понятия, как процедура.
Есть понятие функция и любая функция суть метод какого-либо объекта.
Очень давно. В конечном итоге объект .NET, отвечающий за отдачу команды SQL-серверу, юзает COM+, который по определению тоже объект, вызывая его метод и отдавая туда параметры. COM+ взаимодействует с SQL Server (у которого внутри тоже одни объекты, ибо он написан не процедурным способом), который и возвращает результат в COM+, а тот маршаллит его в .NET..
А вот откуда взялись эти сказки про процедуры в .NET Framework я не знаю. :)
Для доступа к SQL Server используются объекты SqlConnection, SqlCommand, SqlDataReader и их методы :)
Предлагаю забыть мифы про магическую процедуру exec_sql() или как там ее. Как и про процедуры вообще :)

Но вопрос остается открыт: почему конкретно неэффективна работа с БД и как ее сделать эффективнее? :)



Отправил CAHbKA в 20:21 09.02.2005[Ответить]
я не утверждал, а заподозрил.

про числа 20, 50 и т.п.
ничего, если я в качестве примера приведу man DBI ? ну чтобы раз и навсегда покончить с ними? (сразу оговорюсь, что при всей объектности это в общем процедурщина)
> while (my @data = $cursor->fetch) {
ничего, если к выражению 1 раз, 1 параметр я дам ссылку? http://codegen.perignator.com/howtouse.html
на страничке показаны примеры. в частности с заветным М5, т.е. я предлагаю, в связи с выражением 1 раз, взглянуть на реализацию CreateOperation(), GetOperation() и DeleteOperation()

отличий нет по всем пунктам. еще раз отсылаю к страничке http://codegen.perignator.com/howtouse.html
на этот раз смотреть на декларации CreateOperation(), GetOperation() и DeleteOperation(). о не принципиальности внутренностей при одинаковых декларациях при разных подходах надо?

и действительно, вопрос, как мы выяснили, не в процедурной/объектной ориентации
поэтому я был несколько удивлён от того, что приходилось продираться через неуместную, как теперь выяснилось, агитацию и спичи.

Car.Title = value
а я всегда буду делать a = normalize(b) и всё это внутри CreateOperation()
И?!!!

ну Лёш, процедура это только слово.
ну нету и нету, есть API низкоуровневое, оно обязано линковаться со всем на свете. значит где-то есть. это фигня, на самом деле.

по поводу мифов - предлагаю ознакомиться с документацией.
я использую API (1 штука) чтобы делать это, от запуска куска кода, до вызова процедур, функций, сиквенсов и т.п.
DBI делает это: prepare(что угодно)/execute
да и printf(...) делает это, а он уже дедушка :)

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


Отправил Patrol в 17:56 14.02.2005[Ответить]
Сорри, что долго не овечал - лежал болел ;)

По поводу ООП я спорить больше не стану. Если интересно - заведи другой топик ;)
Пока давай остановимся на том, что:
а) .NET - объектно-ориентированная среда
б) 99.8% .NET-программистов используют объектно-ориентированный подход
с) Таковы рекомендации самих разработчиков .NET
д) Генератор расчитан только на эти 99.8%.

Далее. Возможно, ты посмотрел страничку и понял, будто я предлагаю для генерированного кода использовать в программе методы CreateOperation(), GetOperation() и DeleteOperation() ?
Это не так. Сами методы - это просто декларация, они не генерируются и, естественно, в таком виде никогда никто не пишет.
Методы-примеры написаны только для того, чтобы показать как использовать сгенерированные классы. И только. И сделаны только для того, чтобы было немного читабельнее. Если в этом корень непонимания - то, Саш, скажи как ты это понял - я перепишу хелп. Возможно и правда что-то не додумал.

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


Отправил CAHbKA в 20:16 16.02.2005[Ответить]
Лёш, я прошу пардону, но внутреннее ощущение у меня такое, что всё, что я говорил, я повторил не по разу, поворачивая всякий эээ раз чуть эдак. как оно в этом смысле выглядит на самом деле, конечно фик его знает, но желания уже не осталось.
по поводу ООП я, и конечно на мой взгляд, не спорил.
когда сказали, что фишка в коде, я сказал, что код гамно. он и есть гамно (aaa.bbb = ccc; aaa.save(); => ничего замечательного). и n раз показать пытался, что дело не в коде. когда сказали, что дело в sql'е, и оказалось что просто стандартные возможности обёрнуты кодом, я сказал, что и sql в таком разе гамно. последнее и сейчас наиболее интересно (и сомнительно). к примеру, если все авто числятся как красные, а оказались черные, сколько запросов потребуется, чтобы поменять у них цвет? у меня подозрение, что с примитивами, меняющими поле не один(а несколько). если я не прав, то есть смысл говорить.
да о чем там расстраиваться. код ты показал, я посмотрел. а смотреть там не на что. повтор, опять на пальцах. у нас УЖЕ есть SQL99 (select, insert, update,...). у нас УЖЕ есть его процедурное расширение. этот акцент на УЖЕ значит только то, что мы сразу(до .NET, до чего угодно) можем делать с нашими сущностями вообще всё, что только можно с ними делать. ни процедурные, ни объектно-ориентированные внешние языки для этого не нужны. а ты показываешь код, где в процедуре сидят простые select или update и говоришь, что фишка тут - ну нонсенс же, слишком это примитивно, дырки от бубла не стоит.

p.s.
выздоравливай!
и не болей больше! :-)


Отправил Patrol в 11:15 17.02.2005[Ответить]
Саша-Саша ;)
Я тоже уже не 1-й раз повторяю: не предлагает сгенерированный код никаких новых возможностей. Совсем никаких.
Все это точно так же делается руками, так же делалось и до .NET и до генератора.
Я с самого начала говорю, что код получается простой, пусть даже примитивный. :)
Основная логика в том, что.. сразу наложу граничные условия, чтобы еще больше тебя не путать.. логика в том, что _обычно_ (практически всегда) программисты _на .NET_, работая с сущностями, отображающимися в базу данных, создают по классу для каждой такой сущности. Такова практика, таковы рекомендации Microsoft при работе с .net, такова логика самого .net (к примеру, типизированный DataSet - это примерно то же самое).
Мы с тобой не будем спорить о том, хорошо это или плохо.

>>(aaa.bbb = ccc; aaa.save(); => ничего замечательного).
Так точно! Это абсолютно ОБЫЧНО. НИЧЕГО действительно нового и замечательного.

Теперь то, зачем же тогда програмка нужна. Да просто для того, чтобы заменить ручной труд. То есть, вместо того, чтобы писать по классу для каждой сущности руками + делать хранимые процедуры, можно просто сгенерировать все это дело.
Естественно, это некоторая только базовая функциональность. Всю дальнейшую реализует программист сам.

Вот и все :) резюме: Генератор генерирует основные классы, которые программист обычно все равно реализует. Просто руками это гораздо дольше...
А уже после идет нормальная работа - расширение функциональности, добавление новых методов, взаимодействие объектов и т.д.. И никто мне не сможет запретить добавить в класс Vehicle еще пару методов для обработки некоторых специфичных массовых операций, скажем. :)

Спасибо, уже даже и на работу вышел ;)


Отправил CAHbKA в 12:59 17.02.2005[Ответить]
таки тогда продолжим, т.е. уточню, о предполагаемых скрытых изъянах ;-)
наш базовый код...
вот в некоторый момент у тебя есть список твоих вииклов, которые числятся, как красные, а фактически черные.
нужно это поправить. код программиста обопрётся на базовый код, и? в итоге случится N вызовов к базе вида update where id=n или будет ОДИН вызов update where id in (id_list)?


Отправил Sleep-Walker в 14:35 17.02.2005[Ответить]
Я так понимаю будет один вызов, тот который нужен... программист, как я понимаю, не опирается на базовый код, а расширяет его... Просто Вы Санька, будете неделю (утрирую) руками писать то, что этот генеретор за несколько минут нагенерит (опять же если правильно понимаю суть продукта)...


Отправил CAHbKA в 14:44 17.02.2005[Ответить]
поскольку _тут_ выше (Естественно, это некоторая только базовая функциональность. Всю дальнейшую реализует программист сам.) прямо сказано о том, что Вы затронули, а тут http://codegen.perignator.com/sqlexample.html показаны примеры кода, и _тут_ еще выше тоже показаны примеры кода, то получается, что понимаете Вы не правильно (опять же если правильно понимаю суть :)

подозреваю, что будет N вызовов update/select :-)


Отправил Sleep-Walker в 22:42 17.02.2005[Ответить]
посмотрел ещё раз... прикинул...
и всё-таки остаюсь при своём мнении... к тому что эта штука нагенерила можно (и нужно) добавляьб всё-что угодно (в том числе и вызов всего одного апдейта), но вот то что эта штука нагенерила, без этой штуки всё равно придцца писать руками.
Другими словами эта штука генерит код, который необходим в 99% случаев, остальное, то что нужно имменно в вашем проекте, пишите руками, как и положено.


Отправил CAHbKA в 10:07 18.02.2005[Ответить]
ну ить ежели понимать это так, то штука и вовсе не нужна. накой, если не используется этот нижний уровень: var.id=15; var.attr=black; var.save(); который в итоге развернётся в update .... set attr=black where id=15; select * from ... where id=15; ... ?

пришлось бы писать не это. пришлось бы писать логику живущую в БД. от этого никуда не деться. :) вопрос то сейчас повернулся уже не о %%, а о том, логика это или фуззи-логика.
а call_моя_сторед_процедура(); это уже аппликейшн


Отправил Patrol в 10:50 18.02.2005[Ответить]
Sleep-Walker прав.
Он сказал то, что я тебе, Саш, говорю уже давно - генератор генерит базовую логику, необходимую практически всегда. И сами классы со свойствами и методами. Это методы Save, Update, Delete, Get, GetList. И все.

Для остального придется написать свой код. Ибо генератор не может и не должен сгенерить тебе готовое приложение :) То есть, в классе Vehicle руками сделать еще один метод, применительно к твоему примеру, например - MassUpdate(..) какой-нибудь.
В нем вызвать нужную хранимую процедуру с нужными параметрами.
И в дальнейшем использовать как-нить типа myCar.MassUpdate(..);

>>пришлось бы писать логику живущую в БД
Ну да, просто добавишь еще одну хранимую процедуру да и все.

Вот и все.. Нормальная ситуация :) Так же могут понадобиться метода Взять 10 случайных машин (для рекламы), да мало ли чего.
Это просто реализуется в классе да и все.

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


Отправил Patrol в 11:00 18.02.2005[Ответить]
>>программист, как я понимаю, не опирается на базовый код, а расширяет его...
И это тоже очень верно :)

базовый код - это набор свойств и методов. Нужен новый метод - просто делаешь новый. Нужно новое свойство - добавляешь свойство. Нужно сделать перегруз существующего метода - никто не запрещает использовать base если надо, но по сути - это все действительно расширение. Никаких универсальных средств доступа к БД не предлагается и не генерируется. Используется (на выбор, галкой при генерации задается) либо неймспейс System.Data.SqlClient (стандартное API, если хочешь ;)), либо Microsoft Sql Helper (с ним гораздо удобнее работать + некоторые вещи он оптимизирует).
Вот с этим и будешь работать, создавая новую функциональность. Повторюсь - генератор не генерит ниаких универсальных методов для обращения к БД.