本文介绍了如何在mvc c#中处理这种情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用asp.net mvc的多租户应用程序。我必须识别每个请求的租户,所以我创建了一个类:

  public class TenantProvider 
{
public static Tenant Tenant
{
get
{
租户租户= HttpContext.Current.Items [租户]为租户;

if(tenant == null)
{
var tenantUsername = HelperUtility.GetCurrentRequestHost();
//以下代码行是我的问题
TenantRepository tenantRepository = new TenantRepository(new AppointContext());
tenant = tenantRepository.GetByUsername(tenantUsername);
HttpContext.Current.Items.Add(租户,租户);
}

返回租户;
}
}
}

此类返回租户当前的要求。它将首先检查租户的缓存,如果没有找到,如果将从数据库中获取租户,初始化缓存并返回租户。



为了获得租户表单数据库我正在创建一个TenantRepository实例。 TenantRepository具有对数据库上下文的依赖,我在创建实例时传递它。



现在,当我必须对当前的租户进行其他数据库操作时,我必须在其他地方创建一个新的Repository实例,并且必须传递新的Context,所以实际我已经提取了租户的上下文和新的上下文不同,我认为可能会产生问题。



所以我的问题是我如何处理这种情况,所以相同上下文实例会被使用?

解决方案

您正在寻找的解决方案是工作单位设计模式。从Martin Fowler:

参考:



此模式允许您将多个事务注册到单个上下文中。这是一个非常常见的模式,这里是一个可能的实现。首先,创建一个工作单元对象,它将引用您的中央上下文,并将使用该上下文初始化您的存储库(此实现使用实体框架):

  public class UnitOfWork:IUnitOfWork 
{
internal EntitiesContext _context = new EntitiesContext();
private ITenantRepository _tenantRepository;
private IOtherRepository _otherRepository;

public ITenantRepository TenantRepository
{
get
{
if(_tenantRepository == null)
{
_tenantRepository = new TenantRepository (_context);
}
return _tenantRepository;
}
}

public IOtherRepository OtherRepository
{
get
{
if(_otherRepository == null)
{
_otherRepository = new OtherRepository(_context);
}
return _otherRepository;
}
}

public void Save()
{
_context.SaveChanges();
}

private boolwhere = false;

protected virtual void Dispose(bool disposal)
{
if(!this.disposed)
{
if(disposal)
{
_context.Dispose();
}
}
this.disposed = true;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

请注意,如果您使用具有此模式的任何存储库,它们将全部使用



您的控制器应初始化工作单位,甚至更好地将其注入到其构造函数中:

  public TenantController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_tenantRepository = unitOfWork.TenantRepository;
_otherRepository = unitOfWork.OtherRepository;
}

如果您需要将UnitOfWork用于另一层,则通常会传递作为另一个对象的构造函数的参数:

  public ActionResult Index()
{
TenantProvider provider = new TenantProvider(_unitOfWork);
_otherRepository.DoWork();
_unitOfWork.Save();
}

现在您的 TenantProvider 可以使用其各自的存储库进行一些工作,但工作单位 OtherRepository 也可以使用相同的上下文进行一些工作。


I am working on a multi-tenant app with asp.net mvc. I have to identify tenant for each request so i have created a class below:

public class TenantProvider
    {
        public static Tenant Tenant
        {
            get
            {
                Tenant tenant = HttpContext.Current.Items["Tenant"] as Tenant;

                if (tenant == null)
                {
                    var tenantUsername = HelperUtility.GetCurrentRequestHost();
                    //The below line of code is my problem
                    TenantRepository tenantRepository = new TenantRepository(new AppointContext());
                    tenant = tenantRepository.GetByUsername(tenantUsername);
                    HttpContext.Current.Items.Add("Tenant", tenant);
                }

                return tenant;
            }
        }
    }

This class static property returning the Tenant for current request. It will first check for the Tenant in cache, if not found than if will get the Tenant from the database, initialize the cache and return the Tenant.

For getting Tenant form the database i am creating a TenantRepository instance. TenantRepository has a dependency over database context, which i am passing it while creating its instance.

Now when i have to do other database operation on current Tenant than i have to create a new Repository instance at some other place and have to pass new Context, so the actual context with which i have extracted the Tenant and the new Context differ which i think may create the problem.

So my question is how can i handle this scenario, so that same context instance will be used ??

解决方案

The solution you are looking for is the Unit of Work design pattern. From Martin Fowler:

ref: http://martinfowler.com/eaaCatalog/unitOfWork.html

This pattern allows you to enroll multiple transactions into a single context. This is a very common pattern, and here is one possible implementation. First, create a Unit of Work object which will hold a reference to your central context, and which will initialize your repositories with that context (this implementation uses the Entity Framework):

public class UnitOfWork : IUnitOfWork
{
    internal EntitiesContext _context = new EntitiesContext ();
    private ITenantRepository _tenantRepository;
    private IOtherRepository _otherRepository;

    public ITenantRepository TenantRepository
    {
        get
        {
            if (_tenantRepository== null)
            {
                _tenantRepository= new TenantRepository(_context);
            }
            return _tenantRepository;
        }
    }

    public IOtherRepository OtherRepository
    {
        get
        {
            if (_otherRepository== null)
            {
                _otherRepository= new OtherRepository(_context);
            }
            return _otherRepository;
        }
    }

    public void Save()
    {
        _context.SaveChanges();
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                _context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

Note that if you use any repository with this pattern, they will all use the same context.

Your controller should either initializing the Unit of of Work, or even better, have it injected into its constructor:

    public TenantController(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
        _tenantRepository = unitOfWork.TenantRepository;
        _otherRepository = unitOfWork.OtherRepository;
    }

If you need to use the UnitOfWork to another layer, you would typically pass it as an argument to another object's constructor:

 public ActionResult Index()
 {
    TenantProvider provider = new TenantProvider(_unitOfWork);
    _otherRepository.DoWork();
    _unitOfWork.Save();
 }

Now your TenantProvider can do some work with its respective repository, but the Unit of Work's OtherRepository can also do some work using the same context.

这篇关于如何在mvc c#中处理这种情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 06:10
查看更多