API versions with ASP.NET Web API and Entity Framework

I am developing a REST API using the ASP.NET Web API, Code-First Entity Framework 5 and SQL Server 2012, and I need to be able to version the API. I read several blog posts and articles about specifying an API version either in a URI or in a custom HTTP header and using a custom IHttpControllerSelector to select different ApiControllers based on the specified version. All this makes sense.

What I'm struggling to understand is to manage the consequences of versions beyond the level of the web API, in particular in the Entity Framework. How do I go about developing my DbContext without breaking old versions of the API? Can I also version DbContext? And if so, how?

+5
source share
2 answers

What I finished is a combination of a repository template with Pablo's answer. The bottom line is that my EF models are versioned, I use EF Code-First Migrations to transfer the database to new versions of models, mine DbContextalways works with the latest version of models, I have developed a number of specific repositories, each of which implements the interface IRepository<TItem>below.

public interface IRepository<TItem> : IQueryable<TItem>, ICollection<TItem>, IDisposable
    where TItem : class
{
    void Update(TItem item);
    void SaveChanges();
}

One implementation IRepository<TItem>is one DbRepository<TItem>that wraps the entity frame code used to communicate with the database.

public class DbRepository<TItem> : IRepository<TItem> 
    where TItem : class
{
    private MyDbContext _db;

    public DbRepository()
    {
        _db = new MyDbContext();
    }

    // Implementation of IRepository<TItem> methods
}

Another implementation IRepository<TItem>is that TypeConversionRepository<TExternal,TInternal>, which is an abstract class that facilitates the conversion from one type of model to another.

public abstract class TypeConversionRepository<TExternal, TInternal> : IRepository<TExternal>
    where TExternal : class
    where TInternal : class
{
    protected IRepository<TInternal> InternalRepository { get; set; }

    protected abstract TInternal ConvertInbound(TExternal externalItem);

    protected abstract TExternal ConvertOutbound(TInternal internalItem);

    // Implementation of IRepository<TItem> methods
}

, , ConvertInbound() ConvertOutbound() TExternal TInternal . , 2 MyModel, 2 MyModelRepository; 2 , 1 2 1.

namespace Models.v1
{
    public class MyModel
    {
        public int Id { get; set; }
        public string MyProperty { get; set; }
    }

    public class MyModelRepository : TypeConversionRepository<Models.v1.MyModel,Models.v2.MyModel>
    {
        MyModelRepository()
        {
            this.InternalRepository = new Models.v2.MyModelRepository();
        }

        protected override TInternal ConvertInbound(TExternal externalItem)
        {
            return new Models.v2.MyModel
            {
                Id = externalItem.Id,
                MyNewProperty = externalItem.MyProperty
            };
        }

        protected override TExternal ConvertOutbound(TInternal internalItem)
        {
            return new Models.v1.MyModel
            {
                Id = internalItem.Id,
                MyProperty = internalItem.MyNewProperty
            };
        }
    }
}

namespace Models.v2
{
    public class MyModel
    {
        public int Id { get; set; }
        public string MyNewProperty { get; set; }
    }

    public class MyModelRepository : DbRepository<MyModel>
    {

    }
}

v1 ApiController v1 MyModelRepository, v2 ApiController v2 MyModelRepository, , v2.

+3

, -API ( EF). DTO Web API, EF- -API. , -API EF. , Web API EF. , -API, .

, .

+1

All Articles