如何防止 AutoMapper 覆盖目标对象上的现有值?
How to prevent AutoMapper from overwriting existing values on destination object?
我有以下实体和相应的视图模型
public class TopEntity
{
public int Id { get; set; }
public ICollection<BottomEntity> Bottoms { get; set; }
}
public class BottomEntity
{
public int Id { get; set; }
public int TopId { get; set; }
}
public class TopEntityViewModel
{
public int Id { get; set; }
public ICollection<BottomEntityViewModel> Bottoms { get; set; }
}
public class BottomEntityViewModel
{
public int Id { get; set; }
}
我想将类型 TopEntityViewModel
的实例映射到类型 TopEntity
的实例,而不覆盖 BottomEntity.TopId
上可能已经存在的任何值。
我按如下方式配置了 AutoMapper:
var mapperConfig = new MapperConfiguration(exp =>
{
exp.CreateMap<TopEntity, TopEntityViewModel>();
exp.CreateMap<BottomEntity, BottomEntityViewModel>();
exp.CreateMap<TopEntityViewModel, TopEntity>();
exp.CreateMap<BottomEntityViewModel, BottomEntity>()
.ForMember(dest => dest.TopId, opts => opts.Ignore());
});
我添加了 .ForMember(dest => dest.TopId, opts => opts.Ignore());
以在映射期间忽略 BottomEntity.TopId
,认为它应该有助于保留现有值。
我正在像这样映射实例:
mapperConfig.AssertConfigurationIsValid();
var mapper = mapperConfig.CreateMapper();
var topEntity = new TopEntity
{
Id = 45,
Bottoms = new List<BottomEntity>
{
new BottomEntity
{
Id = 56,
TopId = 45
},
new BottomEntity
{
Id = 57,
TopId = 45
}
}
};
var topEntityVm = new TopEntityViewModel
{
Id = 45,
Bottoms = new List<BottomEntityViewModel>
{
new BottomEntityViewModel
{
Id = 56,
},
new BottomEntityViewModel
{
Id = 57
}
}
};
var updatedTopEntity = mapper.Map(topEntityVm, topEntity);
当我访问 updatedTopEntity.Bottoms[<whatever>].TopId
时,它总是设置为 0。
如果我更新 class 上 属性 BottomEntity.TopId
的定义以具有类似 1000
的默认值,映射后我的所有 updatedTopEntity.Bottoms[<whatever>].TopId
都设置为该默认值值(示例中的 1000
)。
我检查了从 mapper.Map
返回的引用是否映射了原始引用,它们确实映射了。
如何防止 AutoMapper 删除现有实例上的任何现有值?
我在 .NET Core 5 中使用 AutoMapper 10.1.1。You can try a working example here。
AutoMapper
这样说 in the documentation:
When mapping to an existing collection, the destination collection is cleared first. If this is not what you want, take a look at AutoMapper.Collection.
AutoMapper.Collection,根据文档,确实:
Adds ability to map collections to existing collections without re-creating the collection object.
Will Add/Update/Delete items from a preexisting collection object based on user defined equivalency between the collection's generic item type from the source collection and the destination collection.
安装后 AutoMapper.Collection
我更新了 AutoMapper 配置如下:
var mapperConfig = new MapperConfiguration(exp =>
{
exp.AddCollectionMappers();
exp.CreateMap<TopEntity, TopEntityViewModel>();
exp.CreateMap<BottomEntity, BottomEntityViewModel>();
exp.CreateMap<TopEntityViewModel, TopEntity>();
exp.CreateMap<BottomEntityViewModel, BottomEntity>()
.ForMember(dest => dest.TopId, opts => opts.Ignore())
.EqualityComparison((src, dest) => src.Id == dest.Id);
});
行 .EqualityComparison((src, dest) => src.Id == dest.Id);
添加了 AutoMapper 将使用的相等比较,如下所示:
- 如果 ID 匹配,则 AutoMapper 会将 BottomEntityViewModel 映射到 BottomEntity
- 如果 BottomEntityViewModel 存在而 BottomEntity 不存在,则 AutoMapper 将从 BottomEntityViewModel 映射的新 BottomEntity 添加到集合中
- 如果 BottomEntity 存在而 BottomEntityViewModel 不存在,则 AutoMapper 将从集合中移除 BottomEntity
AutoMapper.Collection
is described here
的这种行为
工作示例:https://dotnetfiddle.net/tnaUjY
感谢Lucian Bargaoanu给我指明了正确的方向
我有以下实体和相应的视图模型
public class TopEntity
{
public int Id { get; set; }
public ICollection<BottomEntity> Bottoms { get; set; }
}
public class BottomEntity
{
public int Id { get; set; }
public int TopId { get; set; }
}
public class TopEntityViewModel
{
public int Id { get; set; }
public ICollection<BottomEntityViewModel> Bottoms { get; set; }
}
public class BottomEntityViewModel
{
public int Id { get; set; }
}
我想将类型 TopEntityViewModel
的实例映射到类型 TopEntity
的实例,而不覆盖 BottomEntity.TopId
上可能已经存在的任何值。
我按如下方式配置了 AutoMapper:
var mapperConfig = new MapperConfiguration(exp =>
{
exp.CreateMap<TopEntity, TopEntityViewModel>();
exp.CreateMap<BottomEntity, BottomEntityViewModel>();
exp.CreateMap<TopEntityViewModel, TopEntity>();
exp.CreateMap<BottomEntityViewModel, BottomEntity>()
.ForMember(dest => dest.TopId, opts => opts.Ignore());
});
我添加了 .ForMember(dest => dest.TopId, opts => opts.Ignore());
以在映射期间忽略 BottomEntity.TopId
,认为它应该有助于保留现有值。
我正在像这样映射实例:
mapperConfig.AssertConfigurationIsValid();
var mapper = mapperConfig.CreateMapper();
var topEntity = new TopEntity
{
Id = 45,
Bottoms = new List<BottomEntity>
{
new BottomEntity
{
Id = 56,
TopId = 45
},
new BottomEntity
{
Id = 57,
TopId = 45
}
}
};
var topEntityVm = new TopEntityViewModel
{
Id = 45,
Bottoms = new List<BottomEntityViewModel>
{
new BottomEntityViewModel
{
Id = 56,
},
new BottomEntityViewModel
{
Id = 57
}
}
};
var updatedTopEntity = mapper.Map(topEntityVm, topEntity);
当我访问 updatedTopEntity.Bottoms[<whatever>].TopId
时,它总是设置为 0。
如果我更新 class 上 属性 BottomEntity.TopId
的定义以具有类似 1000
的默认值,映射后我的所有 updatedTopEntity.Bottoms[<whatever>].TopId
都设置为该默认值值(示例中的 1000
)。
我检查了从 mapper.Map
返回的引用是否映射了原始引用,它们确实映射了。
如何防止 AutoMapper 删除现有实例上的任何现有值?
我在 .NET Core 5 中使用 AutoMapper 10.1.1。You can try a working example here。
AutoMapper
这样说 in the documentation:
When mapping to an existing collection, the destination collection is cleared first. If this is not what you want, take a look at AutoMapper.Collection.
AutoMapper.Collection,根据文档,确实:
Adds ability to map collections to existing collections without re-creating the collection object.
Will Add/Update/Delete items from a preexisting collection object based on user defined equivalency between the collection's generic item type from the source collection and the destination collection.
安装后 AutoMapper.Collection
我更新了 AutoMapper 配置如下:
var mapperConfig = new MapperConfiguration(exp =>
{
exp.AddCollectionMappers();
exp.CreateMap<TopEntity, TopEntityViewModel>();
exp.CreateMap<BottomEntity, BottomEntityViewModel>();
exp.CreateMap<TopEntityViewModel, TopEntity>();
exp.CreateMap<BottomEntityViewModel, BottomEntity>()
.ForMember(dest => dest.TopId, opts => opts.Ignore())
.EqualityComparison((src, dest) => src.Id == dest.Id);
});
行 .EqualityComparison((src, dest) => src.Id == dest.Id);
添加了 AutoMapper 将使用的相等比较,如下所示:
- 如果 ID 匹配,则 AutoMapper 会将 BottomEntityViewModel 映射到 BottomEntity
- 如果 BottomEntityViewModel 存在而 BottomEntity 不存在,则 AutoMapper 将从 BottomEntityViewModel 映射的新 BottomEntity 添加到集合中
- 如果 BottomEntity 存在而 BottomEntityViewModel 不存在,则 AutoMapper 将从集合中移除 BottomEntity
AutoMapper.Collection
is described here
的这种行为
工作示例:https://dotnetfiddle.net/tnaUjY
感谢Lucian Bargaoanu给我指明了正确的方向