Ray*_*lli 7 versioning rest entity-framework asp.net-web-api
我正在使用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进行版本控制吗?如果是这样,怎么样?
我最终所做的是将存储库模式与巴勃罗的答案结合起来。其要点是我的 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();
}
Run Code Online (Sandbox Code Playgroud)
一种实现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
}
Run Code Online (Sandbox Code Playgroud)
它的另一种实现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
}
Run Code Online (Sandbox Code Playgroud)
返回模型或接受模型作为参数的方法使用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>
{
}
}
Run Code Online (Sandbox Code Playgroud)
现在,v1 ApiController 可以使用 v1 MyModelRepository,v2 ApiController 可以使用 v2 MyModelRepository,但最终所有请求都使用已迁移到 v2 的数据库。