我有一个包含大约30个项目的解决方案,其中大多数项目使用Microsoft作为容器。
对于这个测试,我在不同的区域和不同的网络中使用远程Azure SQL数据库,所以我希望延迟响应,但它不会影响这个测试。
让我们使用统一计算数据访问时间,使用DbContext直接访问数据,下面是以毫秒为单位的平均计算:
Unity Container
8749
5757
7225
7072
7256
8791
7016
7465
8449
10741
7852.1 (average)
DbContext
3599
2239
2902
2378
1898
1682
1692
1522
2773
2054
2273.9 (average)因此,使用统一容器访问数据需要7852.1毫秒(平均)毫秒,同时使用DbContext访问数据需要2273.9毫秒(平均)。这是一个很大的性能瓶颈,你不觉得吗?
让我分享几个代码片段,这将展示我是如何在项目中使用的。
项目中的统一配置如下所示:
public class UnityConfig
{
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
public static void RegisterTypes(IUnityContainer container)
{
//// Repositories
container.RegisterType<ICartRepository, CartRepository>();
// .... total 50 repositories registrations ....
//// Services
container.RegisterType<ICartService, CartService>();
// .... total 72 services registrations ....
}
}
public static class UnityWebActivator
{
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}下面是一个示例存储库和一个与Unity一起使用的示例服务:
public interface ICartRepository
{
Cart Get(string id);
IEnumerable<Cart> GetAll();
// more codes
}
public class CartRepository : ICartRepository
{
[Dependency]
public ApplicationData db { get; set; }
public Cart Get(string id)
{
return db.Carts.AsNoTracking().Where(i => i.Id == id && i.IsDeleted == 0).FirstOrDefault();
}
public IEnumerable<Cart> GetAll()
{
return db.Carts.AsNoTracking().Where(i => i.IsDeleted == 0);
}
// more codes
}
public interface ICartService
{
Cart Get(string id, string orgid);
IEnumerable<Cart> GetAll(string orgid);
// more codes
}
public class CartService : ICartService
{
private ICartRepository cartRepository;
public CartService(ICartRepository _cartRepository)
{
cartRepository = _cartRepository;
}
public Cart Get(string id, string orgid)
{
return cartRepository.GetAll().Where(i => i.OrganizationId == orgid && i.Id == id).FirstOrDefault();
}
public IEnumerable<Cart> GetAll(string orgid)
{
return cartRepository.GetAll().Where(i => i.OrganizationId == orgid);
}
// more codes
}在这些项目中,我使用它们的方式如下:
public class HomeController : Controller
{
private ICartService cartService;
public HomeController(ICartService _cartService)
{
cartService = _cartService;
}
public ActionResult Index()
{
// through unity
var item = cartService.Get("id", "org_id");
// direct DbContext
ApplicationData data = new ApplicationData();
var item1 = data.Carts.AsNoTracking().Where(i => i.Id == "id" && i.OrganizationId == "org_id").FirstOrDefault();
// more code
return View();
}
}这是我们在应用程序中使用的全部内容。你看到什么可以改变以提高性能吗?
发布于 2018-03-14 09:13:50
原因是你们比较的两种方式是完全不同的,而不是因为团结。第一种方法是:
var item = cartService.Get("id", "org_id");它被实现为
return cartRepository.GetAll().Where(i => i.OrganizationId == orgid && i.Id == id).FirstOrDefault()其中GetAll是:
public IEnumerable<Cart> GetAll()
{
return db.Carts.AsNoTracking().Where(i => i.IsDeleted == 0);
}因为GetAll返回类型是IEnumerable<Cart> - cartRepository.GetAll().Where(...)不会过滤出数据库中的购物车。相反,整个Cart表通过select * from Cart where IsDeleted = 0之类的SQL查询被拖到内存中。然后执行Where并在内存中查找目标购物车(通过组织和id)。当然,这是非常低效率的(因为它将整个表从远程数据库传输到您的计算机),并且比另一个appoach花费更多的时间,它可以:
data.Carts.AsNoTracking().Where(i => i.Id == "id" && i.OrganizationId == "org_id").FirstOrDefault();这一项产生了您期望的SQL,如select top 1 * from Cart where IsDeleted = 0 and Id = @id and OrganizationId = @org_id,所有筛选都发生在数据库中,然后数据库只在网络上传输一行。
要修复-更改GetAll (和其他类似的方法)以返回IQueryable
public IQueryable<Cart> GetAll()
{
return db.Carts.AsNoTracking().Where(i => i.IsDeleted == 0);
}https://stackoverflow.com/questions/49271181
复制相似问题