带有实例版本的AutoMapper的嵌套映射 [英] Nested mappings with instance version of AutoMapper

查看:288
本文介绍了带有实例版本的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的自引用循环错误.如果我注释掉UserFullTaskTimes属性,则不会收到错误消息,因此我知道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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆