使用IRepository和对方ASP.NET C#服务 [英] ASP.NET C# Services using IRepository and each other
问题描述
我这是使用约束我的 IRepository
接口 Ninject
和 InRequestScope
。
存储库绑定是:
<$p$p><$c$c>kernel.Bind<IRepository>().To<DefaultRepository>().InRequestScope().WithConstructorArgument(\"dbContext\",的DbContext =&GT; kernel.Get&所述;的DefaultContext&GT;());如果我有一个服务 IAccountService
这是在以同样的方式约束。
具体实现:
公共类的AccountService:IAccountService
{
IRepository _repository; 公众的AccountService(IRepository库){_repository =库; }
}
如果我现在创建另一个服务 IBlogService
这是在以同样的方式约束。
具体实现:
公共类BlogService:IBlogService
{
IRepository _repository;
IAccountService _accountService; 公众的AccountService(IRepository库,IAccountService的AccountService)
{
_repository =库;
_accountService =帐户服务;
}
}
这两种服务都要求 IRepository
是他们收到同样的实例,或者他们要求完全不同的两个隔离的的DbContext
S'
它做工作,但有一个明显的倒台这种方法吗?
由于您使用 .InRequestScope()
所有服务越来越相同的实例你的要求时DefaultRepository
。因此,当一个新的请求时,一个新的实例你的 DefaultRepository
创建
此外,如果你的 IRepository
接口实现的IDisposable
,Ninject会在需要的时候它处理掉。
我不认为有任何的倒台,因为在Web应用程序的生命周期的的DbContext
应该是每个请求(除非你有很好的理由不跟随这种做法)。
修改
您还可以实现每个请求模式的交易,这样可以尽量避免不一致,如果在保存一个资料库成功,但保存在其他存储库中失败。这样,如果你的任何请求期间,出现错误,你可以回滚所有更改。
不是说你要实现这一点,只是想让你知道这是可能的。这是一个非常基本的例子,你应该做的,当你想创建一个事务(例如只对HTTP的职位)上的一些额外的检查,也许你要委托给独立的类让你的Global.asax不会混乱这一切resposiblilites。提到另一件事是,这只会如果您有您的DbContext与.InRequestScope()注射工作,使同样的情况下,通过您的要求使用。
它的工作原理是这样的:
在您的Global.asax的Application_BeginRequest()方法,你应该初始化您的交易是这样的:
VAR交易= _context.Database.BeginTransaction(IsolationLevel.ReadCommitted);
_httpContext.Items [_交易] =交易;
在您的Global.asax的Application_Error()方法,你可以这样设置一个错误标志
_httpContext.Items [_错误] =真;
最后,在您的Global.asax Application_EndRequest()你可以提交一切,如果没有错误,或者回滚:
VAR交易=(DbContextTransaction)_httpContext.Items [_交易]; 如果(_httpContext.Items [_错误]!= NULL)
transaction.Rollback();
其他
器transaction.commit();
I have my IRepository
interface which is bound using Ninject
and InRequestScope
.
The Repository Binding is:
kernel.Bind<IRepository>().To<DefaultRepository>().InRequestScope().WithConstructorArgument("dbContext", dbContext => kernel.Get<DefaultContext>());
If I have a service IAccountService
which is bound in the same way.
The concrete implementation:
public class AccountService : IAccountService
{
IRepository _repository;
public AccountService(IRepository repository) { _repository = repository; }
}
If I now create another service IBlogService
which is bound in the same way.
The concrete implementation:
public class BlogService : IBlogService
{
IRepository _repository;
IAccountService _accountService;
public AccountService(IRepository repository, IAccountService accountService)
{
_repository = repository;
_accountService = accountService;
}
}
Both these services are asking for IRepository
are they getting the same instance or are they requesting two completely different isolated DbContext
s?
It does "work" but is there an obvious downfall to this method?
Because you use .InRequestScope()
all services are getting the same instance of DefaultRepository
during your request. So when a new request comes in, an new instance of your DefaultRepository
is created.
Also if your IRepository
interface implements IDisposable
, Ninject will dispose it when needed.
I don't think there is any downfall, since in web applications, the lifecycle of your DbContext
should be per request (unless you have very good reasons not to follow this approach).
EDIT
You can also implement a transaction per request pattern, so you can avoid inconsistency if saving in one repository succeeds, but saving in another repository fails. This way you can rollback all the changes if anything goes wrong during your request.
Not saying you should implement this, just wanted to let you know it's possible. This is a very basic example, you should do some extra checks on when you want to create a transaction (for example only on http POSTS), and maybe you want to delegate this to a seperate class so your Global.asax will not be cluttered with all this resposiblilites. Another thing to mention is that this will only work if you have your DbContext injected with .InRequestScope(), so the same context is used through your request.
It works like this:
In your Global.asax Application_BeginRequest() method, you should initialize your transaction like this:
var transaction = _context.Database.BeginTransaction(IsolationLevel.ReadCommitted);
_httpContext.Items["_Transaction"] = transaction;
In your Global.asax Application_Error() method, you can set an error flag like this
_httpContext.Items["_Error"] = true;
Finally in your Global.asax Application_EndRequest() you can commit everything if there are no errors, or else rollback:
var transaction = (DbContextTransaction)_httpContext.Items["_Transaction"];
if (_httpContext.Items["_Error"] != null)
transaction.Rollback();
else
transaction.Commit();
这篇关于使用IRepository和对方ASP.NET C#服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!