Может быть, и здесь.
Все равно что-то мне не нравится в таком подходе. Может быть, он и проще, но по логике... Для чего, спрашивается, создаются все эти Entities? Что мешает работать напрямую, скажем, c DataSet? Мы создаем domain model, все-таки исходя из задач, специфичных для предметной области, а не из того, как у нас в БД это хранится. В это-то и соль ORM: в БД своя схема, domain model другая схема, а ORM (или рукописный data access layer, неважно) сопоставляет одно с другим.
По-хорошему, программист должен вообще быть избавлен от деталей, как там у нас данные хранятся.
Допустим, мы пишем магазин. Есть связь вида «категория - продукт». Если мы получаем товары из свойства Products класса Category, логично предположить, что категорию продукта следует брать из свойства Category класса Product, так? А у нас там как Category, так и какой-нибудь CategoryName. Программист, увидя такое, наверняка задастся вопросом (а я бы задался и взялся за декомпилятор) «А как именно мне переместить продукт в другую категорию? Достаточно ли просто поменять CategoryName, или нужно менять свойство Category? А что будет, если я поменяю, скажем, product.Category.Name?»
Чтобы создать ссылку на родителя, необходимо добавлять вот такое извращение, как private int? _parentID. Если в EF можно так не делать, это очень радует. Хотя, казалось бы, сделать код, который, если поле/свойство помечено атрибутами Column и Accociation одновременно, читал/писал бы значение заданного поля для связанной сущности, не так сложно, ан нет...
Какая уж там сильная нагрузка на внутреннем проекте? :)
Нет, дело совсем не в базе. Там была моделька вида «каталог - элементы», соответственно, один-ко-многим. В каждом каталоге EntitySet, в который грузятся лежащие в нем элементы. Так вот, выбиралось все прекрасно, но вот когда делаешь Add() в EntitySet, а потом сохраняешь изменения, возникала проблема. Либо все писалось в базу, но без CatalogID (равным нулю, если точнее), и элемент не выбирался, либо вообще ничего не сохранялось. Проблему обошел, только тупо присваивая item.Catalog = catalog, и после этого вызывая context.Items.InsertOnSubmit(item).
Вот, кстати, еще один, имхо, недостаток Linq to SQL: чтобы прописать Association, необходимо, чтобы в дочернем объекте существовало свойство, хранящее значение идентификатора родителя. С учетом типизации, то есть, EntityRef<> тут не подойдет. Как раз это я и назвал «ограничением Linq на модели предметной области».
>> ограничения, накладываемые на структуру базы данных и модели предметной области
Ну, например, в Linq to SQL поддерживается только модель «одна сущность одна таблица». Разнести данные одной сущности на несколько таблиц уже не получится, что иногда мешает нормализации БД. Наследование тоже только по модели Single Table Inheritance. В EF этих проблемы уже нет.
>> Many-to-many, конечно же поддерживаются
Да, но через задницудополнительную сущность. Тем более странно, что в известных ORM-решениях (в частности, NHibernate, Gentle.Net) это вполне работает и напрямую. Кстати, тут я вас уже не понял: «прямой мэппинг минуя промежуточную таблицу» как это? Как раз и интересен мэппинг через таблицу вида { FirstEntityID, SecondEntityID }, хотя бы потому, что используется едва ли не в каждом проекте.
>> Что такое "система отслеживания изменений в DataContext"
Это внутренняя подсистема Linq to SQL, отслеживающая изменения в объектах, которые были запрошены. По сути, она хранит объект в исходном состоянии и ссылку на тот, который используется вами. При вызове метода SubmitChanges() для DataContext она сравнивает объекты и вносит в базу данных произошедшие изменения. Кроме того, это позволяет осуществлять проверку, не были ли изменены ваши объекты с момента последней их выборки (optimistic concurrency checking).
Подробнее об этом можно посмотреть тут: http://weblogs.asp.net/scottgu/archive/2…
Так вот, этот самый SubmitChanges() у меня вносил изменения в зависимости от фазы Луны. Может быть, я где-то был неправ, но код-то сгенерированный.
Entity Framework, наряду с ASP.NET MVC Framework, одна из интересующих меня вещей. Несмотря на то, что механизм маппинга в ней (посредством трех XML-файлов) немного напрягает.
Linq to SQL я попробовал в паре внутренних проектов, и он вызвал у меня двоякие чувства. С одной стороны, делать запросы через Linq безотносительно к состоянию объектов (выбор из DB или уже загруженной коллекции) удобно, но... с другой стороны, ограничения, накладываемые на структуру базы данных и модели предметной области, отсутствие поддержки many-to-many, несколько странная работа системы отслеживания изменений в DataContext (время от времени изменения в EntitySet'ах ну никак не хотели записываться).
Я надеюсь, Entity Framework будет смотреться намного лучше, тем более, что какие-то его средства (было упомянуто вскользь на Heroes Happen Here) будут включены в SQL Server 2008. К сожалению, пока катастрофически не хватает времени и желания всерьез покопаться с ним.
Еще волнует производительность, ибо база данных обычно нагибается в первую очередь.
Проголосовал за вас.
Если посмотреть на работы, сомнения по поводу законности присуждения вам первого места пропадают сразу:) Искренне желаю вам победы!
P.S.: Результаты голосования фантастические. Хабраэффект? :)
Можно предположить, что любой класс, содержащий виртуальный член (метод, свойство, индексатор или событие) считается виртуальным. Подобно тому, как в C++ были сделаны абстрактные классы.
Я все-таки не до конца осмыслил ваш вопрос :)
Приведенные варианты будут отличаться стек-трейсом. Первый вариант не сохраняет предыдущее состояние стека, поэтому при получении исключения не будет видно, что к нему привело. Во втором варианте все более правильно.
Все равно что-то мне не нравится в таком подходе. Может быть, он и проще, но по логике... Для чего, спрашивается, создаются все эти Entities? Что мешает работать напрямую, скажем, c DataSet? Мы создаем domain model, все-таки исходя из задач, специфичных для предметной области, а не из того, как у нас в БД это хранится. В это-то и соль ORM: в БД своя схема, domain model другая схема, а ORM (или рукописный data access layer, неважно) сопоставляет одно с другим.
По-хорошему, программист должен вообще быть избавлен от деталей, как там у нас данные хранятся.
Допустим, мы пишем магазин. Есть связь вида «категория - продукт». Если мы получаем товары из свойства Products класса Category, логично предположить, что категорию продукта следует брать из свойства Category класса Product, так? А у нас там как Category, так и какой-нибудь CategoryName. Программист, увидя такое, наверняка задастся вопросом (а я бы задался и взялся за декомпилятор) «А как именно мне переместить продукт в другую категорию? Достаточно ли просто поменять CategoryName, или нужно менять свойство Category? А что будет, если я поменяю, скажем, product.Category.Name?»
Чтобы создать ссылку на родителя, необходимо добавлять вот такое извращение, как private int? _parentID. Если в EF можно так не делать, это очень радует. Хотя, казалось бы, сделать код, который, если поле/свойство помечено атрибутами Column и Accociation одновременно, читал/писал бы значение заданного поля для связанной сущности, не так сложно, ан нет...
Нет, дело совсем не в базе. Там была моделька вида «каталог - элементы», соответственно, один-ко-многим. В каждом каталоге EntitySet, в который грузятся лежащие в нем элементы. Так вот, выбиралось все прекрасно, но вот когда делаешь Add() в EntitySet, а потом сохраняешь изменения, возникала проблема. Либо все писалось в базу, но без CatalogID (равным нулю, если точнее), и элемент не выбирался, либо вообще ничего не сохранялось. Проблему обошел, только тупо присваивая item.Catalog = catalog, и после этого вызывая context.Items.InsertOnSubmit(item).
Вот, кстати, еще один, имхо, недостаток Linq to SQL: чтобы прописать Association, необходимо, чтобы в дочернем объекте существовало свойство, хранящее значение идентификатора родителя. С учетом типизации, то есть, EntityRef<> тут не подойдет. Как раз это я и назвал «ограничением Linq на модели предметной области».
Ну, например, в Linq to SQL поддерживается только модель «одна сущность одна таблица». Разнести данные одной сущности на несколько таблиц уже не получится, что иногда мешает нормализации БД. Наследование тоже только по модели Single Table Inheritance. В EF этих проблемы уже нет.
>> Many-to-many, конечно же поддерживаются
Да, но через
задницудополнительную сущность. Тем более странно, что в известных ORM-решениях (в частности, NHibernate, Gentle.Net) это вполне работает и напрямую. Кстати, тут я вас уже не понял: «прямой мэппинг минуя промежуточную таблицу» как это? Как раз и интересен мэппинг через таблицу вида { FirstEntityID, SecondEntityID }, хотя бы потому, что используется едва ли не в каждом проекте.>> Что такое "система отслеживания изменений в DataContext"
Это внутренняя подсистема Linq to SQL, отслеживающая изменения в объектах, которые были запрошены. По сути, она хранит объект в исходном состоянии и ссылку на тот, который используется вами. При вызове метода SubmitChanges() для DataContext она сравнивает объекты и вносит в базу данных произошедшие изменения. Кроме того, это позволяет осуществлять проверку, не были ли изменены ваши объекты с момента последней их выборки (optimistic concurrency checking).
Подробнее об этом можно посмотреть тут: http://weblogs.asp.net/scottgu/archive/2…
Так вот, этот самый SubmitChanges() у меня вносил изменения в зависимости от фазы Луны. Может быть, я где-то был неправ, но код-то сгенерированный.
Entity Framework, наряду с ASP.NET MVC Framework, одна из интересующих меня вещей. Несмотря на то, что механизм маппинга в ней (посредством трех XML-файлов) немного напрягает.
Linq to SQL я попробовал в паре внутренних проектов, и он вызвал у меня двоякие чувства. С одной стороны, делать запросы через Linq безотносительно к состоянию объектов (выбор из DB или уже загруженной коллекции) удобно, но... с другой стороны, ограничения, накладываемые на структуру базы данных и модели предметной области, отсутствие поддержки many-to-many, несколько странная работа системы отслеживания изменений в DataContext (время от времени изменения в EntitySet'ах ну никак не хотели записываться).
Я надеюсь, Entity Framework будет смотреться намного лучше, тем более, что какие-то его средства (было упомянуто вскользь на Heroes Happen Here) будут включены в SQL Server 2008. К сожалению, пока катастрофически не хватает времени и желания всерьез покопаться с ним.
Еще волнует производительность, ибо база данных обычно нагибается в первую очередь.
Если посмотреть на работы, сомнения по поводу законности присуждения вам первого места пропадают сразу:) Искренне желаю вам победы!
P.S.: Результаты голосования фантастические. Хабраэффект? :)
Вот математика на поверку там была не к месту, хватит и (array.Length - 1) / 2.
Про Array.Reverse() даже не задумался.
правильно так:
for(int i = 0, len = (int)Math.Floor((float)((array.Length - 1) / 2)); i <= len; ++i)
...
public string Reverse(string str)
{
char[] array = str.ToCharArray();
char temp;
for (int i = 0, len = Math.Floor((float)((array.Length - 1) / 2); i <= len); ++i)
{
temp = array[i];
array[i] = array[array.Length - (1 + i)];
array[array.Length - (1 + i)] = temp;
}
return new String(array);
}
Можно предположить, что любой класс, содержащий виртуальный член (метод, свойство, индексатор или событие) считается виртуальным. Подобно тому, как в C++ были сделаны абстрактные классы.
Приведенные варианты будут отличаться стек-трейсом. Первый вариант не сохраняет предыдущее состояние стека, поэтому при получении исключения не будет видно, что к нему привело. Во втором варианте все более правильно.