[英]Using static automapper in C# asp.net performance practices
預先,對於這個問題是否已經在其他地方得到解答,我深表歉意。 但是我在這件事上發現了很多不同的結果。
我正在使用:
我對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.Map
將Post
映射到它的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
並且不花費一些時間在映射配置中(您可能會在AfterMap
, BeforeMap
, ResolveUsing
, MapFrom
等中放入一些業務邏輯或耗時的邏輯),就不會影響性能。
如果我每秒在不同的控制器操作上收到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;
AutoMapper的創建者剛剛在今天(26/02/2019)添加了一篇有關AutoMapper使用指南的博客文章。 必讀。
我不知道這是否可以為您提供幫助,但是我已經將AutoMapper更新到版本8.1.0,並且性能更好。 我已經看到性能在7.0.0版本上已得到糾正,但在最新版本中可能會更好。 根據您的實施,更新的影響很小。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.