有没有办法配置AutoMapper以遵守实体框架的.Include样式加载说明?
我已经为我的上下文禁用了延迟加载,我想有条件地为特定实体加载相关数据。理想情况下,我希望通过使用include语法来实现此目的。类似的东西:
if(loadAddreses)
{
query = query.Include(e => e.Addresses);
}
if(loadEmails)
{
query = query.Include(e => e.Emails);
}
问题是,AutoMapper看到我投射的模型包括地址和电子邮件,并且正在生成加载所有数据的SQL,无论我要求EF包含什么。换句话说:
var model = query.Project.To<MyModel>();
如果MyModel有一个Addresses集合,它将加载地址,无论我的Include语句如何。
如果没有更改我的模型,以便我有一个没有地址或电子邮件属性的模型,有没有办法解决这个问题?我想我可以改变我的映射,但映射通常是静态的,并且在最初创建之后不会发生变化。
答案 0 :(得分:5)
这很容易梳理,但看看这对你有什么用。请注意,我使用的是AutoMapper的3.3.0-ci1027版本(在撰写本文时是预发行版)。
假设我的数据模型如下所示:
public class Address
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int AddressId { get; set; }
public string Text { get; set; }
}
public class Email
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int EmailId { get; set; }
public string Text { get; set; }
}
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual ICollection<Email> Emails { get; set; }
public User()
{
this.Addresses = new List<Address>();
this.Emails = new List<Email>();
}
}
我的视图模型未指定,但它们只包含与实体相同的属性。
我从User
到UserViewModel
的映射如下所示:
Mapper.CreateMap<User, UserViewModel>()
.ForMember(x => x.Emails, opt => opt.ExplicitExpansion())
.ForMember(x => x.Addresses, opt => opt.ExplicitExpansion());
我的预测如下:
var viewModels = context.Set<User>().Project()
.To<UserViewModel>(new { }, u => u.Emails).ToList();
使用该映射和投影,仅加载Emails
集合。对此的重要部分是映射中的opt => opt.ExplicitExpansion()
调用 - 除非在投影期间显式扩展,否则会阻止导航属性被跟踪,以及重载的To
方法。这个重载允许你指定参数(我作为一个空对象留下)和你想要展开的成员(在这种情况下只是Emails
)。
在这个阶段我不确定的一件事是从Include
语句中提取详细信息的精确机制,以便您可以将它们传递到To
方法,但希望这样给你一些工作。