Pages

Saturday, March 12, 2011

Silverlight: Manage XAP Files

The XAP file size for Silverlight projects can become quite large if they are not managed properly. This will cause the initial loading time to increase and slow performance of your application.

Manage common assemblies

To address the duplication of shared assemblies in multiple XAP files, we have couple of options.
  1. The first is to reference all the shared assemblies in the shell application XAP file. Then we can go to the reference of these shared assemblies in each of the modules and set the Copy Local property on the reference to false. This causes the referenced shared assemblies to not be included in the compiled XAP file for that module. However, at runtime, the one provided by the shell application XAP file will also be available to the modules.

    Advantages:
    • All the common assemblies are downloaded once.
    • XAP file size for other modules decreases.
    • Subsequent requests are faster.

    Disadvantages:
    • The initial download size will be large.
  2. The second approach is to use application library caching in Silverlight. To use this feature, we need to go to the properties of all the Silverlight projects and select the check box labeled Reduce XAP size by using application library caching. When we do this, any referenced assemblies that have the right metadata files collocated with them will not be included in the XAP file. Instead, they will be placed in a separate .zip file, and the .zip file will be referenced by the XAP file’s ApplicationManifest.xaml file as an external part. These files are added to the browser cache so that they can be reused on subsequent visits. All downloaded files are subject to the caching configuration settings on the server and in the browser. In a typical configuration, files are downloaded only if they are not in the cache or if they are newer than the cached versions. Libraries from Prism, Silverlight SDK and Toolkit have the required metadata files to use this feature.

    If you want to leverage of the functionality for our assemblies, we need to provide the proper metadata files. More about this has been discussed in the following article: How to: Use Application Library Caching

    You can test this option with your application using Fiddler, and see that shared assemblies are only downloaded when they are required and are not downloaded on subsequent requests.

    Advantages:
    • XAP file size of all the module decreases.
    • Common assemblies are downloaded separately as they are required.
    • Downloaded common assemblies are cached and available to all modules until new versions are provided. (subject to the caching configuration settings on the server and in the client browser)

    Disadvantages:
    • We cannot use application library caching and out-of-browser support in the same application. Out-of-browser applications require all startup assemblies to reside in the application package.
    • We need to ensure the clients are not using old cached assemblies when new versions of the common assemblies are deployed.

Improve XAP file compression

XAP files are basically just standard ZIP files with different extension, so we can use compression tools (like Winrar) to decrease the file size even more by using the best compression algorithm.

We can create batch file that can be added to all the Silverlight projects to automatically re-compress the project’s XAP file more efficiently. And we can do this easily by adding command in the project’s post-build events. Around 5% to 20% reduction can be achieved depending on the contents of the XAP file.

Sunday, January 16, 2011

The Repository Pattern - Entity Framework

Introduction
In many applications, business logic accesses data from data stores. There are lot of potential issues when accessing them directly, for example:
  • Code duplication
  • Higher chances of programming errors
  • Problems in testing business logic in isolation from external dependencies
  • Difficulty in implementing centrally managed consistent rules and logic
So it is a good idea to build a layer of abstraction which mediates between the business layer and data source layer of the application. This is where repository pattern comes in to achieve our objectives.

What is Repository
As described on Martin Flower's website:

"A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers."

Implementation
We will discuss the implementation of repositories in context of DDD(domain driven design) for entity framework. Using generics we will create a base repository which will have all the common functionality. And then we will inherit from the base repository to create model/domain specific repositories.

Repository Interface
This is how the repository interface will look like. IRepository<T> is the contract where T is a POCO class. For testing we can later write an fake implementation to remove the dependency.

    public interface IRepository<T> where T : class
    {
        IQueryable<T> GetQuery();

        IEnumerable<T> GetAll();
        IEnumerable<T> Find(Expression<Func<T, bool>> where);
        T Single(Expression<Func<T, bool>> where);
        T First(Expression<Func<T, bool>> where);

        void Delete(T entity);
        void Add(T entity);
        void Attach(T entity);
        void SaveChanges();
    }

Generic Repository Implementation
The base repository takes an IObjectContext as a constructor argument for dependency injection.

    public abstract class EFRepositoryBase<T> : IRepository<T> where T : class
    {
        readonly IObjectContext _objectContext;
        readonly IObjectSet<T> _objectSet;

        public EFRepositoryBase(IObjectContext objectContext)
        {
            _objectContext = objectContext;
            _objectSet = _objectContext.CreateObjectSet<T>();
        }

        public IQueryable<T> GetQuery()
        {
            return _objectSet;
        }

        public IEnumerable<T> GetAll()
        {
            return GetQuery().ToList();
        }

        public IEnumerable<T> Find(Expression<Func<T, bool>> where)
        {
            return _objectSet.Where(where);
        }

        public T Single(Expression<Func<T, bool>> where)
        {
            return _objectSet.Single(where);
        }

        public T First(Expression<Func<T, bool>> where)
        {
            return _objectSet.First(where);
        }

        public void Delete(T entity)
        {
            _objectSet.DeleteObject(entity);
        }

        public void Add(T entity)
        {
            _objectSet.AddObject(entity);
        }

        public void Attach(T entity)
        {
            _objectSet.Attach(entity);
        }

        public void SaveChanges()
        {
            _objectContext.SaveChanges();
        }
    }

Domain specific repository
In these derived repositories you can add the domain/model specific query operations. Here is how the interface and implementation of a User model repository will look like.

    public interface IUserRepository : IRepository<User>
    {
        //add user specific operations
    }

    public class EFUserRepository : EFRepositoryBase<User>, IUserRepository
    {
        public EFUserRepository(IObjectContext objectContext)
            : base(objectContext)
        {
            //add user specific operations
        }
    }