views:

461

answers:

3

A RIA Domain service has this method...

public virtual CmsDealer GetCmsDealer(string id)
{
    return this.Context.CmsDealerSet.FirstOrDefault(p => p.Id == id);
}

The Wcf service has this...

public CmsDealer GetDealer(string id)
{
    return domainservice.GetCmsDealer(id);
}

When called with a nonexistent Id, the GetCmsDealer() call barfs with an exception about

Unable to cast object of type 'System.Object[]' to type 'RIAServicesLibrary.Web.Models.CmsDealer[]'.

It was my impression that it would simply retun a null, that I could test for later. Yet somehow that isn't happening. All the examples I find show something like this working fine.

Any insight helpful, I am a little baffled and a bit of a newb about EF, RIA and Wcf.

Updated: The problem is that I need to track the failure all the way dowwn to Wcf so that the application that ultimately calls GetDealer can find out that there was no solution. Ideally, I need to do that without leaving uncaught exceptions around :)

A try / catch solution inside GetCmsDealer will allow me to detect the failure, but there is still no way to rerutn a "Empty" CmsDealer object without faking a number of contraints (it seems entity is picky about it).

So I can try / catch in GetDealer as well, but I still dont have a valid CmsDealer object to return.

Thanks!

UPDATED

For those who were wondering how it played out, the final routine looked like this...

public virtual IQueryable<CmsDealer> GetCmsDealerSetOrEmpty(string id)
{
    return this.Context.CmsDealerSet
     .Include("CmsItemState")
     .Where(p => p.Id == id)
     ;
}

The Wcf wrapper is now back to being a simple pass through. On the client I check the Count() of the result, if it is 0 then I can knwo there was no record, if it's 1 then a simple First() gets me the record.

I am willing to bet there is a better way.

A: 

FirstOrDefault will return Null if no matching records are found. I suspect that your service is having an issue with the null return. I would recommend altering this to throw an exception if no matches are found and catch the exception on your client.

Jim

Jim Wooley
The problem is when I have to jump down the wire to the wcf client. I could construct an empty CmsDealer object I suppose and pass that down, then test for it on the far side.
Soulhuntre
+3  A: 

You could also modify the Domain service to do a select instead so that you will get an IEnumerable (which has a count if I'm not mistaken) that you can test in your WCF service. So you would modify this to be something like: public virtual IEnumerable GetDealer(string id){ return this.Context.CmsDealerSet.Select(p => p.Id == id); }

Then in the WCF Service you can do: public CmsDealer GetDealer(string id) { var x = domainservice.GetCmsDealer(id); if(x.Count() == 0) { // oops, nothing to see here } else { // have a live on here } }

Liam
Ok, thats just clever :)Thanks!
Soulhuntre
In the end, that is what I did. public virtual IQueryable<CmsDealer> GetCmsDealerSetOrEmpty(string id) { return this.Context.CmsDealerSet .Include("CmsItemState") .Where(p => p.Id == id) ; }I pass that out through wcf and check the count on the client. Still, it feels ugly :)
Soulhuntre
Now, that "Select" needs to be a Where in liams answer.
Soulhuntre
+3  A: 

Here is a good opportunity for the Null Object Pattern For an example of it think of Double.NaN as a default value.

Changing the Domain service function as follows

public virtual CmsDealer GetCmsDealer(string id)
{
  return this.Context.CmsDealerSet.FirstOrDefault(p => p.Id == id)??
    CmsDealer.NullValue;
}

Allows you to have a valid value in the WCF service and perform the check on the client

Mike Brown
Wow, if that works that will just be AWESOME. I will check it out later and see if it works. Thanks!
Soulhuntre
Ok, I checked the link. That pattern looks good, I'll try and build it into the next project.
Soulhuntre