многоклиториальный поиск и паттерн specification

1 765 просмотров
Перейти к первому непрочитанному сообщению

menozz

не прочитано,
27 окт. 2010 г., 02:08:3527.10.2010
– dotnetconf
Доброе утро, коллеги!

1.Хочу задать вопрос по паттерну specification. Кто использовал его
реализацию для многокритериального поиска? Т.е. мне необходимо понять
насколько целесообразно его использование в небольшом проекте, ведь
можно обойтись обычными конструкциями запросов к репозиторию.

2. Где должно происходить создание экземпляров ISpecification и
передача их в репозиторий? В сервисе? Что если существуют такие
экземпляры классов (по кол-ву критериев)

public class ProductByNameSpecification : Specification<Product>
{
public ProductByNameSpecification(string nameToMatch)
: base(p => p.Name == nameToMatch)
{
}
}

В каком слое они должны быть расположены?

3. Не могли бы вы привести ваши тесты использования этого паттерна в
проекте, если они есть.

Спасибо!

Alexander I. Zaytsev

не прочитано,
27 окт. 2010 г., 02:10:1627.10.2010
– dotnetconf
Отличная опечатка в теме;)

27 октября 2010 г. 12:08 пользователь menozz <menoz...@gmail.com> написал:

menozz

не прочитано,
27 окт. 2010 г., 02:29:1227.10.2010
– dotnetconf
навеяно ранним утром ))

On 27 окт, 10:10, "Alexander I. Zaytsev" <hazzik+nos...@gmail.com>
wrote:


> Отличная опечатка в теме;)
>

> 27 октября 2010 г. 12:08 пользователь menozz <menozgra...@gmail.com>написал:

Alexander Byndyu

не прочитано,
27 окт. 2010 г., 04:52:1527.10.2010
– dotne...@googlegroups.com
По сути, используя LINQ, ты уже применяешь шаблон Specification.

Объект Expression может добавлять в себя условия. Самое простое:

var r = new int{1,2,3};
IQueryable<int> query = r.Where(x => x > 1);
query = query.OrderBy(x=> x);
query = query.Count();
...

Запросы на LINQ находятся в репозитории, сервису их не надо формировать. Нужно у репозитория сразу попросить то, что нужно.

Если остались еще вопросы, то пиши.

27 октября 2010 г. 12:29 пользователь menozz <menoz...@gmail.com> написал:



--
С уважением,
Бындю Александр

Тел.: +7 (904) 305 5263
Сайт: http://www.byndyu.ru
Блог: http://blog.byndyu.ru

menozz

не прочитано,
27 окт. 2010 г., 06:06:3827.10.2010
– dotnetconf
Саша, привет

ок, пусть будет репозиторий.
http://pastebin.com/cpCEnib6

Суть в том, что сюда будут приходить параметры с формы на основании
критериев поиска. Создавать экземпляры спецификации нужно здесь, если
вообще нужно? В моем понимании идея использования ISpecification
заключается в том, чтобы превратить этот репозиторий (я его называю
сервисом) в нечто без linq-выражений, чтобы читая методы было понятно
что делается. Там есть метод закоменченный с вариантом создания
ISpecification. Надеюсь, вопрос понятен. Все же хотелось бы посмотреть
на примеры, где действительно необходимо использование шаблона
спецификации (в рамках проекта побольше, хотя бы тестики
использования)

Спасибо.


On 27 окт, 12:52, Alexander Byndyu <alexander.byn...@gmail.com> wrote:
> По сути, используя LINQ, ты уже применяешь шаблон Specification.
>
> Объект Expression может добавлять в себя условия. Самое простое:
>
> var r = new int{1,2,3};
> IQueryable<int> query = r.Where(x => x > 1);
> query = query.OrderBy(x=> x);
> query = query.Count();
> ...
>
> Запросы на LINQ находятся в репозитории, сервису их не надо формировать.
> Нужно у репозитория сразу попросить то, что нужно.
>
> Если остались еще вопросы, то пиши.
>

> 27 октября 2010 г. 12:29 пользователь menozz <menozgra...@gmail.com>написал:
>
>
>
> > навеяно ранним утром ))
>
> > On 27 окт, 10:10, "Alexander I. Zaytsev" <hazzik+nos...@gmail.com<hazzik%2Bnos...@gmail.com>

Alexander Byndyu

не прочитано,
27 окт. 2010 г., 08:36:5027.10.2010
– dotne...@googlegroups.com
Твой TaskService - это чистый репозиторий. А если разбить каждый его метод на отдельный класс запроса, то получится Query из CQRS.

Я не увидел, где тебе надо хитро собирать объект запроса (ISpecification) для выборки данных. Все вполне прозрачно написано на Linq.

Опиши, пожалуйста, корни проблемы, из-за которой ты начал смотреть в сторону рефакторинга и использовать шаблона Specification

27 октября 2010 г. 16:06 пользователь menozz <menoz...@gmail.com> написал:

menozz

не прочитано,
27 окт. 2010 г., 08:41:0027.10.2010
– dotnetconf
Проблему уже описал. В презентере разберуться поля с формы, содержащие
необходимые слова для поиска. Все это должно слиться в один
expression, который я отправлю в _repository<Task>. Это еще не
реализовано. Полей будет эдак 15 в сумме.

On 27 окт, 16:36, Alexander Byndyu <alexander.byn...@gmail.com> wrote:
> Твой TaskService - это чистый репозиторий. А если разбить каждый его метод
> на отдельный класс запроса, то получится Query из CQRS.
>
> Я не увидел, где тебе надо хитро собирать объект запроса (ISpecification)
> для выборки данных. Все вполне прозрачно написано на Linq.
>
> Опиши, пожалуйста, корни проблемы, из-за которой ты начал смотреть в сторону
> рефакторинга и использовать шаблона Specification
>

> 27 октября 2010 г. 16:06 пользователь menozz <menozgra...@gmail.com>написал:

> > <hazzik%2Bnos...@gmail.com <hazzik%252Bnos...@gmail.com>>

Alexander Byndyu

не прочитано,
27 окт. 2010 г., 09:00:3527.10.2010
– dotne...@googlegroups.com
Я бы сделал так http://pastebin.com/arFGXV5B

Часть кода пропущена, но думаю суть должна быть понятна.

27 октября 2010 г. 18:41 пользователь menozz <menoz...@gmail.com> написал:

menozz

не прочитано,
27 окт. 2010 г., 09:32:3427.10.2010
– dotnetconf
Ну, в более упрощенной форме это сейчас реализовано, правда не в этом
проекте.
Основной недостаток - необходима каждая новая реализация класса под
новую форму с новыми параметрами, т.к. присутствует linq выражения,
связанные с конкретной entity.
Почему просиходит валидация параметров в классе, составляющий общий
query? Ясно, что быстро написал, но вопрос принципиальный.
существование реализации null-specification по идее снимает этот
вопрос. Также вопрос по IOC - для новой реализации класса поиска
дополнительная инъекция. Там итак он работает не быстро )

Сейчас, например в реализации репозитория типа T:

public T FindBy(ISpecification<T> criteria)
{
return criteria.SatisfyingEntityFrom(All());
}

public IQueryable<T> FilterBy(ISpecification<T> criteria)
{
return criteria.SatisfyingEntitiesFrom(All());
}
Т.е. ISpecification не зависит от типа entity и все linq выражения
будут содержаться в соответствующих мини-классах. А имя будет
соответствовать его назначению.

В любом случае, огромное спасибо за потраченное время на составление
кода

Конструкция
в классе репозитория снимает эту проблему. Я могу вынести все
On 27 окт, 17:00, Alexander Byndyu <alexander.byn...@gmail.com> wrote:
> Я бы сделал такhttp://pastebin.com/arFGXV5B


>
> Часть кода пропущена, но думаю суть должна быть понятна.
>

> 27 октября 2010 г. 18:41 пользователь menozz <menozgra...@gmail.com>написал:

> > > > <hazzik%2Bnos...@gmail.com <hazzik%252Bnos...@gmail.com> <
> > hazzik%252Bnos...@gmail.com <hazzik%25252Bnos...@gmail.com>>>

menozz

не прочитано,
12 нояб. 2010 г., 04:33:2512.11.2010
– dotnetconf
ну, вот так получилась спецификация:

http://webtasks.codeplex.com/SourceControl/changeset/view/2226#43695
и вот так ее использует сервис:
http://webtasks.codeplex.com/SourceControl/changeset/view/2226#43972

вобщем-то вполне читабельно )

Спасибо!

Alexander Byndyu

не прочитано,
12 нояб. 2010 г., 09:08:0812.11.2010
– dotne...@googlegroups.com
Я не понял зачем используются операторы & и |, а не && и ||

И еще вместо проверок на null можешь использовать шаблон Null Object, т.е. сделать NullSpecification, которая ничего не делает.

12 ноября 2010 г. 14:33 пользователь menozz <menoz...@gmail.com> написал:

Alexander Byndyu

не прочитано,
12 нояб. 2010 г., 09:11:0312.11.2010
– dotne...@googlegroups.com
Еще глянул пару классов в домене. 

Ты сделал доменные функции добавления и удаления менеджера, который должны инкапсулировать список Managers, при этом сам список сделан публичным:

public virtual IList<Account> Managers { get; protected set; }

12 ноября 2010 г. 14:33 пользователь menozz <menoz...@gmail.com> написал:
ну, вот так получилась спецификация:

menozz

не прочитано,
12 нояб. 2010 г., 09:29:5612.11.2010
– dotnetconf


Я не понял зачем используются операторы & и |, а не && и ||

Operators Overloadability

+, -, *, /, %, &, |, <<, >> All C# binary operators can be overloaded.

+, -, !, ~, ++, -, true, false All C# unary operators can be
overloaded.

==, !=, <, >, <= , >= All relational operators can be overloaded,
but only as pairs.


&&, || They can't be overloaded

Я бы рад, но они перегружены в Generic specification

>
> И еще вместо проверок на null можешь использовать шаблон Null Object, т.е.
> сделать NullSpecification, которая ничего не делает.
>

> 12 ноября 2010 г. 14:33 пользователь menozz <menozgra...@gmail.com> написал:

> > > > > hazzik%252Bnos...@gmail.com <hazzik%25252Bnos...@gmail.com> <
> > hazzik%25252Bnos...@gmail.com <hazzik%2525252Bnos...@gmail.com>>>>

> ...
>
> продолжение >>

Alexander Byndyu

не прочитано,
12 нояб. 2010 г., 09:34:3012.11.2010
– dotne...@googlegroups.com
Интересная идея, но не очевидная для того, кто читает код.

12 ноября 2010 г. 19:29 пользователь menozz <menoz...@gmail.com> написал:

menozz

не прочитано,
12 нояб. 2010 г., 09:35:0212.11.2010
– dotnetconf
но, ведь, он protected set. Разве этого не достаточно? В смысле, зачем
его полностью скрывать и реализовывать через IEnumeration<Account>?
Вообще, очень интересно, Саша, услышать твои комментарии по
организации кода.
Был бы рад если бы нашел время для более детального просмотра.
Спасибо.

Про Null, Ты прав, но пока руки не дошли до создания NullAccount и для
остальных.. [посыпая голову пеплом..]

On 12 ноя, 17:11, Alexander Byndyu <alexander.byn...@gmail.com> wrote:
> Еще глянул пару классов в домене.
>

> Например, класс Accounthttp://webtasks.codeplex.com/SourceControl/changeset/view/2226#43525.


> Ты сделал доменные функции добавления и удаления менеджера, который должны
> инкапсулировать список Managers, при этом сам список сделан публичным:
>
> public virtual IList<Account> Managers { get; protected set; }
>

> 12 ноября 2010 г. 14:33 пользователь menozz <menozgra...@gmail.com> написал:

> > > > > hazzik%252Bnos...@gmail.com <hazzik%25252Bnos...@gmail.com> <
> > hazzik%25252Bnos...@gmail.com <hazzik%2525252Bnos...@gmail.com>>>>

> ...
>
> продолжение >>

menozz

не прочитано,
12 нояб. 2010 г., 09:37:0812.11.2010
– dotnetconf
Согласен, но выигрыш от-того, что саму выборку можно читать по
названиям классов спецификаций мне кажется больше, чем хранить все это
дело жестко в методах репозитория. Кроме того, такая схема будет
тестироваться легко. Мы по отдельности можем протестить каждую
спецификацию

On 12 ноя, 17:34, Alexander Byndyu <alexander.byn...@gmail.com> wrote:
> Интересная идея, но не очевидная для того, кто читает код.
>

> 12 ноября 2010 г. 19:29 пользователь menozz <menozgra...@gmail.com> написал:

> > > > hazzik%25252Bnos...@gmail.com <hazzik%2525252Bnos...@gmail.com> <
> > hazzik%2525252Bnos...@gmail.com <hazzik%252525252Bnos...@gmail.com>>>>>


>
> > > > > > > > > > > wrote:
> > > > > > > > > > > > Отличная опечатка в теме;)
>
> > > > > > > > > > > > 27 октября 2010 г. 12:08 пользователь menozz <
> > > > > > > menozgra...@gmail.com
> > > > > > > > > > > >написал:
>
> > > > > > > > > > > > > Доброе утро, коллеги!
>
> > > > > > > > > > > > > 1.Хочу задать вопрос по паттерну specification. Кто
> > > > > > > использовал
> > > > > > > > > его
> > > > > > > > > > > > > реализацию для многокритериального поиска? Т.е. мне
> > > > необходимо
> > > > > > > > > понять
>

> ...
>
> продолжение >>

Alexander I. Zaytsev

не прочитано,
12 нояб. 2010 г., 09:38:2012.11.2010
– dotnetconf
Нашел закоментированный NullSpecification

Там принципиальная ошибка: Expressioin должен возвращать x=>true;

12 ноября 2010 г. 19:35 пользователь menozz <menoz...@gmail.com> написал:

Alexander I. Zaytsev

не прочитано,
12 нояб. 2010 г., 09:43:3412.11.2010
– dotnetconf
Хотя нет. Я не прав. В зависимости от контекста: при использовании внутри Or должен возвращать false, внутри And true 

лучше переопределить | и & в NullSpecification (лучше через виртуальную перегрузку методов а не операндов)




12 ноября 2010 г. 19:38 пользователь Alexander I. Zaytsev <hazzik...@gmail.com> написал:

menozz

не прочитано,
12 нояб. 2010 г., 09:44:2812.11.2010
– dotnetconf
не понял, почему true?

в том смысле, что issatisfied говорит о том, что удовлетворяет ли
объект условию. Если нет, то в группе условных операторов он
пропускается.

On 12 ноя, 17:38, "Alexander I. Zaytsev" <hazzik+nos...@gmail.com>
wrote:
> Нашел закоментированный NullSpecificationhttp://webtasks.codeplex.com/SourceControl/changeset/view/2226#43517


>
> <http://webtasks.codeplex.com/SourceControl/changeset/view/2226#43517>Там
> принципиальная ошибка: Expressioin должен возвращать x=>true;
>

> 12 ноября 2010 г. 19:35 пользователь menozz <menozgra...@gmail.com> написал:

> > > > hazzik%25252Bnos...@gmail.com
>
> ...
>
> продолжение >>

menozz

не прочитано,
12 нояб. 2010 г., 09:47:4712.11.2010
– dotnetconf
ну, да, можно было... :)
в принципе не хочется лишних слов And Or или еще чего, поэтому оставил
так..

On 12 ноя, 17:43, "Alexander I. Zaytsev" <hazzik+nos...@gmail.com>
wrote:


> Хотя нет. Я не прав. В зависимости от контекста: при использовании внутри Or
> должен возвращать false, внутри And true
>
> лучше переопределить | и & в NullSpecification (лучше через виртуальную
> перегрузку методов а не операндов)
>
> 12 ноября 2010 г. 19:38 пользователь Alexander I. Zaytsev <

> hazzik+nos...@gmail.com <hazzik%2Bnos...@gmail.com>> написал:


>
> > Нашел закоментированный NullSpecification
> >http://webtasks.codeplex.com/SourceControl/changeset/view/2226#43517
>
> > <http://webtasks.codeplex.com/SourceControl/changeset/view/2226#43517>Там
> > принципиальная ошибка: Expressioin должен возвращать x=>true;
>

> > 12 ноября 2010 г. 19:35 пользователь menozz <menozgra...@gmail.com>написал:

> ...
>
> продолжение >>

menozz

не прочитано,
12 нояб. 2010 г., 09:50:0712.11.2010
– dotnetconf
Кстати, спасибо, вам обоим. Летом с DDD познакомился именно по вашим
статьям.

> ...
>
> продолжение >>

menozz

не прочитано,
12 нояб. 2010 г., 09:58:4912.11.2010
– dotnetconf
> лучше переопределить | и & в NullSpecification (лучше через виртуальную
> перегрузку методов а не операндов)

А.., понял твою мысль.. ну, да я его использовал только в одном
случае, а потом вообще удалил, поэтому закоменчен. спасибо, буду иметь
в виду.


> >http://webtasks.codeplex.com/SourceControl/changeset/view/2226#43517


>
> > <http://webtasks.codeplex.com/SourceControl/changeset/view/2226#43517>Там
> > принципиальная ошибка: Expressioin должен возвращать x=>true;
>

> > 12 ноября 2010 г. 19:35 пользователь menozz <menozgra...@gmail.com>написал:

> ...
>
> продолжение >>

menozz

не прочитано,
12 нояб. 2010 г., 10:10:1212.11.2010
– dotnetconf
Я правильно понимаю, что в этом куске:

Account participant = accountRepository.GetAccount(id);
if (participant != null)
{
IList<UniversalModelDDL> models =
View.Participants;
var universalModel = new
UniversalModelDDL(participant.UID, participant.FullName);
if (!models.Contains(universalModel))
{
models.Add(universalModel);
View.Participants = models;
}
}
репозиторий должен вернуть экземпляр NullAccount, если по id не
найден объект?

> ...
>
> продолжение >>

Alexander I. Zaytsev

не прочитано,
12 нояб. 2010 г., 11:12:0412.11.2010
– dotnetconf
Вам виднее. Вообще NullObject нужен для того, чтоб избежать постоянной проверки на null. Если она имеется, то имеет смысл так делать, если нет - то нет.

12 ноября 2010 г. 20:10 пользователь menozz <menoz...@gmail.com> написал:

man in the middle

не прочитано,
12 нояб. 2010 г., 11:15:5112.11.2010
– dotne...@googlegroups.com
Видимо, тут, ключевое слово _постоянной_ :)
ладно, порефакторю чуть-чуть. вряд ли он понадобится..
На мой взгляд, введение в проекте NullObject очень сильно влияет на все слои и пустым поведением должны будут обладать все связанные объекты. Это слишком сильно, в данном случае.

2010/11/12 Alexander I. Zaytsev <hazzik...@gmail.com>

Alexander Byndyu

не прочитано,
12 нояб. 2010 г., 12:49:5112.11.2010
– dotne...@googlegroups.com
Вот здесь есть более подробно http://blog.byndyu.ru/2010/05/domain-driven-design.html

Вкратце, у интерфейса IList есть метод Add(), который открывает добавление менеджеров без доменной логики, которая содержится в AddManager и RemoveManager.

12 ноября 2010 г. 19:35 пользователь menozz <menoz...@gmail.com> написал:

menozz

не прочитано,
13 нояб. 2010 г., 02:16:1013.11.2010
– dotnetconf
С этим абсолютно согласен. Накосячил...(вернее изначально сделал, как
описано в твоей статье), но в связи с тем, что мне понадобилось
составить запрос к внутренней сущности (для спецификации) переделал в
public. Вот проблема в классе Task:

инкапсулируем:
protected IList<Participant> participants;

паблик свойство:
public virtual IEnumerable<Account> Participants
{
get { return participants.Select(x => x.Login); }

}


class ContainsInParticipantFullName : Specification<Task>
{
readonly string _nameToMatch;
public ContainsInParticipantFullName(string nameToMatch)
{
_nameToMatch = nameToMatch;
}
public override System.Linq.Expressions.Expression<Func<Task,
bool>> IsSatisfiedBy()
{
//return x => x.ParticipantEntityList.Any(p =>
p.Login.FullName.Contains(_nameToMatch)); раньше так
return x => x.Participants.Any(p =>
p.Login.FullName.Contains(_nameToMatch)); //здесь проблема.

^^^^^^^^^^^^^
}
}

как составить запрос к IEnumerable паблик свойству, чтобы бд смогла
интерпретировать нормально?


On 12 ноя, 20:49, Alexander Byndyu <alexander.byn...@gmail.com> wrote:
> Вот здесь есть более подробноhttp://blog.byndyu.ru/2010/05/domain-driven-design.html


>
> <http://blog.byndyu.ru/2010/05/domain-driven-design.html>Вкратце, у
> интерфейса IList есть метод Add(), который открывает добавление менеджеров
> без доменной логики, которая содержится в AddManager и RemoveManager.
>

> 12 ноября 2010 г. 19:35 пользователь menozz <menozgra...@gmail.com> написал:

> > > > hazzik%25252Bnos...@gmail.com <hazzik%2525252Bnos...@gmail.com> <
> > hazzik%2525252Bnos...@gmail.com <hazzik%252525252Bnos...@gmail.com>>>>>

menozz

не прочитано,
13 нояб. 2010 г., 03:02:4413.11.2010
– dotnetconf
Ой, прошу прощения. С тем все в порядке, вот здесь

public virtual IEnumerable<Task>
GetTasksByDepartmentForOtherRole(Account account,

Department department)
{
return _repository.FilterBy(x => x.Status ==
TaskStatus.InProgress)
.Where(x => x.Department.WebPath ==
department.WebPath)
.Where(x => x.Owner == account || x.Participants.Any(p =>
p == account));

^^^^^^^^^^^^^^^^^ не замапленное свойство. нормально работает только с
замапленным свойством
}

Как это побороть, подскажите пожалуйста?

> ...
>
> продолжение >>

menozz

не прочитано,
14 нояб. 2010 г., 16:10:3514.11.2010
– dotnetconf
Удалось победить, если замапить свойство IEnumerable в режиме чтения.
Т.е.получается двойной маппинг одной таблицы.
HasMany(x => x.Participants)
.KeyColumns.Add("IDtask")
.Inverse()
.Cascade.LazyLoad()
.AsBag().Access.Property().ReadOnly();



HasMany<Participant>(Reveal.Property<Task>("_participants"))
.KeyColumns.Add("IDtask")
.Inverse()
.Cascade.AllDeleteOrphan().LazyLoad()
.AsBag();
Таким образом получаем:

protected virtual IList<Participant> _participants { get; set;}

и

public virtual IEnumerable<Account> Participants
{
get
{

return _participants.Select(x => x.Login);
}
protected set{}
}

и переписанный класс спецификации под использование Participants.
Насколько безграмотно существование protected set в последней
проперти[сеттер нужен для маппинга, само свойство для составления linq
condition]? Может есть более элегантное решение?

On 12 ноя, 20:49, Alexander Byndyu <alexander.byn...@gmail.com> wrote:
> Вот здесь есть более подробноhttp://blog.byndyu.ru/2010/05/domain-driven-design.html
>

> <http://blog.byndyu.ru/2010/05/domain-driven-design.html>Вкратце, у
> интерфейса IList есть метод Add(), который открывает добавление менеджеров
> без доменной логики, которая содержится в AddManager и RemoveManager.
>

> 12 ноября 2010 г. 19:35 пользователь menozz <menozgra...@gmail.com> написал:

> > > > > > > hazzik%252Bnos...@gmail.com <hazzik%25252Bnos...@gmail.com> <
>
> ...
>
> продолжение >>

Alexander Byndyu

не прочитано,
14 нояб. 2010 г., 23:07:3414.11.2010
– dotne...@googlegroups.com
Можно добавить в маппинг:
.Access.ReadOnlyPropertyThroughCamelCaseField()

15 ноября 2010 г. 2:10 пользователь menozz <menoz...@gmail.com> написал:

Alexander I. Zaytsev

не прочитано,
15 нояб. 2010 г., 01:19:1115.11.2010
– dotne...@googlegroups.com
Саня, .Access.ReadOnlyPropertyThroughCamelCaseField() ему все поломает:)

В данном случае protected set это нормально, но лучше его сделать приватным (NH по-фигу на модификатор доступа)

15 ноября 2010 г. 9:07 пользователь Alexander Byndyu <alexande...@gmail.com> написал:

menozz

не прочитано,
15 нояб. 2010 г., 01:21:0315.11.2010
– dotnetconf
Спасибо, Коллеги! )

On 15 ноя, 09:19, "Alexander I. Zaytsev" <hazzik+nos...@gmail.com>
wrote:


> Саня, .Access.ReadOnlyPropertyThroughCamelCaseField() ему все поломает:)
>
> В данном случае protected set это нормально, но лучше его сделать приватным
> (NH по-фигу на модификатор доступа)
>
> 15 ноября 2010 г. 9:07 пользователь Alexander Byndyu <

> alexander.byn...@gmail.com> написал:


>
> > Можно добавить в маппинг:
> > .Access.ReadOnlyPropertyThroughCamelCaseField()
>

> > 15 ноября 2010 г. 2:10 пользователь menozz <menozgra...@gmail.com>написал:

> ...
>
> продолжение >>

Ответить всем
Отправить сообщение автору
Переслать
0 новых сообщений