2013-02-13 4 views
5

Я разрабатываю API REST с использованием веб-API ASP.NET, Code-First Entity Framework 5 и SQL Server 2012, и мне нужно иметь возможность версии API. Я прочитал несколько сообщений в блогах и статей об указании версии API либо в URI, либо в пользовательском HTTP-заголовке и с помощью пользовательского IHttpControllerSelector, чтобы выбрать различные ApiControllers на основе указанной версии. Все это имеет смысл.API-интерфейс с API-интерфейсом ASP.NET и инфраструктурой Entity Framework

То, что я пытаюсь выяснить, - как управлять последствиями версий за пределами уровня веб-API, в частности, в Entity Framework. Как мне перейти на разработку моего DbContext, не нарушая устаревшие версии API? Могу ли я также версия DbContext? И если да, то как?

ответ

3

То, что я закончил, было комбинацией шаблона репозитория с ответом Пабло. Суть в том, что мои модели EF версий, я использую EF Code-First Migrations для переноса базы данных в новые версии моделей, мой DbContext всегда работает с последней версией моделей, я разработал ряд конкретных репозиториев чтобы каждый реализовал интерфейс IRepository<TItem> ниже.

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

Одна реализация IRepository<TItem> является DbRepository<TItem>, который оборачивает рамочное предприятие код, используемый для разговора с базой данных.

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

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

    // Implementation of IRepository<TItem> methods 
} 

Другая реализация IRepository<TItem> является TypeConversionRepository<TExternal,TInternal>, который является абстрактным классом, который облегчает преобразование из одного типа модели к другой.

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.

1

Я думаю, что это хорошая практика для разработки веб-API и базовой модели БД отдельно (или EF-модели). Это означает модель DTO для Web API, которая сопоставляется с EF-моделью в веб-API. Этот слой косвенности даст вам возможность вносить изменения, которые могут повлиять только на веб-API или модель EF. Кроме того, новая версия в Web API может не повлиять непосредственно на существующую модель EF. Например, новая версия веб-API, в которой используется совершенно другой набор таблиц.

С уважением, Пабло.

Смежные вопросы