ADO.NET Data Services with Linq-to-SQL - wcf

I am encountering a weird error when using linq-to-sql with ado.net data services. I have a simple silverlight application that connects to a remote database. I first added the linq-to-sql class and dragged a table onto the designer. Then I added a ADO.NET Data Service, updated the DataService reference to point to the L2S Data context.
Compiled with no problems.
When I open the service in IE I immediately get an error so I add the following attribute to the data service:
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
This brings up the detailed error message:
The exception message is 'On data context type 'DataClasses1DataContext', there is a top IQueryable property 'table1' whose element type is not an entity type. Make sure that the IQueryable property is of entity type or specify the IgnoreProperties attribute on the data context type to ignore this property
this happens to any database table I use in the L2S designer!
What is this error and why am I getting it?

You'll need to decorate your classes with the DataServiceKey attribute.
More details on Marc's blog here, and an MSDN blog here (the latter talks about many to many relationships, but it covers the DatServiceKey attribute).

Related

Why this EntityManagerSaveException?

I am using Silverlight 4 and DevForce 6.1.11.0
I have some POCO classes that implement EntityAspect.
When changes are saved via EntityManager.SaveChanges; DevForce does not save these POCO entities to the server, because these POCO entities are not part of EF.
Instead I send them to a webservice via WebClient.UploadStringAsync.
This works, expect when I am saving more than one entity of the same type. Then I get this exception:
EntityManagerSaveException: An entity with this key: PocoMyClass: 0,0
already exists in this entityManager
I have checked the cache, and there is no entity with that key.
The WebClient.UploadStringAsync still sends the data and everything gets saved, but the exception does not look good to customers.
How do I work around this exception?
The poco entities that I am having problems with are only supposed to live on the client, not the DevForce server. The reason is that only the client can access these on the local network.
So I am using WebClient.OpenReadAsync to read the data in and create the poco entities on the client. And then I use WebClient.UploadStringAsync when saving the poco entities.
When creating the poco entity and adding it to the entitymanager, I do like this:
var pocoEntity = new PocoMyClass();
pocoEntity.keyId = some integer;
…
entityManager.AddEntity(pocoEntity);
pocoEntity.EntityAspect.AcceptChanges();
After doing this I see that the properties for EntityVersion.Original of the poco entity only contains empty stuff (NULL´s and zero’s).
Is this the reason for the exception when saving?
How can I manipulate EntityVersion.Original when the entity does not come from the DevForce server?

Entity Framework T4 POCO objects raising exception in WCF

These objects have collections of type ICollection<>
If I pass an object graph from client to server it throws the following exception:
System.NotSupportedException was unhandled by user code
Message=Collection was of a fixed size.
Source=mscorlib
Which is occurs in the fixup code the T4 template has generated. It seems the collections are being deserialized on the server as arrays and so can't be modified. Is there a way to specify the type the serializer should use?
I would strongly recommend that you don't use the POCO classes on your service boundary. Create a separate set of classes to model the data you want to send and receive across the wire (Data Transfer Objects - DTOs) and use a tool like automapper to move data between the DTOs and your POCO classes
Essentially you end up tying the consumers of your service to your service's internal conceptual model which means you become constrained in changing your implementation because you need to avoid breaking your clients
Try using the following attribute
[ServiceKnownType(typeof(List<string>))]
If that doesn't work, perhaps try using IList<T> if that is possible in your situation

WCF + sending linq generated objects

i have entities generated from my .dbml. So some objects have relationship "one to many" and in entities it was generated as EntitySet.
Also, I have WCF Workflow Service Application which contains .xamlx with bussines logic.
So using this .xamlx i try to send objects which was genereted before to client, but i catch an exception "The underlying connection was closed: The connection was closed unexpectedly".
EntitySet<> was added to KnonwTypes. Serelzation mode in .dbml file has "None" value.
So, could you tell me how i can solve this problem?
is there an inner exception?
my guess is an circular reference caused by the navigation properties.
if that's that case you have a couple of options:
remove the virtual keyword from your navigation properties and eager load everything. Note: not sure if this applies to linq to sql.
map your entities to simple dto objects.
employ a circular reference aware serializer (the one built in to .net is not).

How to serialize SubSonic generated class?

I'm trying to use SubSonic with WCF. I can get data into List but I can't return that data to client side, its error is
The socket connection has been disposed. Object name:
'System.ServiceModel.Channels.SocketConnection'.
I try to send and retrieve data to/from WCF by POCO object and it working but when I try to use generated class from SubSonic it don't work anymore, so I think its has some problem.
I would assume that this is not the "real" exception. I am not familiar with WCF but maybe you find something in the logs.
Here is an article about debugging WCF http://www.codeproject.com/KB/WCF/DebugWCFApps.aspx
Most likely WCF is trying to serialize a SubSonic class with nullable properties.
Properties of SubSonic classes are marked as XMLAttribute, which throws an error if you want to serialize a nullable type. Nullables can only be serialized as XMLElements.
Try if it works with a SubSonic generated class that has no nullable property.
After I've downloaded source code of SubSonic and debug into it SubSonic.Core, I found that it error because GetBody<> will create instance of that class, and inside its constructor is trying to connect to database which it can't; client has no access to database.
Now I'm working on create mapping class with SubSonic and return POCO instead.

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 then 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.