使用IRepository和对方ASP.NET C#服务 [英] ASP.NET C# Services using IRepository and each other

查看:202
本文介绍了使用IRepository和对方ASP.NET C#服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我这是使用约束我的 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 DbContexts?

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆