C# 在我的存储库类和控制器类之间协调以使用相同的上下文对象
我正在开发一个asp.net mvc web应用程序。现在,我创建了多个存储库类,例如,我有以下抽象存储库类:-C# 在我的存储库类和控制器类之间协调以使用相同的上下文对象,c#,asp.net,asp.net-mvc,entity-framework-6,unit-of-work,C#,Asp.net,Asp.net Mvc,Entity Framework 6,Unit Of Work,我正在开发一个asp.net mvc web应用程序。现在,我创建了多个存储库类,例如,我有以下抽象存储库类:- public interface ISkillRepository : IDisposable {//code goes here.. & 以及模型存储库:- public class SkillRepository : ISkillRepository , IDisposable { private SkillManagementEntitie
public interface ISkillRepository : IDisposable
{//code goes here..
&
以及模型存储库:-
public class SkillRepository : ISkillRepository , IDisposable
{
private SkillManagementEntities context = new SkillManagementEntities();
//code goes here
&
现在,在y控制器内,我正在初始化并创建回购协议,如下所示:-
public class SkillController : Controller
{
private ISkillRepository skillRepository;
public SkillController() : this(new SkillRepository()) {}
public SkillController(ISkillRepository repository)
{
skillRepository = repository;
}
public class SecurityRoleController : Controller
{
private UnitOfWork unitOfWork = new UnitOfWork();
public async Task<ActionResult> Index(string filter = null, int page = 1, int pageSize = 20, string sort = "Name", string sortdir = "ASC")
{
try
{
var records = new PagedList<SecurityRole>();
ViewBag.filter = filter;
records.Content = await unitOfWork.SecurityRoleRepository.GetSecurityRoleForGrid(filter, page, pageSize, sort, sortdir).ToListAsync();
public class SkillRepository : ISkillRepository , IDisposable
{
private SkillManagementEntities context ;
private IStaffRepository staffrepo = (IStaffRepository)DependencyResolver.Current.GetService(typeof(IStaffRepository));
public SkillRepository(SkillManagementEntities context)
{
this.context = context;
}
public class StaffController : Controller
{
//private SkillManagementEntities db = new SkillManagementEntities();
UnitOfWork unitofwork = new UnitOfWork();
public async Task<ActionResult> AutoComplete(string term)
{
var staff = await unitofwork.StaffRepository.GetAllActiveStaff(term).Select(a => new { label = a.SamAccUserName }).ToListAsync();
return Json(staff, JsonRequestBehavior.AllowGet);
但目前我的应用程序中出现以下错误:
The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.
问题是我需要在回购协议和控制器之间传递相同的上下文。因此,任何人都可以就此发表意见:-
public class UnitOfWork : IDisposable
{
private SkillManagementEntities context = new SkillManagementEntities();
private SkillRepository skillRepository;
private StaffRepository staffRepository;
private SecurityRoleRepository securityroleRepository;
public SkillRepository SkillRepository
{
get
{
if (this.skillRepository == null)
{
this.skillRepository = new SkillRepository(context);
}
return skillRepository;
}
}
public StaffRepository StaffRepository
{
get
{
if (this.staffRepository == null)
{
this.staffRepository = new StaffRepository(context);
}
return staffRepository;
}
}
public SecurityRoleRepository SecurityRoleRepository
{
get
{
if (this.staffRepository == null)
{
this.staffRepository = new SecurityRoleRepository(context);
}
return securityroleRepository;
}
}
public async Task Save()
{
await context.SaveChangesAsync();
}
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);
}
}
}
然后在回购协议中,我做了以下几点:-
public class SecurityRoleRepository : ISecurityRoleRepository , IDisposable
{
private SkillManagementEntities context;// = new SkillManagementEntities();
public SecurityRoleRepository(SkillManagementEntities context)
{
this.context = context;
在控制器类上,我将引用UnitOfWork,如下所示:-
public class SkillController : Controller
{
private ISkillRepository skillRepository;
public SkillController() : this(new SkillRepository()) {}
public SkillController(ISkillRepository repository)
{
skillRepository = repository;
}
public class SecurityRoleController : Controller
{
private UnitOfWork unitOfWork = new UnitOfWork();
public async Task<ActionResult> Index(string filter = null, int page = 1, int pageSize = 20, string sort = "Name", string sortdir = "ASC")
{
try
{
var records = new PagedList<SecurityRole>();
ViewBag.filter = filter;
records.Content = await unitOfWork.SecurityRoleRepository.GetSecurityRoleForGrid(filter, page, pageSize, sort, sortdir).ToListAsync();
public class SkillRepository : ISkillRepository , IDisposable
{
private SkillManagementEntities context ;
private IStaffRepository staffrepo = (IStaffRepository)DependencyResolver.Current.GetService(typeof(IStaffRepository));
public SkillRepository(SkillManagementEntities context)
{
this.context = context;
}
public class StaffController : Controller
{
//private SkillManagementEntities db = new SkillManagementEntities();
UnitOfWork unitofwork = new UnitOfWork();
public async Task<ActionResult> AutoComplete(string term)
{
var staff = await unitofwork.StaffRepository.GetAllActiveStaff(term).Select(a => new { label = a.SamAccUserName }).ToListAsync();
return Json(staff, JsonRequestBehavior.AllowGet);
二,。然后,我创建了以下依赖项类:-
public class YourDependencyResolverClass : IDependencyResolver
{
private IKernel kernel;
public YourDependencyResolverClass()
{
kernel = new StandardKernel();
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
kernel.Bind<ISkillRepository>().To<SkillRepository>();
kernel.Bind<IStaffRepository>().To<StaffRepository>();
kernel.Bind<ISecurityRoleRepository>().To<SecurityRoleRepository>();
kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
kernel.Bind<ISkillVersionHistoryRepository>().To<SkillVersionHistoryRepository>();
}
}
}
最后,在action方法中,我将调用Uiteofwork类,如下所示:-
public class SkillController : Controller
{
private ISkillRepository skillRepository;
public SkillController() : this(new SkillRepository()) {}
public SkillController(ISkillRepository repository)
{
skillRepository = repository;
}
public class SecurityRoleController : Controller
{
private UnitOfWork unitOfWork = new UnitOfWork();
public async Task<ActionResult> Index(string filter = null, int page = 1, int pageSize = 20, string sort = "Name", string sortdir = "ASC")
{
try
{
var records = new PagedList<SecurityRole>();
ViewBag.filter = filter;
records.Content = await unitOfWork.SecurityRoleRepository.GetSecurityRoleForGrid(filter, page, pageSize, sort, sortdir).ToListAsync();
public class SkillRepository : ISkillRepository , IDisposable
{
private SkillManagementEntities context ;
private IStaffRepository staffrepo = (IStaffRepository)DependencyResolver.Current.GetService(typeof(IStaffRepository));
public SkillRepository(SkillManagementEntities context)
{
this.context = context;
}
public class StaffController : Controller
{
//private SkillManagementEntities db = new SkillManagementEntities();
UnitOfWork unitofwork = new UnitOfWork();
public async Task<ActionResult> AutoComplete(string term)
{
var staff = await unitofwork.StaffRepository.GetAllActiveStaff(term).Select(a => new { label = a.SamAccUserName }).ToListAsync();
return Json(staff, JsonRequestBehavior.AllowGet);
那么,您能同意我使用UniteWork和DI的方法是否能保证我的所有语句都会在单个DB事务中扭曲吗?thnaks?我们通过使用HttpContext共享一个范围为请求的单例上下文来处理这个问题:
public MyContext GetContext()
{
if (System.Web.HttpContext.Current.Items["MyScopedContext"] == null)
{
System.Web.HttpContext.Current.Items["MyScopedContext"] = new MyContext();
}
return (MyContext)System.Web.HttpContext.Current.Items["MyScopedContext"];
}
上下文对象(存储库)本身实际上包含一个工作单元。我在上面添加的代码只提供了一种方法,可以跨一个请求中运行的所有代码共享一个存储库。如果您的存储库类是在web应用程序的范围内定义的,则只需将SkillManagementEntities()的直接实例化替换为对GetContext()方法的调用即可
另一方面,如果存储库是在异构应用程序共享的层中定义的,则可能需要从factory对象获取上下文,以便根据需要注入。无论哪种方式,每个存储库创建一个新的上下文对象都会导致您的问题。我们通过使用HttpContext共享一个范围为请求的单例上下文来处理这个问题:
public MyContext GetContext()
{
if (System.Web.HttpContext.Current.Items["MyScopedContext"] == null)
{
System.Web.HttpContext.Current.Items["MyScopedContext"] = new MyContext();
}
return (MyContext)System.Web.HttpContext.Current.Items["MyScopedContext"];
}
上下文对象(存储库)本身实际上包含一个工作单元。我在上面添加的代码只提供了一种方法,可以跨一个请求中运行的所有代码共享一个存储库。如果您的存储库类是在web应用程序的范围内定义的,则只需将SkillManagementEntities()的直接实例化替换为对GetContext()方法的调用即可
另一方面,如果存储库是在异构应用程序共享的层中定义的,则可能需要从factory对象获取上下文,以便根据需要注入。无论哪种方式,每个存储库创建一个新的上下文对象都会导致您的问题。我们通过使用HttpContext共享一个范围为请求的单例上下文来处理这个问题:
public MyContext GetContext()
{
if (System.Web.HttpContext.Current.Items["MyScopedContext"] == null)
{
System.Web.HttpContext.Current.Items["MyScopedContext"] = new MyContext();
}
return (MyContext)System.Web.HttpContext.Current.Items["MyScopedContext"];
}
上下文对象(存储库)本身实际上包含一个工作单元。我在上面添加的代码只提供了一种方法,可以跨一个请求中运行的所有代码共享一个存储库。如果您的存储库类是在web应用程序的范围内定义的,则只需将SkillManagementEntities()的直接实例化替换为对GetContext()方法的调用即可
另一方面,如果存储库是在异构应用程序共享的层中定义的,则可能需要从factory对象获取上下文,以便根据需要注入。无论哪种方式,每个存储库创建一个新的上下文对象都会导致您的问题。我们通过使用HttpContext共享一个范围为请求的单例上下文来处理这个问题:
public MyContext GetContext()
{
if (System.Web.HttpContext.Current.Items["MyScopedContext"] == null)
{
System.Web.HttpContext.Current.Items["MyScopedContext"] = new MyContext();
}
return (MyContext)System.Web.HttpContext.Current.Items["MyScopedContext"];
}
上下文对象(存储库)本身实际上包含一个工作单元。我在上面添加的代码只提供了一种方法,可以跨一个请求中运行的所有代码共享一个存储库。如果您的存储库类是在web应用程序的范围内定义的,则只需将SkillManagementEntities()的直接实例化替换为对GetContext()方法的调用即可
另一方面,如果存储库是在异构应用程序共享的层中定义的,则可能需要从factory对象获取上下文,以便根据需要注入。无论如何,每个存储库创建一个新的上下文对象都是导致问题的原因。不是答案:这个“使用DI”建议回答了一个稍微不同的问题-OP正在寻找“工作单元”模式-而基本情况(工作单元的生命周期与请求/控制器的生命周期匹配)可以很容易地用任何DI框架解决,管理多个工作单元或具有较长生命周期的工作单元要困难得多,而专用的“工作单元工厂”(UnitofWorkFactory)可能是解决方案
通常,当您使用接口/存储库和构造函数依赖项注入时,您有一些依赖项注入框架。您正在使用的解决方案很可能已经提供了“每个HTTP请求”的解决方案,或者允许轻松添加一个解决方案 也就是说,如果您使用Unity,则有一个
PerRequestLifetime
lifetime管理器,它可以对同一接口/对象执行所有.Resolve
调用,以返回给定请求的同一实例。请参阅MSDN文章中的更多信息
近似样本:
container.RegisterType<ISkillRepository, SkillRepository>();
container.RegisterType<IOtherRepository, OtherRepository>();
container.RegisterType<TheContext, TheContext>(new PerRequestLifetime());
container.RegisterType();
container.RegisterType();
RegisterType(新PerRequestLifetime());
通过这样的注册,并假设您已将ASP.NETMVC配置为在创建控制器时使用Unity解析类型,它将获得必要的依赖项(新实例)