WCF and LINQ to SQL (Part 2 (Creates))

Right, in my last post I wrote about creating a DBML file and hooking it all up through WCF, however, we only got to ‘retrieving’ from the database via the service. So, let’s presume you want to upload…

We already had our contract:

[ServiceContract]
public interface ICarsService
{
    [OperationContract]
    Car GetCar(int id);
 
    [OperationContract]
    void SubmitCar(Car car);
}

Of which we’ve tested the ‘GetCar’ method, let’s get to implementing the ‘SubmitCar’ method.

We actually did implement some code in our class:

 

public void SubmitCar(Car car)
{
    _db.Cars.InsertOnSubmit(car);
    _db.SubmitChanges();
}
But, will this work?

Well, our first problem is actually testing it. The WCF Test Client (which we get from an F5 call) is not particularly easy to use to create more complex calls, such as creating a ‘Car’ instance to upload.

Soooo…. We’d best create ourselves a client app.

Let’s go to our Solution Explorer, and add a new console project: ‘Client_Console’. Now, to get a service reference to this bad boy… so… Right click on the ‘references’ folder on the Client_Console project and select… ‘Add Service Reference’ (easy eh?)… Now click on ‘Discover’ and this should get your service from the solution.

Browse to the actual interface you want (probably only one there in this case :)), and give it a good namespace name – I’ve gone for ‘CarsService’ (imaginative eh?).

AddServiceReference

Now we have that we can code against it, so opening up the ‘program.cs’ file helpfully created by VS for the ‘Client_Console’ app we can construct a new Car instance.

Car car = new Car
              {
                  ID = 5,
                  Make = "Ford",
                  Model = "Focus",
                  Owner = new Owner
                              {
                                  Surname = "Milly",
                                  Title = "Ms"
                              },
                  PreviousOwners = new[]
                                       {
                                           new PreviousOwner {
                                               Surname = "Qwerty", Title = "Miss", 
                                               WhenBought = DateTime.Now.AddDays(-50)},
                                           new PreviousOwner {
                                               Surname = "Vanilly", Title = "Mr", 
                                               WhenBought = DateTime.Now.AddDays(-100)}
                                       }
 
              };

 

Great!

Let’s Submit!!!

CarsServiceClient client = new CarsServiceClient();
client.SubmitCar(car);

Ahhh! NullReferenceException??? What the hey???

NullRef

In fairness it’s true, the ‘PreviousOwners’ property on the 'server’ is null… But why? Well, the cars object was created in the client,not the server, as a result the constructor for the server version was never called. If we look at the constructor for the ‘Cars’ class we’ll see the following line:

this._PreviousOwners = 
    new EntitySet<PreviousOwner>(
        new Action<PreviousOwner>(this.attach_PreviousOwners), 
        new Action<PreviousOwner>(this.detach_PreviousOwners)
    );

 

okey dokey, let’s change the declaration of the _PreviousOwners member:

 
private EntitySet<PreviousOwner> _PreviousOwners = 
    new EntitySet<PreviousOwner>(
        new Action<PreviousOwner>(this.attach_PreviousOwners), 
        new Action<PreviousOwner>(this.detach_PreviousOwners)
        );

 

Ah. We can’t do that as we’re attempting to use ‘non-static’ methods in a member declaration… hmmm, back to the Property itself perhaps…

What about adding a check for null into the property itself…

[DataMember]
[Association(Name="Car_PreviousOwner", Storage="_PreviousOwners", ThisKey="ID", OtherKey="CarId")]
public EntitySet<PreviousOwner> PreviousOwners
{
    get
    {
        return this._PreviousOwners;
    }
    set
    {
        if(_PreviousOwners == null)
            _PreviousOwners = 
                new EntitySet<PreviousOwner>(
                    new Action<PreviousOwner>(this.attach_PreviousOwners), 
                    new Action<PreviousOwner>(this.detach_PreviousOwners)
                    );
        this._PreviousOwners.Assign(value);
    }
}

Right, so firing F5 on our client now, and lo-and-behold there we are! It works! IT ACTUALLY WORKS!!!

If go to our WCF Test Client and ‘GetCar’ for ID 5, we should get back our car we just inserted….

 

TestClient_Car_Get5Huzzah!

So, we have Create and Retrieve working from our CRUD code. Obviously we’ll need to work out Updates and Deletes next, (a new post methinks!).

I will leave you with one note, concerning the use of the dbml file.

Obviously, it’s a great time saver, the code is generated for you (for better or worse) and the associations etc are all setup, but once you’ve added your WCF attributes to the classes you’re only one step away from an accident. A little tweak to the dbml will regenerate all your code. Yes – that does mean you lose all the WCF goodness you’ve put there.

So, the solution to this? Split the file, once you’re content with your dbml, basically go through the *.designer.cs file and create a separate file with the contents in, then exclude the dbml file from the project. You should find it will all still work, you just won’t have the design interface.

Other benefits to this approach are that you can add in methods etc to the classes without fear of losing them.

Anyways, I will be back with part 3, concerning deletes at some near future point (updates will be part 4).

Print | posted @ Wednesday, March 18, 2009 6:00 PM

Comments on this entry:

Gravatar # re: WCF and LINQ to SQL (Part 2 (Creates))
by jb at 5/7/2009 4:12 AM

Hi,
Do you have source code for this blog? I tried following your code but for 1 to many relationships do not show up in the debug window
Gravatar # re: WCF and LINQ to SQL (Part 2 (Creates))
by Chris at 5/7/2009 8:54 AM

Hi Jb,

Yes, I do have the source for these posts, but they are related to my database. So you'd need to have that as well...

You're more than welcome to have the source, if you want it...

Cheers
Post A Comment
Title:
Name:
Email:
Comment:
Verification: