EDM -> POCO -> WCF (.NET4) But transferring Collections causes IsReadOnly set to TRUE
Ok, this may sound a little 'unorthodox', but...using VS2010 and the new POCO t4 template for Entity Framework (Walkthrough: POCO Template for the Entity Framework), I can generate nice POCO's. I can th开发者_如何学Pythonen use these POCO's (as DTO's) in a WCF service essentially going from EDM all the way through to the client. Kinda what this guys is doing (POCO with EF 4.0 and WCF 4.0), except everything is generated automatically. I understand that an entity and a DTO 'should' be different, but in this case, I'm handling client and server, and there's some real advantages to having the DTO in the model and automatically generated.
My problem is, that when I transfer an entity that has a relationship, the client generated collection (ICollection) has the read-only value set, so I can't manipulate that relationship. For example, retrieving an existing Order, I can't add a product to the Products collection client-side...the Products collection is read-only.
I would prefer to do a bunch of client side 'order-editing' and then send the updated order back rather than making dozens of server round trips (eg AddProductToOrder(product)). I'd also prefer not to have a bunch of thunking between Entity and DTO. So all-in-all this looks good to me...except for the read-only part.
Is there a solution, or is this too much against the SOA grain?
The FixupCollection which is assigned to your ICollection is recreated as an Array when the deserialization occurs. Th'at's why your Products collection is read-only.
In order to modify this, you can use the option (existing at least on VS2010) in the "Add Service Reference", to change the Collection type to something else (Generic.List or Generic.Observable).
But, if you use the option to reuse type existing in existing assembly and referencing the assembly containing your entity, the previous option will not be applied to existing type and you will still have Array in your Products collection.
A workaround i use (only if you reuse type on client side and reference your entity assembly) is to modify the T4 template to check if the collection is read-only in the get of Products, and set an FixupCollection if it does:
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;
}
"la mouette" solution works with referenced assemblies:
We have the same problem, and we have noticed that the property IsReadOnly is setted to true after wcf serialization (Before that, the property value is false).
We have referenced assemblies. In the workaround proposed by "la mouette", use a parametrized constructor, but our POCO template doesn't have one.
We have modified the tt creating an empty constructor to invoke the base one, and that do the trick.
精彩评论