EDM -> POCO -> WCF (.NET4) Но при передаче коллекций IsReadOnly устанавливается в TRUE

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

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

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

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


person Gary B    schedule 19.03.2010    source источник


Ответы (2)


Коллекция 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;                   
}
person la mouette    schedule 25.08.2010

Решение "la mouette" работает с указанными сборками:

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

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

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

person Milton    schedule 14.09.2010