如何告诉Web API / Castle Windsor路由引擎在我的存储库中使用不同的数据库实例?
我使用模型,存储库和控制器的ASP.NET Web API Castle Windsorized应用程序了解事件流程:
0)客户端通过URI调用REST方法,例如:
http://localhost:28642/api/platypi/Count
1)Castle Windsor的路由引擎映射拦截来电,发送实现接口platypiController的注册具体类在其构造函数中作为arg。
2)该构造函数确定要调用哪个方法(在这种情况下对应于“Count”)。
3)Controller方法调用Repository上的相应方法。
4)代码运行,数据收集和返回,用户认为这一切都很容易(一个极端观点)或神奇(另一个,稍微不那么极端,观点)。
我已经创建了一对利用它的项目,到目前为止它只是花花公子。 我们为不同的用户提供了几个数据库实例(特定客户端的DB1,另一个客户的DB2等)。这些表几乎但不完全相同(不保证保持不变),并且针对这些表的查询类似。
我的难题/挑战是如何或在何处拦截路由以这种方式或基于用户正在调用的“类”。
我想我需要N个存储库来实现每个接口,例如:
interface FooBar class PhooBar : FooBar // targets DB#1 class PhooeyBar : FooBar // targets DB#2 class PoohBear : FooBar // targets DB#3
但是,我如何告诉Castle Windsor或Web API我想要的具体类/存储库?
在任何给定时间,都会有来自需要为DB#1数据提供服务的客户端的Web API / Castle Windsor应用程序,需要DB#2数据的其他客户端以及需要DB#3数据的用户的请求。
这是在URI中完成的事情,例如:
http://localhost:28642/api/platypi/Count/1
(附加数字表示要使用的DB)
?
要么:
http://localhost:28642/api/platypi/Count/PhooBar
要么…???
在许多情况下,必须在一个Repository类和另一个Repository类之间进行更改的唯一事情是构造函数中的连接字符串。 具体来说,这个:
@"Provider=Microsoft.ACE.OLEDB.12.0;User ID=qypav1;Password=QqPamPoamMSET;Data Source=C:\CatcherNTheRye\DATA\OMDDAT03.MDB;Jet OLEDB:System database=C:\Catch22\Data\trip.mdw"))
……将需要:
@"Provider=Microsoft.ACE.OLEDB.12.0;User ID=qypav1;Password=QqPamPoamMSET;Data Source=C:\CatcherNTheRye\DATA\OMDDAT01.MDB;Jet OLEDB:System database=C:\Catch22\Data\trip.mdw"))
(OMDDAT03成为OMDDAT01)
您可以使用dependency injection将dbContext放入UnitOfWork:
public interface IRepository where T : class { IQueryable GetAll(); void Add(T entity); void Delete(T entity); void DeleteAll(IEnumerable entity); void Update(T entity); bool Any(); } public class Repository : IRepository where T : class { private readonly IDbContext _context; private readonly IDbSet _dbset; public Repository(IDbContext context) { _context = context; _dbset = context.Set (); } public virtual IQueryable GetAll() { return _dbset; } public virtual void Add(T entity) { _dbset.Add(entity); } public virtual void Delete(T entity) { var entry = _context.Entry(entity); entry.State = EntityState.Deleted; _dbset.Remove(entity); } public virtual void DeleteAll(IEnumerable entity) { foreach (var ent in entity) { var entry = _context.Entry(ent); entry.State = EntityState.Deleted; _dbset.Remove(ent); } } public virtual void Update(T entity) { var entry = _context.Entry(entity); _dbset.Attach(entity); entry.State = EntityState.Modified; } public virtual bool Any() { return _dbset.Any(); } }
最后:
public interface IUnitOfWork : IDisposable { IRepository GetRepository () where TEntity : class; void Save(); } public class UnitOfWork : IUnitOfWork where TContext : IDbContext, new() { private readonly IDbContext _ctx; private readonly Dictionary _repositories; private bool _disposed; public UnitOfWork() { _ctx = new TContext(); _repositories = new Dictionary(); _disposed = false; } public IRepository GetRepository () where TEntity : class { if (_repositories.Keys.Contains(typeof(TEntity))) { return _repositories[typeof(TEntity)] as IRepository ; } var repository = new Repository (_ctx); _repositories.Add(typeof(TEntity), repository); return repository; } public void Save() { _ctx.SaveChanges(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (this._disposed) return; if (disposing) { _ctx.Dispose(); } this._disposed = true; } }
我只是复制并浏览我的一个项目中的代码,方法与在应用程序中使用多个dbcontext相同。
另请参阅此解决方案: N层应用程序中的多个DbContexts