LLBLGen and WCF

Posts   
 
    
knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 13-Sep-2007 15:34:38   

Hi

We are using LLBLGen Pro 2.5 in combination with Windows Communication Founcation (WCF). The architecture is as follows: Our server accesses the database using LLBLGEN and provides an interface to other application via WCF. As all our application are implemented by ourselves, we want to have all client application use typed objects, lists.

Our Wcf contract returns typed list, However, the client proxy that is generated recieves a DataSet !! (or if implemented differently it returns an object).

Example1 (not typed list, not what we actually want):

Server method: [OperationContract] IEntityCollection2 IGetAllSkiPist();

generated client method: public object IGetAllSkiPist()

Example2 (typed list, goal):

Server Method: [OperationContract] EntityCollection<PistEntity> GetAllSkiPistEntities();

Client Method: public System.Data.DataSet GetAllSkiPistStateEntities()

This seems rather strange to me. I would like to recieve exactly the same kind of objects on client side as are returned on server side. It is to say that i am a novice when it comes to LLBLGen and WCF. I havent found any good examples yet.

Thanks for any help and greetings

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 13-Sep-2007 16:13:34   

Have you defined a ServiceContract ? Please check the following section in the LLBLGen Pro manual (Using the generated code -> Adapter -> Distributed Systems -> XML Webservices / WCF support): .NET 3.0+ specific: Windows Communication Foundation (WCF) support

knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 14-Sep-2007 17:36:44   

Hi

i checked the manual (again) and i believe my code my code is ok. I forgot to add the [ServiceKnownType(typeof(XEntity))] attribute but this has not had an influence on the generated proxy. (using the svcutil-tool).

If i try not to use the generated proxy but try to instantiate the chanel by hand (as shown in the manual) the method does not return the entity object but a ResponseObject. I generated the projects for .NET 3.0 so i guess serialization etc. is taken care of when the LLBLGen objects are generated.

Right now i am bit at loss at what to try next. Thank in advance and greetings

Daniel

It is to say that i use the deooversion of LLBLGenPro 2.5 as we are evaluating LLBLGen for a coming project.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 14-Sep-2007 17:44:26   

Generics aren't supported in webservices.

Instead of retunring EntityCollection<PistEntity>, just return EntityCollection2.

knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 14-Sep-2007 17:51:57   

Hi

I dont use typed collection list but the recommended untyped collection and single entities. Still it does not work. :-(

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 14-Sep-2007 20:45:58   

knoepdan wrote:

Hi

I dont use typed collection list but the recommended untyped collection and single entities. Still it does not work. :-(

Please elaborate what you see and what you expect. I.e.: what kind of error do you get, what entities do you send and what does arrive at the other end ?

Frans Bouma | Lead developer LLBLGen Pro
knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 17-Sep-2007 18:40:04   

Could it be that i used basicHttp Binding instead of net.tcp binding? I believe this is the only part thats actually different to the example in the manual. i managed to pass my own objects over wcf but not the the generated llblng entities.

When i generate my proxy object, the server method [OperationContract] IEntityCollection2 IGetAllSkiPist();

becomes:

public object IGetAllSkiPist()

and the method

[OperationContract] PistEntity GetPistEntity(int pSkiPistId);

becomes: public System.Data.DataSet GetPistEntity(int pSkiPistId)

i have to say that this seems extraordinarily strange to me.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 17-Sep-2007 18:46:58   

You do have specified the ServiceKnownType objects? e.g.:


    [ServiceContract]
    [ServiceKnownType(typeof(CustomerEntity))]
    [ServiceKnownType(typeof(EntityCollection))]
    public interface IWCFTest
    {
        [OperationContract]
        IEntity2 GetCustomer(string customerID);

        [OperationContract]
        EntityCollection GetCustomers();
    }

Frans Bouma | Lead developer LLBLGen Pro
knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 17-Sep-2007 18:48:01   

When i still try to call this method in the client, i get the following error:

Outer exception An error occurred while receiving the HTTP response to httpdisappointed /localhost:2121/GisabService. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.

  1. Inner Exception The underlying connection was closed: An unexpected error occurred on a receive.

  2. Inner Exception Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

By the way, do i have to hold a referenct to the llblGen generated dll containing the entity-classes on client side? I believe no as they should be generated by proxy class.

Greetings

knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 17-Sep-2007 18:51:26   

Yes i have. My service contract looks like this:

[ServiceContract] [ServiceKnownType(typeof(PistEntity))] [ServiceKnownType(typeof(IEntityCollection2))] [ServiceKnownType(typeof(IEntityCollection))] [ServiceKnownType(typeof(EntityCollection))] public interface IExchange { #region testing

    [OperationContract]
    bool IsServiceWorking();


    [OperationContract]
    PistEntity GetPistEntity(int pSkiPistId);

    [OperationContract]
    IEntityCollection2 IGetAllSkiPist();

}
knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 17-Sep-2007 19:09:45   

a slight correction to what i have written above. Before i had attribute was [ServiceKnownType(typeof(IEntityCollection2))] which resulted in an object generated on client side. I now use the following interface:

[ServiceContract] [ServiceKnownType(typeof(PistEntity))] [ServiceKnownType(typeof(EntityCollection))] public interface IExchange { [OperationContract] bool IsServiceWorking(); [OperationContract] PistEntity GetPistEntity(int pSkiPistId);

        [OperationContract]
    IEntityCollection2 IGetAllSkiPist();

}

However the generated proxy does not compile due to this line of code:

private schema schemaField;

The error message is: Type name excpected but property found.

knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 18-Sep-2007 10:57:21   

Hi

It seems to me that LLBLGen support for WCF is not yet perfect. I didn't get the simple example in the documentation runnning. I guess the following thread explains what would have to be done to get the LLBLGen work with WCF:

http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=7911&HighLight=1

The interface defining the contract must be present on client and server side, generated proxies dont work. Maybe this should be stated in the documentation, it would have helped me a lot.

Greetings

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 18-Sep-2007 19:13:12   

My example worked perfectly fine. I think the main difference is that I don't use generated proxies but solely the interface. the thing is that these proxies are no longer needed with WCF. Perhaps that's a difference which makes it hard to get it working. Could you try without generated proxies? (so no schema importer, no webservice required extra classes which are necessary for .NET 2.0, just the interface and the service definition.

Frans Bouma | Lead developer LLBLGen Pro
knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 19-Sep-2007 12:49:43   

Hi

I have been trying the interface approach and i believe i am making progress. I can transport single entities but no collections. When i try to transport a IEntityCollection2 list i get the following error messages:

Outer Exception An error occurred while receiving the HTTP response to http: //localhost:2121/GisabService. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details. Inner Exception1 The underlying connection was closed: An unexpected error occurred on a receive. Inner Exception 2 Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. Inner Exception 3 An existing connection was forcibly closed by the remote host

My contract looks as follows:

ServiceContract] [ServiceKnownType(typeof(PistEntity))] [ServiceKnownType(typeof(EntityCollection))] [ServiceKnownType(typeof(IEntityCollection2))] // sometimes i remove this declaration but this seems to have no influence public interface IExchange { #region testing

    [OperationContract]
    bool IsServiceWorking();
    #endregion

     [OperationContract]
    PistEntity GetPistEntity(int pSkiPistId);

    [OperationContract]
    TestClass GetTestClass();

      [OperationContract]
    IEntityCollection2 IGetAllSkiPist();
  }

All methods work over WCF except IGetAllSkiPist().

public IEntityCollection2 IGetAllSkiPist() { DataAccessAdapter adapter = new DataAccessAdapter(); EntityCollection<PistEntity> pists = new EntityCollection<PistEntity>(new PistEntityFactory()); adapter.FetchEntityCollection(pists, null); return pists; }

knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 19-Sep-2007 12:50:33   

I actually using the interface approach over using proxies. This seems much more convenient to me.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 19-Sep-2007 13:08:36   

In my example I use a non-generic collection, instead of the generic one. I think that's essential. The error you got has no real info about what was wrong, so it's guesswork what's the real cause but if I look at the differences that might be it.

Once the object is used for serialization, the graph itself can contain generic collections, that's not important anymore. Could this be the case? Could you try:

       DataAccessAdapter adapter = new DataAccessAdapter();
        EntityCollection pists = new EntityCollection(new PistEntityFactory());
        adapter.FetchEntityCollection(pists, null);
        return pists;

instead?

Frans Bouma | Lead developer LLBLGen Pro
knoepdan
User
Posts: 11
Joined: 13-Sep-2007
# Posted on: 19-Sep-2007 13:38:50   

Haleluja. It works.. i should have seen that myself. I was looking at the interface instead of checking the actual implementation.

Thanks for your impressivly quick support.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 19-Sep-2007 14:12:18   

knoepdan wrote:

Haleluja. It works.. i should have seen that myself. I was looking at the interface instead of checking the actual implementation.

Thanks for your impressivly quick support.

No problem, I know how frustrating the world of < and > can be sunglasses wink

Just a FYI: Webservices, and thus also WCF can't deal with generics, so I think that's the reason this goes wrong. (guesswork, but I think that's the reason)

Frans Bouma | Lead developer LLBLGen Pro