簡體   English   中英

在C#asp.net性能實踐中使用靜態自動映射器

[英]Using static automapper in C# asp.net performance practices

預先,對於這個問題是否已經在其他地方得到解答,我深表歉意。 但是我在這件事上發現了很多不同的結果。

我正在使用:

  • .net Framework 4.6.1
  • Microsoft.AspNet.Mvc 5.2.6
  • AutoMapper 6.2.2
  • 實體框架6.2.0

我對ASP.net和C#都是陌生的,最近我成為了AutoMapper軟件包的粉絲。 我主要使用它來將我從ApplicationDbContext獲得的實體轉換為DTO (數據傳輸對象)或ViewModel

現在,我在應用程序中使用此設置來初始化並在Controller使用Mapper

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        Mapper.Initialize(AutoMapperConfiguration.Configure);

        // Other configuration for MVC application...
    }
}

AutoMapperConfiguration.cs

public static class AutoMapperConfiguration
{
    public static void Configure(IMapperConfigurationExpression config)
    {
        config.CreateMap<Post, Post.DetailsViewModel>().ForMember(post => post.CanEdit, cfg => cfg.ResolveUsing((src, dst, arg3, context) => context.Options.Items["UserId"]?.ToString() == src.UserId));
    }
}

PostsController.cs和Post.cs

public class PostsController : Controller
{
    private ApplicationDbContext db = new ApplicationDbContext();

    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        Post post = db.Posts.Find(id);

        if (post == null)
        {
            return HttpNotFound();
        }

        return View(Mapper.Map<Post.DetailsViewModel>(post, options => options.Items["UserId"] = User.Identity?.GetUserId()));
    }
}


// Post.cs

public class Post
{
    public int Id { get; set; }

    public string UserId { get; set; }

    public virtual ApplicationUser User { get; set; }

    public string Title { get; set; }

    public string Content { get; set; }

    public DateTime PostedAt { get; set; } = DateTime.Now;

    public class DetailsViewModel
    {
        public int Id { get; set; }

        public string UserId { get; set; }

        public ApplicationUser User { get; set; }

        public string Title { get; set; }

        public string Content { get; set; }

        /// <summary>
        /// A value indicating whether the current logged in user can edit the model
        /// </summary>
        public bool CanEdit { get; set; }

        public DateTime PostedAt { get; set; }
    }
}

代碼摘要

我在一個靜態類( AutoMapperConfiguration )中配置Mapper ,該類包含一個Config方法,該方法從Global.asax.cs文件中調用並映射所需的類。

然后,在我的Controller我使用靜態方法Mapper.MapPost映射到它的DetailsViewModel

問題

AutoMapper的這種用法(通過靜態方法Mapper.Map )如何影響性能,還有更好的方法嗎?

一些說明:

例如:如果我每秒收到100個不同的控制器操作請求,該怎么辦? 據我所知,每個請求都將有一個單獨的線程,但是將為Mapper.Map方法訪問相同的內存(如果我正確的話)。 據我所知,這意味着性能將受到嚴重影響。

我已經看過一個問題,但是得到的結果卻參差不齊:

非靜態AutoMapper和ASP.NET MVC- > 在哪里放置AutoMapper.CreateMaps?

如果我在這方面有誤,請糾正我。

AutoMapper的這種用法(通過靜態方法Mapper.Map)如何影響性能,還有更好的方法嗎?

您對AutoMapper的使用是正確的。 在應用程序啟動時進行初始化是值得尊重的最佳實踐。 通過調用Mapper.Initialize您正在初始化一個映射器,它是IMapper接口的靜態實例(可通過Mapper.Instance靜態屬性訪問)。 當使用Mapper類中的靜態成員時,您正在處理Mapper.Instance並且所有對象進入同一AppDomain都是相同的實例。 只要您使用相同的AppDomain並且不花費一些時間在映射配置中(您可能會在AfterMapBeforeMapResolveUsingMapFrom等中放入一些業務邏輯或耗時的邏輯),就不會影響性能。

如果我每秒在不同的控制器操作上收到100個請求怎么辦? 據我所知,每個請求都將有一個單獨的線程,但是將為Mapper.Map方法訪問相同的內存(如果我正確的話)。 據我所知,這意味着性能將受到嚴重影響。

您的應用程序使用一個AppDomain實例,每個請求將獲得一個新線程,但是該線程將在啟動您的應用程序的同一AppDomain中運行,該線程執行了Application_Start方法,最后您將獲得相同的Mapper.Instance實例。只有在第一個請求到達時,才會編譯和緩存您的配置計划。 僅第一個請求不會受到影響。 其他請求將使用緩存的配置計划。 因此,只要您位於同一個AppDomain並且沒有在AutoMapper允許您執行的自定義映射替代中使用一些耗時的邏輯,就不會對性能造成影響。

AutoMapper還帶有一些可以激活或取消激活並獲得性能的配置。

顯式編譯

正如我已經說過的,使用映射的第一個請求將編譯您的配置計划。 如AutoMapper的文檔所述

由於表達式編譯可能會占用一些資源,因此AutoMapper會在第一個地圖上延遲編譯類型地圖計划。 但是,這種行為並不總是令人滿意的,因此您可以告訴AutoMapper直接編譯其映射。 對於數百個映射,這可能需要幾秒鍾。

您可以在映射配置之后通過執行以下操作來顯式編譯計划:

Mapper.Configuration.CompileMappings();

我將其與應用程序“ warming”結合使用,在該應用程序中,我的應用程序將自動啟動,而不是等待第一個請求進行映射和編譯我的配置計划。 您可以查看此答案以了解如何啟用該功能。

內聯映射

在6.2.0中,AutoMapper附帶了一項稱為內聯映射的新功能,該功能使您可以即時創建類型映射,而不必通過調用Mapper.Initialize方法對其進行配置。 因為內聯映射是動態創建的,所以它們會在那時進行編譯,因此您要尋求的明確編譯計划的收益沒有太大幫助。 因此,在我的項目中,我禁用了此功能,因此任何人都無法以廣告形式使用它。 要停用它,請執行以下操作:

cfg.CreateMissingTypeMaps = false;

編輯26/02/2019

AutoMapper的創建者剛剛在今天(26/02/2019)添加了一篇有關AutoMapper使用指南的博客文章。 必讀。

我不知道這是否可以為您提供幫助,但是我已經將AutoMapper更新到版本8.1.0,並且性能更好。 我已經看到性能在7.0.0版本上已得到糾正,但在最新版本中可能會更好。 根據您的實施,更新的影響很小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM