gpt4 book ai didi

c# - AutoMapper - 可空和不可空整数的不同 ProjectUsings

转载 作者:太空狗 更新时间:2023-10-30 01:01:26 28 4
gpt4 key购买 nike

我需要使用 Entity Framework 和 AutoMapper 将数据库中的整数值投影到枚举值。问题似乎是列在某些情况下可以为空,而在其他情况下则不可为空。如果它们是可空类型,我想为空值使用默认值(第一个枚举值)。

这是一个完整的、最小的示例,我将其与我当前的方法放在一起。它是一个控制台应用程序,安装了 Entity Framework 和 AutoMapper 的当前 nuget 包。它还需要一个数据库(首先是数据库),其中包含如下表:

CREATE TABLE [dbo].[MyTable] (
[Id] INT PRIMARY KEY,
[EnumValue] INT NOT NULL,
[EnumValueNullable] INT
)

控制台应用程序 (C#) 的代码:

public enum MyEnum
{
Value1 = 0,
Value2 = 1
}

public class MyTableModel
{
public int Id { get; set; }
public MyEnum EnumValue { get; set; }
public MyEnum EnumValueNullable { get; set; }
}

public class MyProfile : Profile
{
public MyProfile()
{
this.CreateMap<MyTable, MyTableModel>();
this.CreateMap<int, MyEnum>().ProjectUsing(x => (MyEnum)x);
this.CreateMap<int?, MyEnum>().ProjectUsing(x => x.HasValue ? (MyEnum)x.Value : MyEnum.Value1);
}
}

static void Main(string[] args)
{
var config = new MapperConfiguration(x => x.AddProfile(new MyProfile()));
var result = new MyDataEntities().MyTable.ProjectTo<MyTableModel>(config).ToList();
}

当执行这段代码时,它告诉我 HasValue 没有为类型 System.Int32 定义。这当然是正确的,但我假设 AutoMapper 会选择为不可空整数指定的版本。删除任一映射(对于 int 和 int?)都没有帮助,同时删除它们或更改顺序也是如此。

作为旁注,我正在从一个更大的项目中的 3.3.1.0 版迁移 AutoMapper。它似乎适用于该版本中定义的两个 map 。

最佳答案

当前的 AutoMapper 中存在(恕我直言)错误 MapperConfiguration导致 Nullable<TSource> -> TDestination 的指定映射的类用于(覆盖已经指定的)TSource -> TDestination .通过执行以下代码可以很容易地看到:

var config = new MapperConfiguration(x => x.AddProfile(new MyProfile()));
var m1 = config.ResolveTypeMap(typeof(int), typeof(MyEnum));
var m2 = config.ResolveTypeMap(typeof(int?), typeof(MyEnum));
Console.WriteLine(m1 == m2); // true

当 AutoMapper 试图映射 TSource 时,结果就是前面提到的运行时异常。至 TDestination (在你的例子中,intMyEnum 对于 EnumValue 属性)使用指定的表达式(因为 xint ,而不是预期的 int? ,因此没有 HasValueValue 属性).

作为解决方法(或通用解决方案?)我建议只定义来自 int 的 map 至 enum ,并使用 AutoMapper Null substitution另一部分的功能。由于目前仅在属性映射级别支持 null 替换,为了更容易,我将它封装在这样的辅助方法中:

public static class AutoMapperExtensions
{
public static void NullSubstitute<TSource, TDestination>(this Profile profile, TSource nullSubstitute)
where TSource : struct
{
object value = nullSubstitute;
profile.ForAllPropertyMaps(
map => map.SourceType == typeof(TSource?) &&
map.DestinationPropertyType == typeof(TDestination),
(map, config) => config.NullSubstitute(value)
);
}
}

并像这样使用它:

public class MyProfile : Profile
{
public MyProfile()
{
this.CreateMap<MyTable, MyTableModel>();
this.CreateMap<int, MyEnum>().ProjectUsing(x => (MyEnum)x);
this.NullSubstitute<int, MyEnum>((int)MyEnum.Value1);
}
}

关于c# - AutoMapper - 可空和不可空整数的不同 ProjectUsings,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38988955/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com