Click here to Skip to main content
Click here to Skip to main content
Go to top

WCF by Example - Chapter XVI - EF 5 & SQL CE - AzureWebSites Deployment

, 31 Jan 2013
Rate this:
Please Sign up or sign in to vote.
EF Code First implementation of generic repository and unit of work. With deployment to Azure web sites using SQL Compact.


 

Previous
Chapter XV
 

The Series

 

WCF by example is a series of articles that describe how to design and develop a WPF client connected to a server component using WCF. For persistence purposes, in the server side, we have already covered how to implement NHibernate, InMemory and RavenDB. The series introduction describes the scope of the articles and discusses the architect solution at a high level. The source code for the series is found at CodePlex.

 

Chapter Overview

This chapter discusses what it takes to implement EF5 Code First using SQL Compact on AzureWebServices and then get a WPF client running in your local machine to interact with the services deployed on Azure.

In relation to the Azure deployment, I used VS2010; if you are using VS2012 you probably find the deployment easier as the IDE is fully integrated with Azure. I am not covering in this article the steps for deployment if you have installed the Azure SDK, instead, the article describes how to manually deploy the server components using an FTP client.

For those new to the series, the persistence components of the eDirectory solution are designed around the unit of work and repository patterns. The first sections in this chapter cover the implement of those patterns using EF5 Code First.

 

The following is an example of the code used in the server components:

    public CustomerDto UpdateCustomer(CustomerDto dto)
    {
01		return ExecuteCommand(locator => UpdateCustomerCommand(locator, dto));
    }
 
    private CustomerDto UpdateCustomerCommand(IRepositoryLocator locator, CustomerDto dto)
    {
02		var instance = locator.GetById<Customer>(dto.Id);
03		instance.Update(locator, dto);            
		return Customer_to_Dto(instance);
    }

Line 01: Entry point for the customer service to update an existing instance

Line 02: Using the Dto.Id property we use the Locator to resolve the customer instance

Line 03: Then we delegate to the domain class to update itself passing the locator and the Dto instances

For a more detailed discussion of the patterns used in the solution, you may want to look at the following chapters:

Entity Framework Implementation - Overview

I wanted to achieve the following goals implementing EF in the eDirectory solution:

  • Minimal changes to the domain entities
  • If feasible, do not make code changes in the service implementation
  • The final solution should not break the other existing implementations

The following were the most relevant changes taken to get EF working:

  • Replace the specialised Iesi collections and use .NET collections instead
  • Inner Mapping classes were added inheriting from EntityTypeConfiguration in the entity classes

  • The introduction of a new FlushModifications method in the RepositoryLocator

The first change, the one regarding the collections, was easy to resolved. The one regarding the Mapping inner classes is a way to replace the mapping configuration we had in NHibernate. I don't like to have persistence declaration within the entity but it was an easy way to manage mapping declarations for non-public members, which is the case of the collections in the eDirectory solution. The last one is relevant as EF manages identity columns in a different fashion than NHibernate does when a new entity is created. When NHibernate always provides an Id value once the Save method is invoked, EF does not do so when the Add method is invoked. The FlushModifications provides a mechanism so all modifications are persisted so the new entities get the Id property populated, the process takes place without commiting the current transaction.

EF Repository

This is the third time we implement this pattern within the series; we have already discussed the NHibernate and the RabenDB implementations. In any case, a quick remainder of what a Repository means within the eDirectory solution; in first place it is a generic class that exposes basic CRUD operations for a domain entity, but it also exposes a FindAll method that returns a IQueryable instance. I have used the EF linq implementation: AsQueryable to provided such a functionality. The following code is the final EF implementation:

    public class RepositoryEF<TEntity>
        : IRepository<TEntity> where TEntity : class
    {
        private readonly IDbSet<TEntity> _dbSet;
 
        public RepositoryEF(IDbSet<TEntity> dbSet)
        {
            _dbSet = dbSet;
        }
        
        #region Implementation of IRepository<TEntity>
 
        public TEntity Save(TEntity instance)
        {
            return _dbSet.Add(instance);
        }
 
        public void Update(TEntity instance)
        {
        }
 
        public void Remove(TEntity instance)
        {
            _dbSet.Remove(instance);
        }
 
        public TEntity GetById(long id)
        {
            return _dbSet.Find(id);
        }
 
        public IQueryable<TEntity> FindAll()
        {
            return _dbSet.AsQueryable();
        }
 
        #endregion
    }

The IDbSet provides all the functionality that is required, implementing the IRepository pattern using EF was very straight forward.

EF Repository Locator

The IRepositoryLocator main responsibility is the creation of entity repositories within the transaction, the first time a repository is used the locator creates it. In the case of the EF implementation, it also exposes the FlushModifications that it was mentioned above. The code, again, is straight forward:

    public class RepositoryLocatorEF
        : RepositoryLocatorBase
    {
        private readonly DbContext _dbContext;
 
        public RepositoryLocatorEF(DbContext dbContext)
        {
            _dbContext = dbContext;
        }
 
        #region Overrides of RepositoryLocatorBase
 
        public override void FlushModifications()
        {
            base.FlushModifications();
            _dbContext.GetObjectContext().SaveChanges(SaveOptions.DetectChangesBeforeSave);
        }
 
        protected override IRepository<TEntity> CreateRepository<TEntity>()
        {
            return new RepositoryEF<TEntity>(_dbContext.Set<TEntity>());
        }
 
        #endregion
    }

So the locator keeps a reference to a DbContext that helps creating repository instances but it also helps in getting the ObjectContext that allows us to save the changes in the middle of a transaction without committing. By the way, the GetObjectContext is just an extension method that you can find at the DbContextExtensions under the TransManager folder.

EF Transaction Manager

This class is the one that required the most code, nevertheless, it was not too bad, in 70 LOC we have a full transactional EF component in place. As its name indicates, this class is responsible for managing all the entity changes within a transaction; we use this class within a using statement and then we invoke the ExecuteCommand that gives access to a RepositoryLocator; the use of lambdas delegating to helper methods is a must when using this pattern. When the using statement is complete, the transaction manager looks after committing all the changes. If an exception takes place, a rollback is actioned without any additional code statements in the business logic. Following is the code:

    public class TransManagerEF
        : TransManagerBase
    {
        private readonly DbContext _dbContext;
        private DbTransaction _transaction;
 
        public TransManagerEF(DbContext dbContext)
        {
            _dbContext = dbContext;
            var locator = new RepositoryLocatorEF(_dbContext);
            Locator = locator;
        }
       
        public override void BeginTransaction()
        {
            base.BeginTransaction();
            if (_dbContext.GetObjectContext().Connection.State != ConnectionState.Open)
            {
                _dbContext.GetObjectContext().Connection.Open();
            }
            _transaction = _dbContext.GetObjectContext().Connection.BeginTransaction();
        }
 
        public override void CommitTransaction()
        {
            base.CommitTransaction();
            _dbContext.GetObjectContext().SaveChanges(SaveOptions.DetectChangesBeforeSave);
            _dbContext.GetObjectContext().AcceptAllChanges();    
            _transaction.Commit();
        }
 
        public override void Rollback()
        {
            base.Rollback();            
            _transaction.Rollback();
        }
 
        ...
    }

Again a DbContext instance is the key EF component used here, in fact, the same instance is passed to the RepositoryLocator created with this TransactionManager. You can see how full control over the connection is taken using the ObjectContext, the DbContext instance is not good for what we need. The ObjectContext provides all the advanced functionality that is required to manage the transaction instead. Worth to mention is the DbTransation instance that allows to rollback the changes if required.

EF Transaction Manager Factory

The only role for this class is the creation of TransactionManager instances. The code is the following:

    public class TransManagerFactoryEF
        : ITransFactory
    {
        public IModelCreator ModelCreator { get; private set; }
 
        public TransManagerFactoryEF(IModelCreator modelCreator)
        {
            ModelCreator = modelCreator;
        }
 
        #region Implementation of ITransFactory
 
        public ITransManager CreateManager()
        {
            return new TransManagerEF(new eDirectoryDbContext(ModelCreator));
        }
 
        #endregion
    }

The main difference with other implementations is the IModelCreator, this is an EF Code First requirement; it helps in the EF initialisation and in the mapping between domain entities and the database tables. In first place we have a new class eDirectoryDbContext:

    public class eDirectoryDbContext : DbContext
    {
        public IModelCreator ModelCreator { get; private set; }
 
        public eDirectoryDbContext(IModelCreator modelCreator): base("eDirectory")
        {
            ModelCreator = modelCreator;
        }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            ModelCreator.OnModelCreating(modelBuilder);            
        }
    }

This is the common pattern in EF, it permits to initialise the persistence layer. One difference with other common implementation is that it does not declare a DbSet property for each entity/aggregation; instead we delegate to the IModelBuilder to do so. In this way this class is very generic and does not have a direct dependency to our domain/entities.

It is worth noting how the constructor delegates to the base class passing the connection name in the App/Web configuration file. You may want to articulate a more flexible mechanism in your own implementation so this is not hard coded in your solution.

The IModelBuilder implementation is straight forward:

    public class ModelCreator:IModelCreator
    {
        #region Implementation of IModelCreator
 
        public void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            modelBuilder.Configurations.Add(new Customer.Mapping());                        
            modelBuilder.Entity<Address>();
        }
 
        #endregion
    }

It is just pretty much a fluent declaration of our mappings, a very short one though; this class resides on the Domain project and it gets injected at run time on the TransManagerFactoryEF. Then the first time a DbContext is used, this class is invoked and configures EF so it can work with our database. EF is quite smart linking the Poco classes to the database, in our case, it just needs a little help.

In first place, you can use DataAnnotation attributes, the EntityBase uses the [Key] attribute to indicate which is the PK in all our entities. Then you can use the generic Entity method in the ModelBuilder (as it was done with the Address class), or you can also delegate to an EntityTypeConfiguration class. This is the case for the Customer entity:

    [JsonObject(IsReference = true)]
    public class Customer
        :EntityBase
    {
        protected Customer()
        {
            AddressSet = new HashSet<Address>();
        }
 
        ...        
        
        protected virtual ICollection<Address> AddressSet { get; set; }
 
        ...
 
        public class Mapping : EntityTypeConfiguration<Customer>
        {
            public Mapping()
            {
                HasMany(c => c.AddressSet).WithRequired(a => a.Customer);
            }
        }
    }

The Mapping class is internal so it can access the AddressSet collection that is not publicly exposed. The customised mapping declares the collection using the "hidden" collection and its navigation mapping with the Address entity. As I said before, you may not like to include this sort of dependency in your entities, another approach is to use partial classes to achieve the same result.

Worth to notice, we don't really need to declare the Address entity in the ModelBuilder, EF can work out the configuration mappings from the aggregate root entities, in this case, declaring the Customer is sufficient for EF to know about the Address.

WPF Client Configuration with EF and SQL Compact

To get the WPF client to use EF to connect to a SQL Compact database you have to add the following section to your configuration file:

  <connectionStrings>
    <add name="eDirectoryDbContext" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=|DataDirectory|\eDirectory.sdf;default lock timeout=60000" />
  </connectionStrings>

Watch out for the connection name, it is the same one that we use declaring the eDirectoryDbContext but without the "Context" suffix. As you can see we indicate that the database is to be found at the DataDirectory, that is, the output folder for a client application or the App_Data folder in a web application. Then add the EntityFramework.SqlServerCompact package using NuGet, it will also add the following dependencies:


Then check that the following lines were added to your configuration file:

  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="System.Data.SqlServerCe.4.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>

In this example, the SQL Compact database was already created. It should not be difficult to let EF Code First to generate the database if needed. You may also install the SQL Server Compact Tools VS Extension. It provides some nice functionality for creating and managing compact databases.

At this point you should try to test the application locally and when you are sure things are working, then you should be ready to deploy to the web.

Deployment to Azure WebSites

You may know that currently Azure Web Sites offer free hosting for small web site deployments, you may want to check for pricing and features, deployment using VS2010 or VS2012 is very straight forward if the Azure SDK is installed in your machine. You may check out this video from Scott Hanselman or a full article regarding Azure WebSites deployment.

But you can also deploy the application using a FTP client, if you do so, you don't need to install the SDK at all. This article contains two set of binaries, one with the WPF client configured to execute connected to the WcfByExamples server in Azure. The other set is the server side artefacts so you can try to deploy it by yourself.

WPF Client

Lets try to see how to get the client working with the Azure WebSite, firstly, download the WPF Client binaries and execute the application, if you get to the following window and you can see data, then you are connected to the Azure web site:


If you have a look at the client configuration file, you can see the WCF endpoits configured to connect to the Azure web site:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="SpringConfigFile" value="file://WcfConfiguration.xml" />
  </appSettings>
  <system.serviceModel>
    <client>
      <endpoint address="http://wcfByExample.azurewebsites.net/CustomerWcfService.svc/CustomerServices" 
				binding="basicHttpBinding" 
				contract="eDirectory.Common.ServiceContract.ICustomerService" 
				name="BasicHttpBinding_ICustomerService">
      </endpoint>
      <endpoint address="http://wcfByExample.azurewebsites.net/AddressWcfService.svc/AddressServices" 
				binding="basicHttpBinding" 
				contract="eDirectory.Common.ServiceContract.IAddressService" 
				name="BasicHttpBinding_IAddressService">
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

The client configuration is very simple and because it uses the basic Http binding you should have not trouble to get it working in most networks.

Server Deployment

As mentioned earlier, with the Azure SDK the deployment is easy from VS; here instead, I am going to explain how to deploy the server solution manually, you need to do the following:

  • Download the eDirectory server binaries contained within this article
  • Install a FTP client, I used FileZilla
  • Create an account in Azure so you can create a web site
  • Deploy the server binaries
  • Point the WPF client to your site

Create Web Site in Azure

Once you have an Azure account, you need to create a web site using the 'quick create' option:


Then, give it a name:


Once it is created, we need to set the FTP user and password. Select 'Deployment Credential' option on the right side and enter a user name and password:


At this point, you should be able to gather the following FTP details in the dashboard on the right side:


With that it should be easy to connect using the FTP client:


Copy all the server files, including the App_Data and bin folders, to the wwwroot folder in the Azure site. When you are finished, you can configure the client to point to your site. Just change the eDirectory.WPF.exe.config so the end points are renamed using your site name:


Enable NHibernate Instead

You may want to change the server side to use NHibernate instead, it is just one liner change. Open the web.config file and change the appSetting 'SpringConfigFile' so is set to ServerNhConfiguration.xml instead:

Conclusion

Finally I got the time to implement EF on the eDirectory series. I was surprised how little mapping was required to get the solution working once I put in place the main EF components. On the other hand, I struggled with the EF API when I was trying to implement the transaction manager; it seems that the DbContext to be the recommended object to use but then it is in the ObjectContext where all the advance functionality is available.

I hope you like the combination of SQL Compact and ORM solutions, I think is a winner for small/medium applications. It is very easy to deploy on the web and it performs very well.

The last but not the least, I hoped the article convinces how easy is the deployment of your apps to Azure these days ... and you get 10 web sites for free, small ones but for many it may well be a good start point

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Enrique Albert
Software Developer (Senior)
Ireland Ireland
No Biography provided
Follow on   Twitter

Comments and Discussions

 
QuestionEF implementation for more than one database PinmemberiProg726-Aug-13 8:18 
AnswerRe: EF implementation for more than one database PinmemberEnrique Albert26-Aug-13 12:22 
GeneralRe: EF implementation for more than one database PinmemberiProg727-Aug-13 3:02 
QuestionCost in Azure Pinmemberkiquenet.com3-Jun-13 20:19 
AnswerRe: Cost in Azure [modified] PinprofessionalEnrique Albert3-Jun-13 22:59 
QuestionEF Implementation question PinmemberDarius Bakunas28-May-13 6:47 
AnswerRe: EF Implementation question PinprofessionalEnrique Albert28-May-13 10:55 
GeneralMy vote of 5 Pinmembercaosnight14-Feb-13 15:02 
GeneralRe: My vote of 5 PinmemberEnrique Albert14-Feb-13 23:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 31 Jan 2013
Article Copyright 2013 by Enrique Albert
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid