繁体   English   中英

具有字段级别类型转换的AutoMapper.ProjectTo

[英]AutoMapper.ProjectTo with field level type conversion

我正在尝试使用AutoMapper的ProjectTo扩展方法将基于Entity Framework表的对象转换为自定义DTO。 EF侧的Person实体如下所示:

public partial class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public string Age { get; set; }
}

我要投影的PersonViewModel DTO看起来像这样:

public class PersonViewModel
{
    public PersonViewModel(Person p)
    {
        PersonId = p.PersonId;
        Name = p.Name;
        Age = Convert.ToInt32(p.Age);
    }

    public PersonViewModel()
    {

    }

    public PersonViewModel(int id, string name, int age)
    {
        PersonId = id;
        Name = name;
        Age = age;
    }

    public int PersonId { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

要注意的关键是人员表包含一个名为Age的字段,该字段是nvarchar类型,而PersonViewModel的Age类型是int类型。 不幸的是,我无法更改表,而必须找到一种方法来转换数据。

以下代码是我尝试过的AutoMapper配置,它们的“问题”以及使用代码(数据库调用等)。

MapperConfiguration config = new MapperConfiguration(cfg => 
        {
            // -----  Throws "Unable to create map expression" exception  ------
            //cfg.CreateMap<Person, PersonViewModel>();


            // -----  Throws "Linq to Entities does not support method" exception  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ForMember(dest => dest.Age, opt => opt.MapFrom(src => Convert.ToInt32(src.Age)));


            // -----  Throws "Unable to create map expression" exception  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ConstructProjectionUsing(src => new PersonViewModel
            //    {
            //        PersonId = src.PersonId,
            //        Name = src.Name,
            //        Age = Convert.ToInt32(src.Age)
            //    });


            // -----  Throws "Unable to create map expression" exception  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ConstructProjectionUsing(src => new PersonViewModel(src.PersonId, src.Name, Convert.ToInt32(src.Age)));


            // -----  Throws "Unable to create map expression" exception  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ConstructProjectionUsing(src => new PersonViewModel(src.PersonId, src.Name, 25));


            // -----  Throws "Linq to Entities does not support method" exception  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ProjectUsing(src => new PersonViewModel
            //    {
            //        PersonId = src.PersonId,
            //        Name = src.Name,
            //        Age = Convert.ToInt32(src.Age)
            //    });


            // -----  Throws "Unable to create map expression" exception  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ConstructUsing(src => new PersonViewModel
            //    {
            //        PersonId = src.PersonId,
            //        Name = src.Name,
            //        Age = Convert.ToInt32(src.Age)
            //    });


            // -----  Throws "Unable to create map expression" exception  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ConstructUsing(src => new PersonViewModel(src));


            // -----  Doesn't throw exception, but all values are null or 0.  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ConvertUsing(src => new PersonViewModel
            //    {
            //        PersonId = src.PersonId,
            //        Name = src.Name,
            //        Age = Convert.ToInt32(src.Age)
            //    });


            // -----  Doesn't throw exception, but all values are null or 0.  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ConvertUsing(src => new PersonViewModel(src.PersonId, src.Name, Convert.ToInt32(src.Age)));


            // -----  Works, but bypasses the conversion I need  ------
            //cfg.CreateMap<Person, PersonViewModel>()
            //    .ProjectUsing(src => new PersonViewModel
            //    {
            //        PersonId = src.PersonId,
            //        Name = src.Name,
            //        Age = 25
            //    });


            // -----  Works, but bypasses the conversion I need  ------
            cfg.CreateMap<Person, PersonViewModel>()
                .ForMember(dest => dest.Age, opt => opt.MapFrom(src => 35));
        });

        using (FamilyEntities db = new FamilyEntities())
        {
            PersonViewModel p = db.Set<Person>()
                .Where(x => x.PersonId == 1)
                .ProjectTo<PersonViewModel>(config)
                .SingleOrDefault();

            Console.WriteLine("Name: " + p.Name + Environment.NewLine + "Age: " + p.Age);
        }

        Console.ReadLine();

使用AutoMapper的ProjectTo可以将字符串转换为int吗? 其次,如果可能,该配置是什么样的?

在此先感谢您的帮助。

您的第一个尝试就是为什么此方法不起作用。 实体框架不知道如何将字符串转换为int,因此您无所适从。 没有其他方法很重要,重要的是EF给您带来的例外。

如果EF不支持该转换,则AutoMapper无法帮助您。

相反,我会在您的viewmodel内部执行类似转换的操作:

public class PersonViewModel
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public string Age { get; set; }
    public int AgeValue => Convert.ToInt32(Age);
} 

https://stackoverflow.com/a/24027242/1736944解释了如何向EF添加功能。 基本上,生成的查询将必须执行类型转换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM