前言
ABP中有一个很好的思想,我认为就是Dto+Mapper 说白点就是一个数据库表,你在API中,或者是UI中需要以什么业务展示,就拆分成多个Dto 按照需要的情况去添加或者缩减字段 比如登录,你只要账号和密码,再添加一些其他字段等 如果是注册,有注册的字段 最后在提交给数据库前通过Map把数据转化成数据库表的信息,最后更新或者是写入等! 问题 后面我发现有这么一个问题!!!
直接代码
先看代码
/// <summary>
/// 批量编辑
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
[TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "edit" })]
public async Task<string> BatchUpdate(List<DragAttributeInfoUpdateDto> input)
{
var ids = input.Where(x => x.Id != 0).Select(x => x.Id).ToArray();
var infos = await _dbContext.DragAttributeInfo.Where(x => ids.Contains(x.Id)).ToListAsync();
if (infos?.Any() == false)
{
throw new PasteCodeException("没有获得有效数据,请确认数据是否正确!");
}
//方法一
foreach (var item in infos)
{
var find = input.Where(x => x.Id == item.Id).FirstOrDefault();
if (find != null && find != default)
{
ObjectMapper.Map<DragAttributeInfoUpdateDto, DragAttributeInfo>(find, item);
}
}
//方法二
//打印input可以获得新的数据,标识上面的转化是正常的,其实不正常上面也就报错了,因为读取不到数据
//ObjectMapper.Map<List<DragAttributeInfoUpdateDto>, List<DragAttributeInfo>>(input, infos);
//打印infos可以看到数据已经转换了
await _dbContext.SaveChangesAsync();
return "批量编辑完成,刷新后可见!";
}
上面代码,你肯定会说用方法二就行了,简单干净,干嘛要搞方法一? 再看看另外一个代码
/// <summary>
/// 批量编辑
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
[TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "edit" })]
public async Task<string> BatchUpdate(List<DragAttributeValueUpdateDto> input)
{
var ids = input.Where(x => x.Id != 0).Select(x => x.Id).ToArray();
var infos = await _dbContext.DragAttributeValue.Where(x => ids.Contains(x.Id)).ToListAsync();
if (infos?.Any() == false)
{
throw new PasteCodeException("没有获得有效数据,请确认数据是否正确!");
}
foreach (var item in infos)
{
var find = input.Where(x => x.Id == item.Id).FirstOrDefault();
if (find != null && find != default)
{
find.DragAttributeId = item.DragAttributeId;
}
}
ObjectMapper.Map<List<DragAttributeValueUpdateDto>, List<DragAttributeValue>>(input, infos);
await _dbContext.SaveChangesAsync();
return "批量编辑完成,刷新后可见!";
}
其实站我角度,我是真的不理解的,为啥片段一的方法一不行呢!!!
数据模型
一起来看看他们的数据模型
///<summary>
///属性
///</summary>
public class DragAttributeInfoAddDto
{
///<summary>
///名称
///</summary>
[MaxLength(16)]
[Required]
public string Name { get; set; }
///<summary>
///状态
///</summary>
public bool IsEnable { get; set; } = true;
///<summary>
///排序
///</summary>
public int Sort { get; set; }
///<summary>
///描述
///</summary>
[MaxLength(64)]
public string Desc { get; set; } = "";
///<summary>
///备注
///</summary>
[MaxLength(64)]
public string Mark { get; set; } = "";
}
///<summary>
///属性
///</summary>
public class DragAttributeInfoUpdateDto : DragAttributeInfoAddDto
{
///<summary>
///ID
///</summary>
[PasteHidden]
public int Id { get; set; }
}
另外一个的
///<summary>
///属性值 记录每一个属性的可选值
///</summary>
public class DragAttributeValueAddDto
{
///<summary>
///属性
///</summary>
[PasteQuery("attribute_id", true)]
[PasteRequired]
public int DragAttributeId { get; set; }
///<summary>
///值 示例3,3.2
///</summary>
[MaxLength(16)]
public string Value { get; set; }
///<summary>
///默认选中
///</summary>
public bool Default { get; set; } = false;
///<summary>
///排序
///</summary>
public int Sort { get; set; }
///<summary>
///描述
///</summary>
[MaxLength(128)]
public string Desc { get; set; }
}
///<summary>
///属性值 记录每一个属性的可选值
///</summary>
public class DragAttributeValueUpdateDto : DragAttributeValueAddDto
{
///<summary>
///ID
///</summary>
[PasteHidden]
public int Id { get; set; }
}
我实在是没发现有啥特殊的地方 上面的Paste特性是PasteForm框架的特性,里面并没有校验啥的,相当于没写一样,就这样的,居然一个Mapper.List成功,一个Mapper.List失败?
测试结果
正和上面的方法二注释的那样,其实并不是Mapper的问题? 或者说也是Mapper的问题 我们都知道Mapper其实干了2件事 1.按照Mapper规则,对对应字段进行变更 2.标记这个实体的这个字段的变更属性为true,也就是Tracker的EntityState 可是测试结果就是,保存没报错,重新读取数据后,发现数据没更新 别和我说某一个字段,我是能改的字段都改了测试,结果一样!!!
回想
其实这个问题我以前也遇到过一次,就是做商城的SKU的时候,一开始我也是List直接Mapper的,结果死活对不上数据,后面不得不拆开一个一个属性赋值的!!! 后面我感觉优点问题,会不会是List的问题,改成和上面的方法二一样的测试了下可以了。。。。 我有种想吐的感觉! 后面事情多了,也就忘了继续深究了 今天又被我碰到了 先做一下记录 后续我看看啥问题 如果你知道是啥问题产生的,欢迎在评论区留言!!!