The pain and problems of WCF and Entity Framework Code First

July 4, 2011 Leave a comment

After some initial prototyping with the CTPs of EF Code First we decided to start using the release version for our production code. Although we really like EF Code First we’re found that a number of difficulties have arisen from using EF Code First in conjunction with WCF (and thus working with entities that are detached from the context).

To put this another way, when using EF directly everything is all very nice and easy, but bring WCF into the mix and it becomes more complex and messy. Now although this is to be expected I think Microsoft could make EF Code First work better in a disconnected environment.

For example, we have a client, which connects via WCF to a windows service. The following is a simplified flow of events of inserting a new customer record:

  1. A new Customer instance is created on the client.
  2. The user specifies a Country to associate with the Customer – we therefore make a service call to get the Country instance. This is then assigned to the Customer.
  3. A Save method is then called on the service – we pass to this the Customer (which has the associated Country assigned to it).

In reality our object graphs are a lot more complex than what I describe above but it illustrates how we work.

The problems we’re encountering are as follows:

Setting the entity state

When the service receives the customer and it is attached to the service it assumes all entities in the graph are of Added state. We therefore have to set the entity state for all objects in the graph. Rowan Miller (Microsoft) mentions in a post I made a few months back that they’re working on, as of yet no signs of improvement here:

http://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/4d8af696-6054-4acb-b616-430eecf86b3d

Change to foreign keys not updated

If I retrieve an entity, then update it so it references a different entity, I’m finding that it saves with the original foreign key value. This again appears due to working with the entity on the client and then sending it to the service – the service/context doesn’t know that the relation is modified. The solution seems to be to add a foreign key property to the entity:

http://stackoverflow.com/questions/5729031/ef-4-1-code-first-change-to-fk-value-not-updated-when-using-new-context-over-wc/5729844#5729844

This leads though to a less OO design and more messing around when assigning entities.

Duplicate entities in the object graph

In some situations we have duplicate entities in the object graph. Each of the duplicates are retrieved via separate service calls so although they have the same ID they don’t reference the same object in memory. This is best explained here:

http://stackoverflow.com/questions/6280731/ef-4-1-code-first-duplicate-entities-in-object-graph-causes-exception/6284699#6284699

So what to do?

The only solution to the above seems to be to add code to your service to deal with this.  This involves changing the state of entities in the object graph.  This tends to be not particularly nice code and if not careful it can become messy.   What we really want if for Microsoft to consider EF (Code First) alongside WCF and make them just work!  That of course may be wishful thinking.

WCF – Making multiple async calls with the ChannelFactory

June 18, 2011 4 comments

The post explains how to use the ChannelFactory to make multiple asynchronous calls.

Say for example on the client you have a collection of Customer entities that you wish to save. Service side you have a WCF service method which takes a single customer. You therefore need to call this service multiple times (once for each customer). The service interface is as follows:

[ServiceContract]
public interface ICustomerService
{
    [OperationContract]
    int Save(Customer customer);

    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginSave(Customer customer, AsyncCallback callback, object state);

    int EndSave(IAsyncResult result);
}

In this post I am working on the premise that I don’t want to use queuing in the service (or that I am calling a service I don’t control).

As can be seen, the above implements the service operation asynchronously:
http://msdn.microsoft.com/en-us/library/ms731177.aspx

This post focuses on how we call this service asynchronously using the ChannelFactory and how we manage the WCF channel(s).

From the client side of things, when calling a service asynchronously, the Begin method should be called, passing it the callback method. This is explained here:
http://msdn.microsoft.com/en-us/library/bb885132.aspx

Calling the service:
The following code shows how to make multiple calls on the same channel. We open the channel, use it to call the service multiple times and then close it when we’re finished with it. The reason we use the same channel, rather than opening a new channel for each call, is because we don’t want multiple TCP channels open at once. It’s neater and less resource intensive to reuse the same channel. You also minimise the risk of exceeding the number of allowed open connection (some non server operating systems have a maximum number of TCP channels which can be open simultaneously).

NetTcpBinding netBinding = new NetTcpBinding();
ChannelFactory<ICustomerService> factory = new ChannelFactory<ICustomerService>(
    netBinding,
    "net.tcp://localhost:61501/CustomerService");
ICustomerService service = factory.CreateChannel();

// Get the collection of customers we need to save.
List<Customer> customers = GetCustomers();

for (int i = 0; i < customers.Count; i++)
{
    Customer customer = customers[i];
    CallState state = new CallState();
    state.Channel = (IChannel)service;
    if (i == customers.Count - 1)
    {
        state.CloseChannelInCallback = true;
    }

    Console.WriteLine("Calling BeginSave method for customer id {0}", customer.AccountId.ToString());
    service.BeginSave(customer, SaveCallback, state);
}

Console.ReadLine();

So to explain the above code, firstly a channel is opened using the ChannelFactory. Then inside the for loop, before making the call, I create an instance of a class I created named CallState. I use this to pass state information to the callback method. I use it to pass both the channel to the callback, and a property to indicate if it’s the last call. You need access to the channel in the callback because you need to call the End method. I also need to be able to tell the callback if it should close the channel (you need to close the channel whenever you are finished with it).

public class CallState
{
    public bool CloseChannelInCallback { get; set; }
    public IChannel Channel { get; set; }
}

The callback method is then as follows:

static void SaveCallback(IAsyncResult ar)
{
    CallState state = (CallState)ar.AsyncState;
    ICustomerService service = (ICustomerService)state.Channel;
    int id = service.EndSave(ar);

    Console.WriteLine("SaveCallback for customer id {0}", id); 

    if (state.CloseChannelInCallback)
    {
        state.Channel.Close();
        Console.WriteLine("Channel closed");
    }
}

Within the callback I therefore cast the AsyncState property of IAsyncResult to CallState. This then gives me access to the channel. Using the channel I then call then End method to get the result. I also check the CloseChannelInCallBack property to see if the channel should be closed.

Now I could have just passed the channel as the state object of the Begin method. But then I wouldn’t have known if I should close the channel in the callback. Using this approach also allows any other sort of useful information to be passed to the callback.

Categories: Development Tags:

Entity Framework Code First – Specify foreign key name in one to many relationship with fluent API

April 18, 2011 1 comment

This post shows how to create a one to many relationship and define the foreign key name.  Here we specify the foreign key name using the fluent API.

In this example we have two entities – a Customer and an Address.  Each Customer can have one or more Addresses associated with it.

So on the Customer class we have a collection of Addresses.  On the Address class we have a property for the Customer it relates to.

public class Customer
{
public int Id { get; set; }
public string CompanyName { get; set; }
public virtual ICollection<Address> Addresses { get; set; }

public Customer()
{
Addresses = new List<Address>();
}
}

public class Address
{
public int Id { get; set; }
public string Town { get; set; }
public Customer Customer { get; set; }
}

By default EF will create a foreign key on the Address table named Company_Id.  I want it to be named CompanyId.  This can be specified as follows using the fluent API:

HasRequired(p => p.Customer)
.WithMany(c => c.Addresses)
.Map(x => x.MapKey("CustomerId"));

To dissect this code:

HasRequired(p => p.Customer) – this is saying that an Address must have a Customer associated with it.

WithMany(c => c.Addresses) – on the other side of the relationship a Customer can have many Addresses.

.Map(x => x.MapKey(“CustomerId”) – this specifies the name of the foreign key column on the Addresses table.

The full code for this post can be found here (easiest to use an SVN client to download this):

https://subversion.assembla.com/svn/agilenet/tags/OneToMany

Entity Framework Code First – Same table relationship

April 12, 2011 Leave a comment

This post shows how to create a same table/entity relationship with Entity Framework Code First (RC).

Say for example that you have a Customer entity.  A customer can have a head office associated with it.  The head office is also a customer.  Your entity model would like something like this:


public class Customer
{
public int Id { get; set; }
public string CompanyName { get; set; }
public Customer HeadOffice { get; set; }
}

I then create the following configuration class:

public class CustomerConfiguration
  : EntityTypeConfiguration<Customer>
{

public CustomerConfiguration(): base()
{
HasKey(p => p.Id);
Property(p => p.Id)
    .HasColumnName("Id")
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
    .IsRequired();
Property(p => p.CompanyName)
    .HasColumnName("Name")
    .IsRequired();
HasOptional(p => p.HeadOffice).WithMany()
    .Map(p => p.MapKey("HeadOfficeId"));
ToTable("Companies");
}
}

Note the syntax for specifying the foreign key name.  Here I’m saying that the head office is optional.

The context can be created in the usual way.  The table is then created as follows:

 

 

 

 

 

 

The full code for this example can be found here (use an SVN client to download):

https://subversion.assembla.com/svn/agilenet/tags/EntityWhichReferencesSameType

Using Entity Framework 4.1 Code First with an existing database

April 11, 2011 7 comments

This post focuses on using the Entity Framework 4.1 RC Fluent API with an existing database.

When I say an existing database, what I really mean is that you’re not letting EF Code First auto generate the database for you.  So it could be that you like to create your entities and then manually craft the database.  Or you may have a separate team of developers who like to control and manage the database.

This article refers to the fluent API which is part of the Code First approach to the using the Entity Framework.  Code First can create the database for you based on your entities and entity relationships, but as I mention above you may not want Code First to do this.

Using EF Code First in this way is seen a core aspect of Code First by the EF team at Microsoft.  So far I have to say I really like this approach, no large edmx files to worry about, instead it’s all controlled through code.  Additionally the entities are plain old CLR objects (POCO).  This means that your entities (and thus the assembly they are contained in) don’t need to reference the Entity Framework.

The following example shows how to create an entity model, then manually create your database and then map those entities to your database.  Finally it shows using the DatabaseContext to save and retrieve entities.

Create the entities

Here we have a company class and a country class.  Each company has a country associated with it.  There is no association going the other way:


public class Company
{
public int Id { get; set; }
public string CompanyName { get; set; }
public Country HomeCountry { get; set; }
}

public class Country
{
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}

Create the database

Next we create the database.  We could let EF do this for us, but here we want full control over the new database (or it could be an existing database you’re connecting to):

CREATE DATABASE CodeFirst;
GO
Use CodeFirst
create table Companies	(
Id int identity(1,1) not null,
HomeCountryId int not null,
Name varchar(20) not null,
constraint PK_Companies primary key clustered (Id))

create table Countries	(
Id int identity(1,1) not null,
Code varchar(4) not null,
Name varchar(20) not null,
constraint PK_Countries primary key clustered (Id))

alter table Companies
add constraint FK_Company_HomeCountry foreign key (HomeCountryId)
references Countries (Id) on delete no action

Mapping the entities to the database

So we now have the entities and the database.  Next the fun bit, mapping the two together using the fluent API which is part of EF Code First.

Firstly we create a configuration class for each entity which maps between the entity and the database:

public class CompanyConfiguration: EntityTypeConfiguration<Company>;
{

public CompanyConfiguration(): base()
{

HasKey(p => p.Id);
Property(p => p.Id).
    HasColumnName("Id").
    HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).
    IsRequired();
Property(p => p.CompanyName).
    HasColumnName("Name").
    IsRequired();
HasRequired(x => x.HomeCountry).
    WithMany().
    Map(x => x.MapKey("HomeCountryId"));
ToTable("Companies");
}

}

public class CountryConfiguration: EntityTypeConfiguration<Country>;
{

public CountryConfiguration(): base()
{
HasKey(p => p.Id);
    Property(p => p.Id)
    .HasColumnName("Id")
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
    .IsRequired();
Property(p => p.Code)
    .HasColumnName("Code")
    .IsRequired();
Property(p => p.Name)
    .HasColumnName("Name")
    .IsRequired();
ToTable("Countries");
}

}

The most difficult part of the above is understanding the syntax for defining the relationship between the Company and Country entity.  We actually wouldn’t need to do this if we had named the FK column HomeCountry_ID (as this is what EF will use by default).  In our case though we don’t use underscores so we have to tell the fluent API what the name of the column is.  So within the configuration class for the Company we say HasRequired(x => x.HomeCountry) – this tells EF that a home country must be set.  We then define the relationship going back the other way, in this case we say WithMany() – however, in our example there is no relation going the other way, so we leave this empty.  Finally we use Map(x => x.MapKey(“HomeCountryId”)) to specify the foreign key name.

It should be noted that an alternative to the Fluent API is to use attributes on your entity.  I like to keep the entities clean though, even from attributes.  I’ll talk about attributes in a future post though.

Creating the context

It is the context that we code against to add and remove entities to and from the database.  We create our context by creating a class which inherits from DbContext:

public class MyContext: DbContext
{

public DbSet<Company> Companies { get; set; }
public DbSet<Country> Countries { get; set; }

public MyContext(string connectionString): base(connectionString)
{
Database.SetInitializer<MyContext>(null);
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CountryConfiguration());
modelBuilder.Configurations.Add(new CompanyConfiguration());
base.OnModelCreating(modelBuilder);
}

}

Above I have created a couple of properties using DbSet for our entities that we wish to expose.

In the constructor we then tell EF Code First not to attempt to create a database as we are using our own.  We then override the OnModelCreating method and load our configuration classes.

That’s it, we can then start using the context.

Using the context

In this example, we’re starting off with an empty database:

class Program

{

private const string ConnectionString = @&amp;quot;Server=.sql2005;Database=CodeFirst;integrated security=SSPI;&amp;quot;;

static void Main(string[] args)
{

// Firstly, create a new country record.
Country country = new Country();
country.Code = "UK";
country.Name = "United Kingdom";

// Now create an instance of the context.
MyContext myContext = new MyContext(ConnectionString);

// Set the state of the new entity as added (note that this also adds it to the context).
myContext.Entry(country).State = EntityState.Added;
myContext.SaveChanges();

Console.WriteLine(&amp;quot;Saved Country&amp;quot;);

// Now insert a Company record
Company company = new Company();
company.CompanyName = "AccessUK";

// Assign our new Country instance to the Company instance
// (we could just use the instance we created above, but I want to show how
// easy it is to query the context)
company.HomeCountry = myContext.Countries.First(e => e.Code == "UK");

// This is another way of adding an entity to the conext.
myContext.Companies.Add(company);

// Save the new company.
myContext.SaveChanges();
Console.WriteLine("Saved Company");

// Retrieve the company we just saved
Company savedCompany = myContext.Companies.First(e => e.CompanyName == "AccessUK");
Console.WriteLine("Retrieved Company");

Console.ReadLine();
}

}

In the above example, I create a new Company instance, save it to the database then create a new Company to which I assign the Country.  I then finish by retrieving the Company instance.

The full example created above can be found here (use an SVN client to download it):

https://subversion.assembla.com/svn/agilenet/tags/EFCodeFirstExampleForBlogPost

Update 19/11/11 – There is now a power tool available which creates the entities and the mappings from an existing database, see http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d

Entity Framework 4.1 RC Code First

April 6, 2011 Leave a comment

This week we started using the release candidate of Code First in our production code.  During the course of the various CTPs it’s changed a fair amount, as you would expect.  It will be interesting to see what the RC is like.  More posts will follow!

Categories: Development Tags:

WCF – DataContractSerializer v NetDataContractSerializer

October 2, 2010 Leave a comment

Moving our application from .NET Remoting to WCF was always likely to present something of a challenge. We made this move 2 years and I recently looked at this area again.

This post explains the series of obstacles that helped us choose between the DataContractSerializer and NetDataContractSerializer.

About our application:

  • It has in the region of 1000 business entities which we need to transfer over the wire.
  • Our business entities are POCO.
  • There are a number of places where we have cyclic references e.g. a child object references its parent.

When I first looked at moving to WCF I set out some goals:

  • Would like to use WCF in as standard a way as possible.
  • Would like to make our services available to 3rd parties.
  • Should consider the use of client side code generation with WCF.

I decided that I would use the default DataContractSerializer. Although this can work with POCO it seems best practice to decorate your classes with the [DataContract] and [DataMember] attributes.

Cyclic References

At this stage I tested the service and discovered the first problem:

There was an error while trying to serialize parameter http://tempuri.org/:GetCustomer. The InnerException message was ‘Object graph for type ‘Customer’ contains cycles and cannot be serialized if reference tracking is disabled.’. Please see InnerException for more details.

This is due to reference types being serialized by value. Amending the attribute on the class in question to be [DataContract(IsReference=true)] I was then given the following exception:

There was an error while trying to serialize parameter http://tempuri.org/:GetCustomer. The InnerException message was ‘Object graph for type ‘Account’ contains cycles and cannot be serialized if reference tracking is disabled.’. Please see InnerException for more details.

Account is the base class for Customer. I therefore followed the inheritance chain adding IsReference=true to the base classes. However, it then transpires that any classes which inherit from these must also have this attribute. I therefore ended up with pretty much all classes having the IsReference=true attribute. Not in itself a problem, but it’s certainly true to say that it’s not plain sailing.

KnownType attribute

Because the DataContractSerializer does not include CLR type information in the serialized XML you have to decorate your service methods with the known types attributes. You use these attributes to specify the types that may be returned. An example of why this is necessary can be found here:

http://blogs.msdn.com/b/sowmy/archive/2006/06/06/all-about-knowntypes.aspx

[Edit - I believe this has been resolved in .NET Framework 4]

Generating code with SVCUtil

After adding the above attributes I then thought I’d try generating some client side code using SVCUtil (or from the Add Service Reference Dialog in Visual Studio). Because our business entities contain significant logic we want to reference the business logic assembly on the client and let SVCUtil generate the code to call the services (in other words not create proxy representations of the classes).

Next problem, there is a bug in SVCUtil whereby it can’t generate code if IsReference=true and reuse types from reference assemblies is on:

http://blogs.msdn.com/b/distributedservices/archive/2010/02/04/wcf-client-issue-with-reuse-types-from-referenced-assemblies.aspx?wa=wsignin1.0

The above is likely to be fixed, but nonetheless for now it’s a problem.

I therefore started to look at solutions to the above problems. One would be use Data Transfer Objects (DTO) to move the data over the wire. This would however require us to create a complete set of new objects.

Taking a different approach

It was at this stage that I started to realise that using WCF in this way maybe just isn’t the right approach. Although there is the possibility that 3rd parties may want to consume our services, most of the time it will be the client (that we control) that will be consuming them. WCF brings together a number of technologies which were previously disparate and to an extent tries to be all things to all people. However, once you look inside there are a number of different ways of using it.

One of these alternatives is to use the NetDataContractSerializer. This differs in one important way, .NET type information is included in the serialized XML. It works with our existing classes which already have the Serializable attribute or that implement ISerializable. It brings the following advantages:

  • It works with our object graphs – no errors about cyclic references.
  • No need to decorate classes with attributes to tell the serializer how to serialize it.
  • No need to use the KnownType attributes.

The downside is that it isn’t interoperable to non .NET clients, however, I don’t see any non .NET clients using our object model as is. The solution for non .NET clients is probably to create a separate much simplified WCF service using the DataContractSerializer. The NetDataContractSerializer requires the client to reference our .NET assemblies, but this is something we wanted anyway.

Microsoft don’t make it easy to use the NetDataContractSerializer. This is because they want to encourage interoperability through the use of the DataContractSerialzer. As I’ve demonstrated above though, it doesn’t really work for all scenarios. The following explains how to use the NetDataContractSerializer:

http://www.pluralsight-training.net/community/blogs/aaron/archive/2006/04/21/22284.aspx

It was also at this point that I realized that using SVCUtil to generate client data may not be the best solution. Making calls using the ChannelFactory against a shared interface may be a better approach. Search for ChannelFactory v Proxies to see what I mean.

Conclusion

If you control both ends of the pipe, the NetDataContractSerializer is worth considering.  If there weren’t the barriers to using the DataContractSerializer then we would have used it, but once implemented the NetDataContractSerializer does exactly what we need it to with minimal fuss.  If at some stage we need non .NET clients, or .NET clients which don’t have a reference to our assemblies, to connect to our services, then we’ll look at creating a simpler set of services using the DataContractSerializer.

Categories: Development Tags:
Follow

Get every new post delivered to your Inbox.