首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与直接数据访问相比,统一容器性能有很大的不同

与直接数据访问相比,统一容器性能有很大的不同
EN

Stack Overflow用户
提问于 2018-03-14 06:38:00
回答 1查看 697关注 0票数 3

我有一个包含大约30个项目的解决方案,其中大多数项目使用Microsoft作为容器。

对于这个测试,我在不同的区域和不同的网络中使用远程Azure SQL数据库,所以我希望延迟响应,但它不会影响这个测试。

让我们使用统一计算数据访问时间,使用DbContext直接访问数据,下面是以毫秒为单位的平均计算:

代码语言:javascript
复制
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毫秒(平均)。这是一个很大的性能瓶颈,你不觉得吗?

让我分享几个代码片段,这将展示我是如何在项目中使用的。

项目中的统一配置如下所示:

代码语言:javascript
复制
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一起使用的示例服务:

代码语言:javascript
复制
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
}

在这些项目中,我使用它们的方式如下:

代码语言:javascript
复制
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();
    }
}

这是我们在应用程序中使用的全部内容。你看到什么可以改变以提高性能吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-14 09:13:50

原因是你们比较的两种方式是完全不同的,而不是因为团结。第一种方法是:

代码语言:javascript
复制
var item = cartService.Get("id", "org_id");

它被实现为

代码语言:javascript
复制
return cartRepository.GetAll().Where(i => i.OrganizationId == orgid && i.Id == id).FirstOrDefault()

其中GetAll是:

代码语言:javascript
复制
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花费更多的时间,它可以:

代码语言:javascript
复制
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

代码语言:javascript
复制
public IQueryable<Cart> GetAll()
{
    return db.Carts.AsNoTracking().Where(i => i.IsDeleted == 0);
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49271181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档