EDM -> POCO -> WCF (.NET4) Но передача коллекций приводит к тому, что IsReadOnly имеет значение TRUE - PullRequest
3 голосов
/ 19 марта 2010

Хорошо, это может звучать немного «неортодоксально», но ... используя VS2010 и новый шаблон POCO t4 для Entity Framework ( Пошаговое руководство. Шаблон POCO для Entity Framework ), я могу создать хороший ПОКО годов. Затем я могу использовать эти POCO (как DTO) в сервисе WCF, по сути, проходя от EDM до клиента. Вроде то, что делают эти ребята ( POCO с EF 4.0 и WCF 4.0 ), за исключением того, что все генерируется автоматически. Я понимаю, что сущность и DTO «должны быть разными», но в этом случае я работаю с клиентом и сервером, и есть некоторые реальные преимущества наличия DTO в модели и ее автоматической генерации.

Моя проблема в том, что при передаче сущности, имеющей отношение, клиентская коллекция (ICollection) имеет установленное значение только для чтения, поэтому я не могу манипулировать этим отношением. Например, при получении существующего Заказа я не могу добавить продукт в клиентскую часть коллекции Products ... коллекция Products доступна только для чтения.

Я бы предпочел выполнить кучу «редактирования заказа» на стороне клиента, а затем отослать обновленный заказ обратно, а не совершать десятки обращений к серверу (например, AddProductToOrder (product)). Я также предпочел бы, чтобы между Entity и DTO не было ничего общего. Так что в целом это выглядит хорошо для меня ... за исключением части только для чтения.

Есть ли решение, или это слишком много против зерна SOA?

Ответы [ 2 ]

0 голосов
/ 14 сентября 2010

Решение "La Mouette" работает с ссылочными сборками:

У нас та же проблема, и мы заметили, что для свойства IsReadOnly установлено значение true после сериализации wcf (до этого значение свойства было равно false).

Мы ссылались на сборки. В обходном пути, предложенном «la mouette», используйте параметризованный конструктор, но в нашем шаблоне POCO его нет.

Мы изменили tt, создав пустой конструктор, чтобы вызывать базовый конструктор, и это делает свое дело.

0 голосов
/ 25 августа 2010

FixupCollection, которая назначена вашему ICollection, воссоздается как массив, когда происходит десериализация. Вот почему ваша коллекция продуктов доступна только для чтения.

Чтобы изменить это, вы можете использовать опцию (существующую по крайней мере на VS2010) в «Добавить ссылку на службу», чтобы изменить тип коллекции на что-то другое (Generic.List или Generic.Observable).

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

Обходное решение, которое я использую (только если вы повторно используете тип на стороне клиента и ссылаетесь на сборку сущностей), - это изменить шаблон T4, чтобы проверить, доступна ли коллекция только для чтения при получении продуктов, и установить FixupCollection, если это так. :

if (<#=code.FieldName(navProperty)#>.IsReadOnly)
{
    var newCollection = new FixupCollection<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>>(<#=code.FieldName(navProperty)#>);
    newCollection.CollectionChanged += Fixup<#=navProperty.Name#>;
    <#=code.FieldName(navProperty)#> = newCollection;                   
}
...