EF. Концепция использования
От: Аноним  
Дата: 01.10.10 12:32
Оценка:
Использую EF и POCO в своей поделке.

Для генерации POCO классов и класса DataContext использовал "ADO.NET c# POCO Entity Generator" здесь

Написал сервисы которые извлекают данные из базы и возвращают объекты. При этом я не храню объект DataContext (вроде как лучшая практика), т.е. после извлечения данных DataContext диспозится:

class PersonService {
public GetPerson(Guid ID) {
        using (DataContext ctx = new ...) {
                   // ...
                }
     }
 
}


Сами сервисы я тягаю в контроллере, в нем же (котроллере) храню загруженные объекты, обрабатываю их там, что бы потом сохранить. Еще раз: никакой ссылки на DataContext не храню, потому что использую сервисы по указанному выше сценарию.
Нарвался на проблему, что LazyLoad не работает с объектами, у которых DataContext уничтожен. Не беда, сразу гружу нужные данные: Include("..").
Теперь допустим у Person есть Nationality поле, которое я хочу обновить. Nationality соответствует одноименной таблице и находится в связи с Person. Если я меняю значение поля, вываливается ошибка в сгенерированном коде в методе FixupNationality, что DataContext уничтожен. Пока не делал но видимо придется создавать в сервисе метод вида

SetNationality (Person person, Nationality nationality) {
using (DataContext ctx = new ...) {
// a) приаттачить персону
// b) установить ему нацинальность
// c) в Client/Service сценарии пришлось бы наверное вернуть измененную персону
}
}

В общем вопросы следующего характера:
— нормально ли то что я работаю с POCO объктом без сохранения DataContexta
— нормально ли то что для изменения такого поля как Nationality я должен пересоздавать DataContext (ведь я же не использую DataContex при изменении например имени). Смущает концепция.
— может быть стоит отказаться от генерированных классов или модифицировать генерация, что бы исключить проверку консистенции данных
— может я вообще неправильно подошел и надо хранить ссылку на DataContext (правда тогда совершенно непонятно можно работать с ним в n-tier сценариях)

Спасибо за советы
Re: EF. Концепция использования
От: HowardLovekraft  
Дата: 01.10.10 13:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Нарвался на проблему, что LazyLoad не работает с объектами, у которых DataContext уничтожен

О каком LazyLoad может идти речь при использовании POCO?

А>Теперь допустим у Person есть Nationality поле, которое я хочу обновить. Nationality соответствует одноименной таблице и находится в связи А>с Person. Если я меняю значение поля, вываливается ошибка в сгенерированном коде в методе FixupNationality, что DataContext уничтожен

Т.е. есть POCO вида:
public class Nationality
{
}

public class Person
{
  public Nationality Nationality { get; set; }
}

и при выполнении кода на клиенте:
person.Nationality = new Nationality { ... };

вы получаете ошибку?

А>В общем вопросы следующего характера:

А>- нормально ли то что я работаю с POCO объктом без сохранения DataContexta
Да.
Упрощенно, работа с POCO в n-tier строится по такому сценарию:
1. В сервисе вытащили из базы граф объектов и вернули его клиенту (соответственно, выбросили контекст и, следовательно, отсоединили от него полученный граф).
2. На клиенте выполнили изменения, которые граф объектов запомнил (self-tracking).
3. Вернули граф объектов на сервер и одали его вновь созданному контексту.
4. Контекст сам, на основании сохраненных изменений в графе, выполняет присоединение объектов к контексту, меняет их состояние в контексте и сохраняет изменения.
5. Опционально граф объектов отправляется обратно клиенту (с обновленными значениями identity и calculated свойств).

А>- нормально ли то что для изменения такого поля как Nationality я должен пересоздавать DataContext (ведь я же не использую DataContex при изменении например имени). Смущает концепция.

По идее, вы меняете Nationality на клиенте. Там контекста вообще нет и он там на фиг не нужен.
Либо я вас не понял.

А>- может быть стоит отказаться от генерированных классов или модифицировать генерация, что бы исключить проверку консистенции данных

Отказаться от генерации можно, если модель очень простая. В противном случае руками писАть очень много.
Association fixup — штука тоже полезная и тоже избавляет от ручной работы.
Идеальный готовый кодогенератор пока не встретился. Может, хреново искал.

А>- может я вообще неправильно подошел и надо хранить ссылку на DataContext (правда тогда совершенно непонятно можно работать с ним в n-tier сценариях)

См. список выше.
Нет, DataContext хранить не нужно. Выполнили свой unit of work (считали/записали граф) — выбросили контекст.
Re[2]: EF. Концепция использования
От: Аноним  
Дата: 01.10.10 13:22
Оценка:
А>>Нарвался на проблему, что LazyLoad не работает с объектами, у которых DataContext уничтожен
HL>О каком LazyLoad может идти речь при использовании POCO?

Может и даже работает, но при условии что объект создан при помощи контекста, или в него добавлен. Runtime, насколько я понимаю, подменяет его прокси объектом. Кстати должна быть включена опция: this.ContextOptions.LazyLoadingEnabled = true;

А>>Теперь допустим у Person есть Nationality поле, которое я хочу обновить. Nationality соответствует одноименной таблице и находится в связи А>с Person. Если я меняю значение поля, вываливается ошибка в сгенерированном коде в методе FixupNationality, что DataContext уничтожен

HL>Т.е. есть POCO вида:
HL>
HL>public class Nationality
HL>{
HL>}

HL>public class Person
HL>{
HL>  public Nationality Nationality { get; set; }
HL>}
HL>

HL>и при выполнении кода на клиенте:
HL>
HL>person.Nationality = new Nationality { ... };
HL>

HL>вы получаете ошибку?

Совершенно верно.

А>>В общем вопросы следующего характера:

А>>- нормально ли то что я работаю с POCO объктом без сохранения DataContexta
HL>Да.
HL>Упрощенно, работа с POCO в n-tier строится по такому сценарию:
HL>1. В сервисе вытащили из базы граф объектов и вернули его клиенту (соответственно, выбросили контекст и, следовательно, отсоединили от него полученный граф).
HL>2. На клиенте выполнили изменения, которые граф объектов запомнил (self-tracking).
HL>3. Вернули граф объектов на сервер и одали его вновь созданному контексту.
HL>4. Контекст сам, на основании сохраненных изменений в графе, выполняет присоединение объектов к контексту, меняет их состояние в контексте и сохраняет изменения.
HL>5. Опционально граф объектов отправляется обратно клиенту (с обновленными значениями identity и calculated свойств).

Ну тут мне еще self-tracking надо поковырять. Еще не добрался

А>>- нормально ли то что для изменения такого поля как Nationality я должен пересоздавать DataContext (ведь я же не использую DataContex при изменении например имени). Смущает концепция.

HL>По идее, вы меняете Nationality на клиенте. Там контекста вообще нет и он там на фиг не нужен.
HL>Либо я вас не понял.

Я тоже так думал, но сгенерированные POCO классы имеют логкику, для поддержания консистенции объектов. Так например при утановки национальности эта логика устанавливает значение FK; старый Nationality Объект теряет ссылку на персону, и в новой национальности устанавливается ссылка на персону Nationality.Person = Person. Эта логика затрагивает контекст и вызвает исключение

А>>- может быть стоит отказаться от генерированных классов или модифицировать генерация, что бы исключить проверку консистенции данных

HL>Отказаться от генерации можно, если модель очень простая. В противном случае руками писАть очень много.
HL>Association fixup — штука тоже полезная и тоже избавляет от ручной работы.
HL>Идеальный готовый кодогенератор пока не встретился. Может, хреново искал.

А>>- может я вообще неправильно подошел и надо хранить ссылку на DataContext (правда тогда совершенно непонятно можно работать с ним в n-tier сценариях)

HL>См. список выше.
HL>Нет, DataContext хранить не нужно. Выполнили свой unit of work (считали/записали граф) — выбросили контекст.
Ок, учту.

Кстати указанный мною сценарий по установке национальности работает, но сильно смущает. Я сейчас поковыряю self-traking объкты и подумаю как его у себя применить.
Спасибо за ответы
Re[3]: EF. Концепция использования
От: HowardLovekraft  
Дата: 01.10.10 13:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Может и даже работает, но при условии что объект создан при помощи контекста, или в него добавлен

Речь шла о графе объектов, который уже передан клиенту. Там контекста нет. И lazy loading нет.
Зачем lazy loading на сервисе, при построении графа, который будет отправляться за пределы этого сервиса, я х.з.
Обычно метод сервиса, которому нужно отдать граф, четко знает, что и на какую глубину загружать. Хотя, может быть, я не сталкивался с такими сценариями.

А>Совершенно верно.

А>Ну тут мне еще self-tracking надо поковырять. Еще не добрался
А>Я тоже так думал, но сгенерированные POCO классы имеют логкику, для поддержания консистенции объектов. Так например при утановки национальности эта логика устанавливает значение FK; старый Nationality Объект теряет ссылку на персону, и в новой национальности устанавливается ссылка на персону Nationality.Person = Person. Эта логика затрагивает контекст и вызвает исключение
Использование POCO нужно для persistence ignorance.
Наличие в коде POCO какой-либо ссылки на сборки EF — это нарушение persistence ignorance, которое лишает смысла использование POCO.
Association fixup в коде POCO ("логика для поддержания консистенции объектов") — это нормально.
Association fixup в коде POCO, использующий контекст — это странно.
Я не смотрел на шаблоны, которые вы используете. Но, если они действительно генерируют fixup-код с использованием контекста, выбростье их.

А>Кстати указанный мною сценарий по установке национальности работает, но сильно смущает.

Еще бы. Ведь вы фактически выполняете руками то, что контекст должен делать автоматически.
Суть self tracking — объект хранит минимально-необходимую информацию о своих изменениях, а контекст умеет этой информацией правильно пользоваться.
Посмотрите хотя бы на те шаблоны, которые идут вместе со студией.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.