我正在使用ASP.NET Web API,Code-First Entity Framework 5和SQL Server 2012开发REST API,我需要能够对API进行版本控制。我已经阅读了一些博客文章和文章,关于在URI或自定义HTTP标头中指示API版本,并使用自定义IHttpControllerSelector根据指定的版本选择不同的ApiControllers。这一切都有道理。
我正在努力弄清楚如何管理Web API层以外的版本控制的影响,特别是在Entity Framework中。如何在不破坏旧版本API的情况下改进我的DbContext?我也可以对DbContext进行版本控制吗?如果是这样,怎么样?
答案 0 :(得分:4)
我最终做的是将Repository Pattern与Pablo的答案结合起来。它的要点是我的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 :(得分:1)
我认为单独发展Web API和下划线数据库模型(或EF模型)是一种很好的做法。这意味着Web API的DTO模型,它映射到Web API中的EF模型。该间接层将使您有机会进行可能仅影响Web API或EF模型的更改。此外,Web API中的新版本可能不会直接影响现有的EF模型。例如,Web API的新版本使用完全不同的表集。
此致 巴勃罗。