1

マッパーのインスタンス バージョンを使用して、AutoMapper でネストされたマッピングを使用しようとしていますが、機能していないようです。

私が使用している2つのモデルは次のとおりです。

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; }
}

そして、私はこのコードを使用してそれらをマッピングしています:

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; }
}

問題は、 aUserが a を含み、TaskTimeaが a をTaskTime含むことUserです。最初に要求したオブジェクトに応じて、各アイテムに到達する方法がいくつかあるため、このサイクルが存在する必要があります (これが、AutoMapper のインスタンス バージョンを使用している理由です)。ASP.NET MVC API アプリを介して送信するためにこれらをシリアル化しているため、サイクルは大きな問題です。

AutoMapper でネストされたマッピングを使用するこの例を読みましたが、正しくやっていることがわかります。Userしかし、上記のマッピングでは、 path に対して自己参照ループ エラーが発生しています[0].TaskTimes[0].User.TaskTimesTaskTimesのプロパティをコメントアウトしてもUserFullエラーは発生しないので、User->UserFullマッピングが機能していることはわかっていますが、何らかの理由でが機能しTaskTime->UserTaskTimeていません。

私に何ができる?

編集:私はこのようにマッピングしています:

// GET api/Users
public IEnumerable<UserFull> GetUsers()
{
    //var query = SelectUsers(db.Users.ToList());
    return UserViewConfiguration.Engine.Map<IEnumerable<UserFull>>(db.Users);
}
4

1 に答える 1

3

入力ミスがあり、UserFull に TaskTime のコレクションではなく UserTaskTime のコレクションが必要であると仮定すると、これらの簡単なテストが機能します。

[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)));
    }
}

上記では、マッピングを静的メソッドを使用するように変換したことに注意してください。

public static void Configure()
{
    Mapper.CreateMap<User, UserFull>();
    Mapper.CreateMap<TaskTime, UserTaskTime>();

    Mapper.AssertConfigurationIsValid();
}

TaskTime にするつもりだった場合は、もう一度調べます。

于 2012-11-12T02:19:10.037 に答える