带有实例版本的AutoMapper的嵌套映射 [英] Nested mappings with instance version of AutoMapper
问题描述
我正在尝试使用Mapper的实例版本在AutoMapper中使用嵌套映射-但它似乎不起作用.
I'm trying to use nested mappings with AutoMapper, using the instance version of the mapper -- but it doesn't seem to be working.
这是我正在使用的两个模型:
Here's two models I'm using:
public class User
{
[Key]
public string Email { get; set; }
public string Hash { get; set; }
public string Salt { get; set; }
public string Name { get; set; }
public virtual ICollection<TaskTime> TaskTimes { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public virtual ICollection<HistoricalEstimation> HistoricalEstimations { get; set; }
}
public class TaskTime
{
public int Id { get; set; }
public User User { get; set; }
public Task Task { get; set; }
public TimeSpan Duration { get; set; }
public DateTime Date { get; set; }
}
我正在使用以下代码映射它们:
And I'm using this code to map them:
public static class UserViewConfiguration
{
private static ConfigurationStore configuration;
public static MappingEngine Engine { get; private set; }
static UserViewConfiguration()
{
configuration = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.AllMappers());
Engine = new MappingEngine(configuration);
configuration.CreateMap<User, UserFull>();
configuration.CreateMap<TaskTime, UserTaskTime>();
/* snip... */
configuration.AssertConfigurationIsValid();
}
}
在这些视图模型上:
public class UserFull
{
public string Email { get; set; }
public string Name { get; set; }
public virtual ICollection<TaskTime> TaskTimes { get; set; }
}
public class UserTaskTime
{
public int Id { get; set; }
public Task Task { get; set; }
public TimeSpan Duration { get; set; }
public DateTime Date { get; set; }
}
问题在于,User
包含TaskTime
,而TaskTime
包含User
.由于存在多种不同的方法来获取每个项目,因此需要存在这个周期,具体取决于您最初要求的对象(这就是为什么我使用的是AutoMapper的实例版本).我正在对它们进行序列化,以通过ASP.NET MVC API应用程序发送它们,因此周期是个大问题.
The problem is that, a User
contains a TaskTime
, and a TaskTime
contains a User
. This cycle needs to be present since there are several different ways of getting to each item, depending on which object you originally asked for (which is why I'm using the instance version of AutoMapper). I'm serializing these to send them through an ASP.NET MVC API app, so the cycle is a big problem.
我已阅读将嵌套映射与AutoMapper结合使用的示例,并且据我所知,我做对了.但是,使用上面的映射,我在User
上遇到路径[0].TaskTimes[0].User.TaskTimes
的自引用循环错误.如果我注释掉UserFull
的TaskTimes
属性,则不会收到错误消息,因此我知道User->UserFull
映射正在工作-但由于某些原因TaskTime->UserTaskTime
无法正常工作.
I've read this example of using nested mappings with AutoMapper, and from what I can tell I'm doing it right. But with the mappings above, I'm getting a self-referencing loop error on User
for the path [0].TaskTimes[0].User.TaskTimes
. If I comment out the TaskTimes
property of UserFull
, I don't get an error, so I know the User->UserFull
mapping is working -- but for some reason the TaskTime->UserTaskTime
is not working.
我该怎么办?
我这样映射:
// GET api/Users
public IEnumerable<UserFull> GetUsers()
{
//var query = SelectUsers(db.Users.ToList());
return UserViewConfiguration.Engine.Map<IEnumerable<UserFull>>(db.Users);
}
推荐答案
假定您有错字,并且UserFull应该具有UserTaskTime的集合而不是TaskTime的集合,这些快速测试有效:
Assuming that you have a typo, and that UserFull should have a collection of UserTaskTime's rather than a collection of TaskTime's, these quick tests work:
[TestFixture]
public class MappingTests2
{
[Test]
public void AutoMapper_Configuration_IsValid()
{
UserViewConfiguration.Configure();
Mapper.AssertConfigurationIsValid();
}
[Test]
public void AutoMapper_MapsAsExpected()
{
UserViewConfiguration.Configure();
Mapper.AssertConfigurationIsValid();
var user = new User
{
Email = "user1@email.com",
Hash = "1234Hash",
Name = "user1",
Salt = "1234Salt",
TaskTimes =
new Collection<TaskTime>
{
new TaskTime
{ Date = new DateTime(2012, 11, 01), Duration = new TimeSpan(0, 20, 1), Id = 1 },
new TaskTime
{ Date = new DateTime(2012, 11, 02), Duration = new TimeSpan(0, 20, 2), Id = 2 }
}
};
foreach (var taskTime in user.TaskTimes)
{
taskTime.User = user;
}
var userView = Mapper.Map<User, UserFull>(user);
Assert.That(userView, Is.Not.Null);
Assert.That(userView.Email, Is.EqualTo("user1@email.com"));
Assert.That(userView.Name, Is.EqualTo("user1"));
Assert.That(userView.TaskTimes, Is.Not.Null);
Assert.That(userView.TaskTimes.Count, Is.EqualTo(2));
var tt = userView.TaskTimes.FirstOrDefault(x => x.Id == 1);
Assert.That(tt, Is.Not.Null);
Assert.That(tt.Id, Is.EqualTo(1));
Assert.That(tt.Date, Is.EqualTo(new DateTime(2012, 11, 01)));
Assert.That(tt.Duration, Is.EqualTo(new TimeSpan(0, 20, 1)));
}
}
请注意,对于以上内容,我使用静态方法将映射转换回了:
Note that for the above I converted the mapping back to using the static methods:
public static void Configure()
{
Mapper.CreateMap<User, UserFull>();
Mapper.CreateMap<TaskTime, UserTaskTime>();
Mapper.AssertConfigurationIsValid();
}
如果您打算将其作为TaskTime,我会再看看.
I'll take another look if you did intend it to be TaskTime.
这篇关于带有实例版本的AutoMapper的嵌套映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!