Dec
3
2009

Bug in the Create DomainService wizard

In a previous blog post I documented an undocumented breaking change in the DomainService wizard. It turns out that it is really a bug.

 

When you create a DomainService using the July .NET RIA Services you would get an update that looks like this:

public void UpdateMyEntity(MyEntity currentMyEntity)
{
    this.ObjectContext.AttachAsModified(currentMyEntity, this.ChangeSet.GetOriginal(currentMyEntity));
}

The new version gives you a version that looks like this:

public void UpdateMyEntity(MyEntity currentMyEntity)
{
    if ((currentMyEntity.EntityState == EntityState.Detached))
    {
        this.ObjectContext.AttachAsModified(currentMyEntity, this.ChangeSet.GetOriginal(currentMyEntity));
    }
} 

It turns out that the new version is a mistake, not a change that was undocumented in the breaking changes document, and it is causing major problems for people. The recommendation is that all Updates should be modified to remove the If check so that the resulting method looks like the original .NET RIA Services version.

Dec
3
2009

To Share or Not to Share

One of the really interested puzzles that occurred to me with the release of SL4 and the VS2010 version of WCF RIA Services is what the new ability of .NET 4 to reference SL4 code libraries means to the WCF RIA Services shared file feature. My thinking goes like this:

  1. The shared code feature was created because the Silverlight and Desktop CLRs couldn’t share assemblies.
  2. The Desktop CLR can now reference Silverlight 4 assemblies
  3. Given that the shared code feature is not being removed, there must still be a use case for shared code
  4. The use case for shared code must be uniquely related to RIA Services, otherwise the feature would become part of Visual Studio itself
  5. Given both 3 and 4, it follows that while the shared feature is important, we must be careful to limit our usage.
The Use Case for Shared Code

The use case is very simple, RIA Services uses a DAL or PM object and a RIA Services Entity on the client. Those are two completely different objects yet we have business logic and partial classes that we want to share between the two tiers.

One way to fix this problem might be to apply a shared interface to the client and server side objects. If that interface was defined in a Silverlight class library then both the server and client could share that same interface. Then all of the business logic could be defined within a Silverlight class library and shared between the client and the server. However, creating interfaces and class libraries doesn’t really fit in with the “RAD for Silverlight” image that RIA Services has.

The shared code feature handles this by copying un-compiled code between projects. This allows the same code to be compiled against two completely different objects (the server side DAL/PM object and the client side Entity) without having having to have any real interfaces. Also, to be frank, for most people putting interfaces on data objects is taking things a little too far.

The Case Against Shared Code

I am not going to get too deep into this one. Suffice to say, there is a reason that we use multiple projects that compile into dlls instead of just copying all of the code files for a solution into a single mega project and producing a single mega-dll. The shared code feature is part of RIA Services that Shawn Wildermuth would probably call a “Visual Studio Trick”. It is, much like the metadata file used to attach business rules, a bit of a kludge. I wouldn’t be surprised if the shared code feature doesn’t end up getting ripped out of Silverlight in a few years when some new feature of the CLR gives us a better way of solving the core use cases.More importantly, since the shared code feature is purely a compile time piece of trickery I don’t expect Microsoft to be worrying to much about keeping backwards compatibility of shared files too high on their must do list.

Great, so what is the recommendation?

To put it quite simply, for any code that needs to interact directly with both the Entity and the DLR/PM objects you should be using the Shared file feature. Any shared code should be kept as shallow as possible so keep as much of your code as possible in a Silverlight class library that is shared by both the server and client sides of your project.

Nov
18
2009

Updated ApplyState/ExtractState Library

Export more blog entries this week. I will be putting up my guide to the major new features after todays keynote.

In the meantime, here is an updated ApplyState/ExtractState refactored to use the EntitySet instead of the EntityList. I will put up a VS2010 version as well tonight.

RIAServicesContrib2008.zip (235.60 kb)

Aug
20
2009

ApplyState and ExtractState with RIA Services Contrib

UPDATE: There is a new version of the ApplyState and ExtractState at http://www.riaservicesblog.net/Blog/post/Updated-ApplyStateExtractState-Library.aspx

Tomorrow Soon  Some day I am going to updating RIA Services Contrib with some new features. The existing T4 templates, as fun as they are, are going to left alone for now. I am going to look at them again after the PDC version of RIA Services is released. In the meantime, I am going to release some new utility classes that I have been putting together. The release is attached to this blog post and Codeplex will be updated tomorrow. 

This new contrib release adds ApplyState and ExtractState methods to Enity objects, an Import method to EntityList<T>, and an Export method to all IEnumerable<T> where T : Entity collections. To use the new code simply reference the RIAServicesContrib.dll and import the RiaServicesContrib.Extensions namespace.

Here are some usage examples:

Entity cloning

Person newPerson = newPerson();
newPerson.ApplyState(Nothing, existingPerson.ExtractState(ExtractType.ModifiedState);
newPerson.PersonId = Guid.NewGuid();
context.Persons.Add(newPerson);

Partial Save (i.e. save only a single change instead of the whole DomainContext)

PersonDomainContext tempContext = new PersonDomainContext();
Person savePerson = newPerson();
tempContext.Persons.Add(savePerson);
savePerson.ApplyState(originalPerson.ExtractState(ExtractType.OriginalState, ExtractType.ModifiedState);
tempContext.SubmitChanges();

Export EntityList and save to Isolated Storage

using IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()
{
    using IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(fileName, FileMode.OpenOrCreate, isf)
    {
        DataContractSerializer serializer = new DataContractSerializer(typeof(List<EntityStateSet>));
        serializer.WriteObject(isfs, context.Persons.Export());
        isfs.Close();
    }
}

Import information from Isolated Storage into EntityList

using IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()
{
    using IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(fileName, FileMode.Open, isf)
    {
        DataContractSerializer serializer = new DataContractSerializer(typeof(List<EntityStateSet>));
        context.Persons.Import(serializer.ReadObject(isfs));
        isfs.Close();
    }
}

Some things which might not be obvious is that the Export functionality can also be done against a LINQ query, allowing partial exports of entities. When I update CodePlex I am going to include better documentation of the API.

RiaServicesContrib.zip (12.97 kb)

Month List