You’ve been asking for it for what seems like forever now, and as of today, it’s available. That’s right, WCF RIA Services now supports EntityFramework Code First! Varun Puranik developed the feature, and he has blogged about it, including some very useful Code Snippets. I recommend going to read his post first, and then coming back here.

NuGet Baby!

EF Code First support for RIA Services is the first feature where we’re using NuGet as the first distribution mechanism. Only NuGet offers the ability to release features independently from one another (without flooding your Add/Remove Programs list anyway), and it was a great fit for getting EF Code First support in your hands as quickly as possible.

We will also roll this feature into the WCF RIA Services Toolkit the next time we put out a release of the entire toolkit.

Heads-Up

With this release, there is no Domain Service Wizard support for your DbContext classes. So when you do Add New Item and choose Domain Service Class, you won’t see your DbContext classes in the dialog. But with the NuGet package and Varun’s VS Code Snippets, I suspect you won’t miss it much. As Varun mentioned, we will be adding Domain Service Wizard support for your DbContext classes in WCF RIA Services V1.0 SP2.

There’s also a small gotcha that you need to be aware of. In order to generate code into your Silverlight project, RIA Services has to inspect your DbContext at build time in order to get the entity types that are available. If you have been using DbContext, you’re likely aware that simply creating and accessing a DbContext can actually create your database in SQL Express. Chances are though, you don’t want this to happen at build time when RIA Services generates code. In order to prevent this, there’s a small bit of code you need to add to your DbContext to null out your database initializer. Varun illustrated this, and I’ll show it below too.

When using this feature, you will inevitably get a build warning along the lines of:

The attribute 'System.ComponentModel.DataAnnotations.DatabaseGeneratedAttribute' requires a reference to System.ComponentModel.DataAnnotations in the client project 'SilverlightApplication10'. Skipping generation of attribute. Please add a reference to System.ComponentModel.DataAnnotations to ensure generation of the attribute.

This is unavoidable at the moment, and you might have actually seen similar build warnings when using other DataAnnotations attributes that aren’t available in Silverlight. This is where our code generation was trying to be smart, recognizing that your model has an attribute applied from the DataAnnotations namespace, but seeing that the attribute type isn’t available to your Silverlight project. At the time we created that build warning messages, it was safe to assume this meant that you didn’t have a reference to DataAnnotations in your Silverlight project. That is no longer true - EntityFramework 4.1 includes a DatabaseGeneratedAttribute type that is defined within the DataAnnotations namespace, but of course isn’t available in Silverlight. You can just ignore this build warning.

Update:Lastly, the day after we released this NuGet package, the Entity Framework team released a June CTP for EF. That CTP is not yet supported for RIA Services. We wanted to first get support in place for the released EntityFramework 4.1 bits, and we’ll work to target EntityFramework 4.2 as soon as we can.

Zero to Nifty in 5 Minutes

Let’s run through a super-quick-start for getting going with RIA Services and EF Code First. This by no means is a guide to how to use EF Code First, but it illustrates how to use RIA Services with it in a basic example.

Before you begin, you must have WCF RIA Services (V1.0 RTM, SP1, or SP2) installed on your machine, as well as NuGet.

As far as RIA Services / EF Code First goes, you’re done. At this point, you can now go into the Silverlight application and do all of the things you expect to do with RIA Services. As with other DomainServices, your client has no awareness of what data access layer you’re using. Because of this, you can use the new DbDomainService with Silverlight 4, Silverlight 5, or with RIA/JS.

Because we don’t have Domain Service Wizard support (until the next release of WCF RIA Service V1.0 SP2), you might want to grab Varun’s VS Code Snippets to make the above code simpler to crank out for each of your entity types.

How It Works

Thanks to the power or NuGet, quite a bit was actually done for you by adding the package reference to RIAServices.EntityFramework.

Our NuGet package has a dependency on the EntityFramework 4.1 NuGet package, so that was installed for you.

The NuGet package includes Microsoft.ServiceModel.DomainServices.EntityFramework, which added DbDomainService to the System.ServiceModel.DomainServices.EntityFramework namespace. A reference to this assembly gets added.

The NuGet package adds references to System.ServiceModel.DomainServices.Hosting and System.ServiceModel.DomainServices.Server

The NuGet package transforms your web.config file to include the domainServices section definition, and the DomainServiceModule HTTP Module under both <system.web> and <system.webServer>

Note that 2-4 in this list matches up with what the Domain Service Wizard would typically do for you. So even though we don’t have wizard support with the NuGet package, you still don’t have to mess with references or web.config to use RIA Services.

I was able to get the sample project to compile just fine, but creating my own solution with the Silverlight app and RIA Service in separate projects results in this error. My models and DomainService is in the RIA Service project.

Question for you:If I am already using a Repository pattern behind my Domain Service (So my Domain Services never directly query my DbContext -- they calls methods on my repositories), are there any additional benefits to using a DbDomain Service?

@guestYou should feel free to use this NuGet package in Production. These are release-quality bits, but we've left them under the Toolkit license rather than putting them in the product. This allowed us to release much sooner, and we'll be able to make changes to support EF 4.2. We'll do our best to not change any API or anything though.

For anyone that might still be struggling with the "Failed to get the MetadataWorkspace for the DbContext" error and you are certain that the connection string is correct, verify that your class includes an ID property.

The class I was working with should of inherited the Id but wasn't which was causing me the problem. Ensure that any class that will be included on the client includes an ID either directly or via inheritance.

The ID:

- Has to be a public property (cannot be a public member)- Must include both getter and setter- Name is case-insensitive- Datatype worked as any type I tried (int, string, Guid, double). I’m using int.

On 7/8 you wrote "... Yes, you can definitely use DataAnnotations attributes directly on your Code First classes and eschew the Metadata classes completely..."

That doesn't seem to work. I can easily load related entities server-side with either EF's .Include function or Assocation attribute. But they never appear client-side unless I specify the Include attribute in metadata. I tried both a DbDomainService and a DomainService with repository pattern.

The [Include] attribute is still needed if you want RIA Services to serialize the related data to the client. But you should be able to put the [Include] attribute directly on the model rather than in a buddy class.

Because RIA is DAL-agnostic, we need to have our own mechanism for marking related data as included in serialization. Otherwise, if we inspected all related data properties to see if data was there, and you had lazy-loading in place, we'd send your whole database to the client.

I knew about the difference between .Include in EF and [Include] in RIA, but not that I could put it directly on the model.

So does that mean I should define my Model in my RIA Services Web assembly?

With ASP.Net I used to create separate assemblies for model and data access code. But adding a reference to System.ServiceModel.DomainServices.Server (which defines the [Include] attribute) in a separate assembly throws a DomainOperationException. Besides, it seems to defy the whole purpose of separating my model out in a separate assembly.

Nice post - we had just ruled out Code First due to its lack of playing nicely with RIA services... this has just created me some new work!

I notice that the 'AttachAsModified' extension method is only provided for the concrete DbSet class - and not for the IDbSet interface. This is a bit of a pain for testing - since I want to be able to swap in test IDbSet implementations.

Is this something that is being looked at - or perhaps there is a simple workaround (other than casting)?

Thank you for making RIA Services support for EF DbContext / Code First available. It's absolutely awesome!

I submitted a sample on code.msdn where I attempted to introduce Unit-of-Work and Repository patterns where IDbSet<T> serves as my generic repository interface and I created a UnitOfWorkDomainService as follows:

@davebI found the issue with the AttachAsModified extension method being provided on DbSet<T>, not IDbSet<T>, but I ended up implementing this on my DbContext derived class directly as you can see in my sample on code.msdn.

@Remco Blok - I have had some problems when using DomainService directly - and not using DbDomainService... when retrieving a set of objects that contain navigation properties, the navigation properties all get resolved, which means you can end up loading a huge object graph. Perhaps you've seen that and found a solution, but I have found that when using DbDomainService (or LinqToEntitiesDomainService) this problem disappears, though you have to specifically eager load the navigations using the .Include syntax (which suits me fine).

@davebDbDomainService sets LazyLoadingEnabled to false on your DbContext, which is what you would have to do yourself if you derive directly from DomainService. I have done this in the UnitOfWorkDomainService in my sample on code.msdn

@Remco BlokDoh, that makes me feel foolish... when we first picked up EF we set LazyLoadingEnabled to true - so that we didn't have to explicitly load navigation entities. I'd put 2 and 2 together and got 2 back.

I do have another problem. If I try to add any custom logic to my OnModelCreating DbContext override (perhaps to map a column to the storage model), I get this error in my Silverlight project:

Failed to get the MetadataWorkspace for the DbContext type

I know my connection string is correct, and if I use ColumnAttribute on those properties everything works...

I am fighting with the "Failed to get the MetadataWorkspace for the DbContext type" error at the moment.

I have one connections string I use for internal testing (local SQLEXPRESS) but I need to update that to point to SQL Azure. Once I do the update the build fails, because outgoing 1433 is being blocked.

I guess I am surprised that the connection is being actively used at build time.. and in my current situation it is making life difficult.

Jeff, Please correct me if I am wrong What is the best way to use unity or mef(prism) using wcf ria and code first for domain services?Is it best to refactor silverlight business application? or silverlight navigation application? Is the best pattern unit of work??Thanks

Anyone have any inkling of how to get the dbdomain service to be completely accepted by LightSwitch?I can get the LS app to detect the service in the project and the entities.. but the app fails to buildError 1 The type 'SLCLCAData.Services.ControllersAssistantDomainService' cannot be used as type parameter 'TServiceContext' in the generic type or method 'Microsoft.LightSwitch.ServerGenerated.Implementation.RiaDataServiceImplementation<TContext,TServiceContext>'. There is no implicit reference conversion from 'SLCLCAData.Services.ControllersAssistantDomainService' to 'System.ServiceModel.DomainServices.Server.DomainService'. D:\SourceCode\New folder\HSProjects\Old\WcfServiceLibrary1\CompanyEditorWCF\ServerGenerated\GeneratedArtifacts\DataServiceImplementation.cs 99 18 ServerGenerated

Error 2 The type 'System.ServiceModel.DomainServices.EntityFramework.DbDomainService`1<T0>' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.ServiceModel.DomainServices.EntityFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. D:\SourceCode\New folder\HSProjects\Old\WcfServiceLibrary1\CompanyEditorWCF\ServerGenerated\GeneratedArtifacts\DataServiceImplementation.cs 99 18 ServerGenerated

In the existing DomainService, I have a private property of HRContext that I new up and an override on Submit that calls SaveChanges. This all works fine until I convert to DbDomainService, that's when I get the build error.

Many folks have indicated a problem with their connection string. I don't see this as the problem in my case because, as I said, the DomainService is able to new up the HRContext (which is a DbContext) and query the db, etc.

When i compile I get this error "Failed to get the MetadataWorkspace". The connection string is ok because ifi use public Int32 WorkerId { get; set; } and public Int32 Company { get ; set; }. It's not very well because iloose navigation properties. Why? Sorry for my bad english =) Regards. Gabriele

Jeff I would greatly appreciate any updates on entity framework june ctp 2011 for table value functions, code first for silverlight, wcf ria. We do appreciate when you keep us informed! Thank you for your excellent post.

I'm also getting the "Failed to get the MetadataWorkspace for the DbContext type '...'." error. When I have ONE DbSet<...> property on the DbContext everything builds correctly. When I add another DbSet<...> property I get the error. Somehow it appears to be having trouble reconciling multiple DbSet properties on the context.

Just in case anyone is still getting the "Failed to get the MetadataWorkspace for the DbContext type" errors you can run an additional instance of VS and attach to the instance which is failing to build. If you turn on break on CLR exceptions you can catch the exception which is causing the failure.

If you guys are still having issues with the "Failed to get the MetadataWorkspace" error, usually it's because you have an Entity with a Composite primary key (an Entity with multiple properties decorated with a Key DataAnnotation attribute).

The error you'll usually get when running Unit Tests is: "System.InvalidOperationException: Unable to determine composite primary key ordering for type 'Your Type'. Use the ColumnAttribute or the HasKey method to specify an order for composite primary keys."

Basically EF does not know the Order of which Key should come first (not sure why this EVEN MATTERS because it's a Primary Key, who CARES about the friggin order!). Anyway, decorate your Properties with a [Column(Order = x)] attribute and the errors go away.

Ok, finally got past all these "Failed to get the MetadataWorkspace..." errors. But now I am running into another issue. It doesn't stop me from building but it's quite annoying to have these "Warnings" show up for no reason. Basically, I have decorated my classes with the Table[TableName, SchemaName] attribute. However, the RIA Services Client generates TONS of warning messages (one for each Table and Column attribute) and just says that it will not generate them because I don't have a reference to "System.ComponentModel.DataAnnotations" (which of course, I do). Basically, I can see that it wants the "Server" reference of DataAnnontations and doesn't recognize that it is in fact generating code for a SL client.

Here's the full warning message:

"The attribute 'System.ComponentModel.DataAnnotations.TableAttribute' requires a reference to System.ComponentModel.DataAnnotations in the client project 'Client.Services'. Skipping generation of attribute. Please add a reference to System.ComponentModel.DataAnnotations to ensure generation of the attribute."

and also:

The attribute 'System.ComponentModel.DataAnnotations.DatabaseGeneratedAttribute' requires a reference to System.ComponentModel.DataAnnotations in the client project 'Client.Services'. Skipping generation of attribute. Please add a reference to System.ComponentModel.DataAnnotations to ensure generation of the attribute.

Is there ANY way to get rid of these annoying messages that obviously mean nothing since I know it shouldn't even generate these attributes on the Client side?

Sorry there isn't a way to get rid of those warnings. We special-cased the System.ComponentModel.DataAnnotations namespace back in v1.0 as we didn't expect other teams in Microsoft to be creating types in that namespace outside of the actual DataAnnotations assembly. We've been proved wrong there, and the result is the warning.

To everybody who get a "Failed to get the MetadataWorkspace for the DbContext" Exception:Try to access the "svc" address, some exception message is there, fix it and rebuild your solution, that exception may be resolved.My English is not good, sorry.

I added the reference over NuGet and now I'm also get the error "Index (zero based) must be greater than or equal to zero and less than the size of the argument list." when I try to add a new DomainService through the wizard. When I remove the references in the project (and clean), the error's gone, but of course, my code first context won't show up.

Happy to provide further info... I'm a little disappointed to be honest, usually your stuff works like a charm :(

Great article, but I've tried everything to solve the metadataworkspace error and I cannot find the problem. I can connect to the database using server explorer and I'm using the same connection details in my web.config. I've even specified the connection name in the datacontext constructor.

My entity and datacontext is in a class library which is referenced by a WCF RIA Services Class library. THe connection string is in the web.config of the main SIlverlight web project.

I finally solved the problem through some trial and error. As I'm using a WCF RIA Class library to house my domain service, I needed to add a web.config file to the web project of the class libary with the same connection string in it as in the main silverlight web project.

Could you please give us some guidance on whether you are offering support for newer versions of EF and what the roadmap is please? This is a very serious question and nobody is getting any answer???????

I touched base with Rowan Miller from the EF team on this, @Scott. Here's his input...

"In reality, the code will actually work because setting something to deleted when it's already detached is a no-op. The else part of the clause will also work for attached and detached entities because Attach will move the entity to the Unchanged state and then Remove will mark it as Deleted.

"I think you could actually reduce the code to the following and it would still work:

fixed "Failed to get the MetadataWorkspace for the DbContext type" Error1 localhost\SQLExpress service must enabled.2 RIA class library's Web project must has a Web.config file (not include to web project) include two sections <connectionStrings> and <runtime>3 DbContext constructor: public XxxDbContext() : base("Server=192.168.1.10;...")