views:

452

answers:

3

My EF model was generated from my SQL Server database. I then generated a DomainService for RIAServices against the EF model. One of the entities is called "EntryCategories". The DomainService created this method:

public IQueryable<EntryCategories> GetEntryCategoriesSet()
{
    return this.Context.EntryCategoriesSet;
}

Since my user interface display model looks quite different from the physical model, I decided to write my own DomainService for that and related entities. Yes, I know we are meant to modify the generated one but it has so much stuff in there and I wanted to focus on a small thing.

I removed the EnableClientAccess attribute from the generated DomainService and added a new class called ClientDomainService, and encapsulated in it the generated DomainService:

[EnableClientAccess()]
public class ClientDomainService : DomainService
{
    // the generated domain service encapsulated in my new one.
    private DataDomainService _dcds = new DataDomainService(); 

    // reimplement one of the DataDomainService methods
    public IQueryable<EntryCategories> GetEntryCategories()
    {
        return (from t in _dcds.GetEntryCategoriesSet() where t.EntryCategoriesVersions.EntryCategoriesVersionId == datahead.EntryCategoriesVersions.EntryCategoriesVersionId orderby t.DisplayOrder select t);
    }  
}

The very fist thing I tried is to reimplement the GetCateogoriesSet method but with the underlying data filtered based on another entity in my class (not shown). But when I build this, an error shows up:

Entity 'DataProject.Web.EntryCategories' has a property 'EntryCategoriesVersionsReference' with an unsupported type

If I comment out my CientDomainService, replace the EnableClientAccess attribute on the generated DomainService, and place the analagous linq filtering in the original GetEntryCategoriesSet method, the project compiles with no errors.

What is so special about the generated DomainService that my new one doesn't have? Is it that metadata.cs file?

A: 

If you want to expose a specific entity on a domain service you will have to provde at least one query method for it. This is also required when the entity is only accessed as a child of another entity.

In this case you need to add the EntryCategoriesVersions entityset to the domain service, to get the scenario working correctly.

W.Meints
A: 

Hi John,

What's special about the generated domain service is not the .metadata.cs file (you can keep it, and use it, but it doesn't solve your problem).

The problem appears somehow because RIA services (?) needs a 'domain service description provider' for the exposed Linq to EF entities. The LinqToEntitiesDomainService class has the LinqToEntitiesDomainServiceDescriptionProviderAttribute, already applied, so the generated domain services which inherit from it also inherit the provider.

When you build your own custom domain service, derived from DomainService, and expose entities through it, you need to apply this attribute yourself. Furthermore, since the provider cannot infer the object context type from the domain service base class (which it can and does if the base class is LinqToEntitiesDomainService), you need to specify the object context type in the attribute constructor, like this:

[EnableClientAccess()]
[LinqToEntitiesDomainServiceDescriptionProvider(
                            typeof(YourObjectContextType))]
public class ClientDomainService : DomainService
{
    ...
}

That should fix it.

Note that this means if you had hoped to abstract your object context away from your domain service, you'll be disappointed. I had opted for the seemingly popular repository model where all code that operates on the object context goes into a provider used by the domain service. This facilitates unit testing, but evidently doesn't remove the domain service's dependency on the object context. The context is required for RIA Services to make sense of your entites, or at least those referenced by the domain entity (such as EntryCategoriesVersions in your case).

Tor Haugen
A: 

What type is EntryCategoriesVersionsReference ? Try adding a [DataContract] annotation against the type, and appropriate [Key] and [DataMember]. It should help with marshalling.

Chui Tey