Joa*_*oas 1 c# asp.net asp.net-mvc entity-framework automapper
预先,对于这个问题是否已经在其他地方得到解答,我深表歉意。但是我在这件事上发现了很多不同的结果。
我正在使用:
我对ASP.net和C#都是陌生的,最近我成为了AutoMapper软件包的粉丝。我主要是使用它来将我的实体转换ApplicationDbContext
为DTO
的(数据传输对象)或ViewModel
。
现在,我在应用程序中使用此设置进行初始化并在Mapper
中使用Controller
:
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
Mapper.Initialize(AutoMapperConfiguration.Configure);
// Other configuration for MVC application...
}
}
Run Code Online (Sandbox Code Playgroud)
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));
}
}
Run Code Online (Sandbox Code Playgroud)
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; }
}
}
Run Code Online (Sandbox Code Playgroud)
代码摘要
我Mapper
在一个静态类(AutoMapperConfiguration
)中配置自己,该类包含一个Config
从Global.asax.cs
文件中调用并映射所需类的方法。
然后,在我中,Controller
我使用static方法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
static属性访问)。当使用来自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();
Run Code Online (Sandbox Code Playgroud)
我将其与应用程序“ warming”结合使用,在该应用程序中,我的应用程序将自动启动,而不是等待第一个请求进行映射和编译我的配置计划。您可以查看此答案以了解如何启用该功能。
在6.2.0中,AutoMapper附带了一项称为内联映射的新功能,该功能使您可以即时创建类型映射,而不必通过调用Mapper.Initialize
方法进行配置。因为内联映射是动态创建的,所以它们会在那时进行编译,因此您要寻求的明确编译计划的收益没有太大帮助。因此,在我的项目中,我禁用了此功能,因此任何人都无法以广告形式使用它。要停用它,请执行以下操作:
cfg.CreateMissingTypeMaps = false;
Run Code Online (Sandbox Code Playgroud)
AutoMapper的创建者刚刚在今天(26/02/2019)添加了一篇有关AutoMapper使用指南的博客文章。必读。
归档时间: |
|
查看次数: |
2599 次 |
最近记录: |