自动映射从源和输出引用的同一模型的对象
Automapping objects of the same model referenced from both source and output
我想通过自动映射从模型到视图模型。我的视图模型看起来像这样,模型 (FooBarRecord
) 几乎没有额外的属性,bar
属性是相同的:
public class FooBarVm
{
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public id barbaz_id { get; set; }
public string barbaz_name { get; set; }
}
public class FooBarRecord
{
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public int foo2 { get; set; }
public BarBazRecord barbaz { get; set; }
}
public class BarRecord
{
public int id { get; set; }
public BarBazRecord baz { get; set; }
public string bar1 { get; set; }
public int bar2 { get; set; }
}
public class BarBazRecord
{
public int id { get; set; }
public string name { get; set; }
}
问题出在栏目中。我的自动映射器配置如下所示:
Mapper.CreateMap<FooBarRecord, FooBarVm>()
.ForMember(s => s.bar, m => m.MapFrom(rec => rec.bar))
//other columns - those are OK
;
我还尝试了一些其他方法,比如定义从 BarRecord
到 BarRecord
或 substitution of rec
for rec.bar
and mapping from FooBarRecord
to BarRecord
的映射。我发现唯一可行的解决方案是展平 BarRecord
,将其所有属性添加到 FooBarVm
而不是单个引用 - 但这很丑陋且难以维护,绝对不是我想要的。
编辑:类 只是示例,真实的有更多属性,但我已经检查过它们没问题。可能有点作用的是BarRecord
的属性中有一个对象,所以我把它加成BarBazRecord
.
错误信息如下:
The following 4 properties on Foo.Bar.ViewModels.FooBarVm are not mapped:
bar1
bar2
id
name
这些都是BarRecord
和BarBazRecord
的非对象属性。我试着这样解决它们:
.ForMember(s => s.bar.bar1, m => m.MapFrom(rec => rec.bar.bar1))
甚至忽略它们:
.ForMember(s => s.bar.bar1, opt => opt.Ignore())
但错误消息刚刚更改为 "System.ArgumentException: Expression 's => s.poskytovatel.ulice' must resolve to top-level member." 我确认有效的唯一解决方案是从第一个错误消息(在我的实际情况中有数十个属性)添加整个列表,只需更改代码比如从 bar = vm.bar;
到 bar = GetBar(vm.bar_id);
这是一个解决方法,但我更愿意学习一个合适的解决方案。
EDIT2:即使解决方法失败了:-(无论我做什么,我的第一个错误仍然存在。我将 bar
更改为 bar_id
添加所有 BarRecord
属性FooBarVm
。然后我尝试映射新属性 (m.MapFrom(rec => rec.bar.bar1)
) 或忽略它们 (opt => opt.Ignore()
),甚至从 [=24= 中删除对 BarRecord
的任何引用] 和自动映射器配置。没有任何变化 - 所有未直接出现在 FooBarRecord
中的属性都被列为未映射,即使被忽略或从嵌套模型映射。向 FooBarRecord
添加虚拟属性显然是不正确的方式,尽管它是被证明会影响错误消息的唯一方式,除了用其他错误覆盖它。
我更新了模型 - BarBazRecord
也从 FooBarRecord
引用,并且 FooBarVm
包含从 BarBazRecord
映射的属性。这些属性似乎已正确映射,它们未包含在未映射属性列表中。更奇怪了。
我将此作为答案发布,因为它太大而无法发表评论。在当前形式下,使用 Automapper 4.2,您的映射应该可以正常工作(见下文)。我所做的唯一更改是将 barbaz_id
定义为 int
,而不是 id
,以便编译代码。所以,对于类型:
public class FooBarVm {
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public int barbaz_id { get; set; }
public string barbaz_name { get; set; }
}
public class FooBarRecord {
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public int foo2 { get; set; }
public BarBazRecord barbaz { get; set; }
}
public class BarRecord {
public int id { get; set; }
public BarBazRecord baz { get; set; }
public string bar1 { get; set; }
public int bar2 { get; set; }
}
public class BarBazRecord {
public int id { get; set; }
public string name { get; set; }
}
定义映射:
Mapper.CreateMap<FooBarRecord, FooBarVm>();
定义来源:
var src = new FooBarRecord { bar = new BarRecord { bar1 = "b1", bar2 = 23,
baz = new BarBazRecord { id = 5,
name = "nme" },
id = 2 },
barbaz = new BarBazRecord { name = "nee",
id = 3 },
foo = "fooo", foo2 = 123, id = 99 };
并将其映射到目的地:
var dest = Mapper.Map<FooBarVm>(src);
所有字段都已映射,没有任何错误。如果您正在做一些不同的事情,您应该更新您的问题以使错误可重现。或者,您可能想检查您是否使用了最新版本的映射器。
问题出在另一个映射中,但我也需要解决它,只是稍后。最后,correct use of ForAllMembers(opt => opt.Ignore()
成功了。
Mapper.CreateMap<FooBarRecord, FooBarVm>().ForAllMembers(opt => opt.Ignore());
Mapper.CreateMap<FooBarRecord, FooBarVm>()
.ForMember(s => s.bar, m => m.MapFrom(rec => rec.bar))
//other columns - those are OK
;
我想通过自动映射从模型到视图模型。我的视图模型看起来像这样,模型 (FooBarRecord
) 几乎没有额外的属性,bar
属性是相同的:
public class FooBarVm
{
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public id barbaz_id { get; set; }
public string barbaz_name { get; set; }
}
public class FooBarRecord
{
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public int foo2 { get; set; }
public BarBazRecord barbaz { get; set; }
}
public class BarRecord
{
public int id { get; set; }
public BarBazRecord baz { get; set; }
public string bar1 { get; set; }
public int bar2 { get; set; }
}
public class BarBazRecord
{
public int id { get; set; }
public string name { get; set; }
}
问题出在栏目中。我的自动映射器配置如下所示:
Mapper.CreateMap<FooBarRecord, FooBarVm>()
.ForMember(s => s.bar, m => m.MapFrom(rec => rec.bar))
//other columns - those are OK
;
我还尝试了一些其他方法,比如定义从 BarRecord
到 BarRecord
或 substitution of rec
for rec.bar
and mapping from FooBarRecord
to BarRecord
的映射。我发现唯一可行的解决方案是展平 BarRecord
,将其所有属性添加到 FooBarVm
而不是单个引用 - 但这很丑陋且难以维护,绝对不是我想要的。
编辑:类 只是示例,真实的有更多属性,但我已经检查过它们没问题。可能有点作用的是BarRecord
的属性中有一个对象,所以我把它加成BarBazRecord
.
错误信息如下:
The following 4 properties on Foo.Bar.ViewModels.FooBarVm are not mapped:
bar1
bar2
id
name
这些都是BarRecord
和BarBazRecord
的非对象属性。我试着这样解决它们:
.ForMember(s => s.bar.bar1, m => m.MapFrom(rec => rec.bar.bar1))
甚至忽略它们:
.ForMember(s => s.bar.bar1, opt => opt.Ignore())
但错误消息刚刚更改为 "System.ArgumentException: Expression 's => s.poskytovatel.ulice' must resolve to top-level member." 我确认有效的唯一解决方案是从第一个错误消息(在我的实际情况中有数十个属性)添加整个列表,只需更改代码比如从 bar = vm.bar;
到 bar = GetBar(vm.bar_id);
这是一个解决方法,但我更愿意学习一个合适的解决方案。
EDIT2:即使解决方法失败了:-(无论我做什么,我的第一个错误仍然存在。我将 bar
更改为 bar_id
添加所有 BarRecord
属性FooBarVm
。然后我尝试映射新属性 (m.MapFrom(rec => rec.bar.bar1)
) 或忽略它们 (opt => opt.Ignore()
),甚至从 [=24= 中删除对 BarRecord
的任何引用] 和自动映射器配置。没有任何变化 - 所有未直接出现在 FooBarRecord
中的属性都被列为未映射,即使被忽略或从嵌套模型映射。向 FooBarRecord
添加虚拟属性显然是不正确的方式,尽管它是被证明会影响错误消息的唯一方式,除了用其他错误覆盖它。
我更新了模型 - BarBazRecord
也从 FooBarRecord
引用,并且 FooBarVm
包含从 BarBazRecord
映射的属性。这些属性似乎已正确映射,它们未包含在未映射属性列表中。更奇怪了。
我将此作为答案发布,因为它太大而无法发表评论。在当前形式下,使用 Automapper 4.2,您的映射应该可以正常工作(见下文)。我所做的唯一更改是将 barbaz_id
定义为 int
,而不是 id
,以便编译代码。所以,对于类型:
public class FooBarVm {
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public int barbaz_id { get; set; }
public string barbaz_name { get; set; }
}
public class FooBarRecord {
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public int foo2 { get; set; }
public BarBazRecord barbaz { get; set; }
}
public class BarRecord {
public int id { get; set; }
public BarBazRecord baz { get; set; }
public string bar1 { get; set; }
public int bar2 { get; set; }
}
public class BarBazRecord {
public int id { get; set; }
public string name { get; set; }
}
定义映射:
Mapper.CreateMap<FooBarRecord, FooBarVm>();
定义来源:
var src = new FooBarRecord { bar = new BarRecord { bar1 = "b1", bar2 = 23,
baz = new BarBazRecord { id = 5,
name = "nme" },
id = 2 },
barbaz = new BarBazRecord { name = "nee",
id = 3 },
foo = "fooo", foo2 = 123, id = 99 };
并将其映射到目的地:
var dest = Mapper.Map<FooBarVm>(src);
所有字段都已映射,没有任何错误。如果您正在做一些不同的事情,您应该更新您的问题以使错误可重现。或者,您可能想检查您是否使用了最新版本的映射器。
问题出在另一个映射中,但我也需要解决它,只是稍后。最后,correct use of ForAllMembers(opt => opt.Ignore()
成功了。
Mapper.CreateMap<FooBarRecord, FooBarVm>().ForAllMembers(opt => opt.Ignore());
Mapper.CreateMap<FooBarRecord, FooBarVm>()
.ForMember(s => s.bar, m => m.MapFrom(rec => rec.bar))
//other columns - those are OK
;