在CarTrackr project中,它使用一些技术,为Asp.net Mvc网站中的所有请求仅创建1个存储库实例,并使用UnityControllerFactory类来管理所有存储库实例(发送到请求的控制器)。
与每个请求创建新的存储库实例相比,使用单个存储库实例有什么好处吗?
我知道,这可能会提高整体表现。但是,它会导致任何交通问题吗?
部分Global.asax
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
RegisterDependencies();
}
protected static void RegisterDependencies() {
IUnityContainer container = new UnityContainer();
// Registrations
container.RegisterType<IUserRepository, UserRepository>(new ContextLifetimeManager<IUserRepository>());
container.RegisterType<ICarRepository, CarRepository>(new ContextLifetimeManager<ICarRepository>());
// Set controller factory
ControllerBuilder.Current.SetControllerFactory(
new UnityControllerFactory(container)
);
}
}
部分CarController.cs
[Authorize]
public class CarController : Controller
{
private IUserRepository UserRepository;
private ICarRepository CarRepository;
public CarController(IUserRepository userRepository, ICarRepository carRepository)
{
UserRepository = userRepository;
CarRepository = carRepository;
}
}
谢谢,
答案 0 :(得分:3)
每个请求创建一个存储库实例本身不应导致任何性能问题;存储库通常很浅,当需要访问数据时,连接池之类的东西可以最大限度地降低建立实际连接的成本。对象创建是非常便宜的,特别是对于像Web请求这样的短期内容,其中对象在仍然处于“零代”时被收集。
关于是否每个实例都有一个存储库或存储库 - 这取决于存储库;-p
最大的问题是:您的存储库线程安全吗?如果不是:每个请求一个。
即使它是;如果您的存储库本身保留了类似LINQ-to-SQL DataContext
(您以某种方式同步)的内容,那么如果您保持长期,特别是身份,那么您就会遇到大问题经理。您将很快使用大量内存和获得过时的结果。远非理想。
使用单个存储库实例,您可能最终会遇到大量阻塞,试图获得线程安全性。这可以降低吞吐量。相反,数据库本身具有实现粒度锁的好方法 - 当您考虑到并发请求通常会查看单独的表等时,这一点特别有用 - 因此在数据库层没有阻塞。这只是非常在存储库层很难做到 - 所以你可能不得不同步整个“fetch” - 非常糟糕。
IMO,在大多数情况下,每个请求一个都没问题。如果要缓存数据,请单独执行 - 即不在存储库实例上直接
。答案 1 :(得分:2)
我认为你误解了ContextLifeTimeManager发生的事情。通过将管理器传递给Register()方法,告诉Unity将存储库实例的缓存范围设置为HttpContext。
说:
实际上是不正确的它使用一些技术,只为Asp.net中的所有请求创建一个存储库实例&gt; Mvc网站
没有存储库单例。 Unity正在为每个请求创建一个。听起来这实际上是你想要的行为。
当管理器的作用域设置为HttpContext时,容器会向HttpContext查找所请求类型的现有实例(在本例中为您的存储库)。由于HttpContext在每个请求中都是新鲜的,因此容器将不具有此实例,因此将创建一个新实例。
当你问:
使用单身是否有任何好处 与之比较时的存储库实例 每次创建新的存储库实例 请求?
没有
就交易问题而言:线程将成为一个问题。 CarRepository似乎使用Linq2Sql或Linq2Entities。它的ctor需要一个有效的datacontext。 DataContext不是线程安全的。如果datacontext存储在高于当前请求的范围内,则会出现问题。
答案 2 :(得分:0)
使用新的ContextLifetimeManager());,存储库的生命周期仅限于一个请求。这意味着每次存储库的evry请求都会被实例化(如果需要),并在响应发送到客户端后销毁。