dotnetcore / FreeSql

🦄 .NET aot orm, C# orm, VB.NET orm, Mysql orm, Postgresql orm, SqlServer orm, Oracle orm, Sqlite orm, Firebird orm, 达梦 orm, 人大金仓 orm, 神通 orm, 翰高 orm, 南大通用 orm, 虚谷 orm, 国产 orm, Clickhouse orm, QuestDB orm, MsAccess orm.
http://freesql.net
MIT License
3.99k stars 842 forks source link

升级衍生bug,原功能 "Api 命名换成了 SetDtoIgnore,使用习惯与 SetSourceIgnore 一致" #1773

Closed easy999000 closed 3 weeks ago

easy999000 commented 1 month ago
          Api 命名换成了 SetDtoIgnore,使用习惯与 SetSourceIgnore 一致

Originally posted by @2881099 in https://github.com/dotnetcore/FreeSql/issues/1688#issuecomment-1855756525

原功能链接:https://github.com/dotnetcore/FreeSql/pull/1688#issuecomment-1855756525

大佬,这个接口是我提供的,最近我准备删掉我自己的扩展方法,使用这个方法的时候,我发现了一个问题. 我提供的接口原型是. public IUpdate SetDtoIgnoreNull(object dto) 而最后经过你的改名后的接口原型变成了 IUpdate SetSourceIgnore(T1 source, Func<object, bool> ignore = null);

这个参数类型从 Object变成T1后,对这个接口影响巨大,这导致这个接口与原始意图不符.

我的原始意图是, 传入参数是一个符合的DTO,这个DTO,并不是DB中的类型. 在执行更新的时候,与原始 SetDto方法一直.DTO中与数据库字段名字不匹配的属性,不进行操作, 紧紧是增加了对Null值的过滤.他的基础,还是原来的 SetDto方法思路.

现在这个改成T1之后. 传入类型必须是DB类型,那字段就永远不会是null了. 这个方法相当于没有使用场景.

DTO不需要是原始的db类型

2881099 commented 1 month ago

没看懂意思

easy999000 commented 1 month ago

没看懂意思 我提交的原型是 public IUpdate SetDtoIgnoreNull(object dto)
经过你修改后原型改成了. IUpdate SetSourceIgnore(T1 source, Func<object, bool> ignore = null); 对比

IUpdate SetDtoIgnoreNull( object dto)
IUpdate SetSourceIgnore( T1 source, Func<object, bool> ignore = null);

区别是,一个传入类型是object,一个传入类型是T11.

我的方法扩展,源之于,SetDTO,也就是说,传入参数的DTO可以是任何类型,不是必须强制是DB的实体类型. 多几个字段少几个字段是无所谓的. 少的字段不做更新,多的字段,忽略不计. 只有名称匹配了才进行更新, 我只是进一步加了一个功能,就是如果参数值是null,也不进行更新.

你修改之后的方法是,传入参数必须是数据库的DB实体类型,而这个实体类型和数据库是对应的,字段大部分是不可以null的,而且在日常工作中,传入参数往往不是db类型,而且一个DTO,那么还需要二次转换. 数据库中的,比如年龄,单价,数量,税率, 这些字段往往是不可以null的类型. 那么也就没法使用这个Ignore null的思路了.

我的想法是,一个dto,我给哪个字段赋值,我就更新哪个字段,字段是null的,我不进行操作. 如果类型是T1. 是没有办法执行这个思路的.

easy999000 commented 1 month ago

` public class ProcureMaterialApplyDTO {

    public int ID { get; set; }

    /// <summary>
    /// 发起人
    /// </summary>
    /// 
    public int? AccountID { get; set; }

    public string Annex1 { get; set; }

    public string Annex2 { get; set; }

    public int? PayMode { get; set; } = 0;

    public int? ProjectID { get; set; }

    /// <summary>
    /// 标题
    /// </summary>
    /// 
    public string Title { get; set; }

    /// <summary>
    /// 总金额
    /// </summary>
    /// 
    public decimal? TotalAmount { get; set; } = 0.0000M;
}`

我一般会定义一个这样的DTO.所有参数都是可以null的,更新的时候,我给哪个字段赋值,就更新哪个,不赋值的,不操作. 不会把null更新进去. 而db的实体,都是不可以null的.而且这个dto和db实体字段不是一致的,这个dto是多个db字段组合起来的. 对外接口的传入参数字段,不可能是完整的一个db实体,肯定都是复核多个db字段的dto,更新的时候, 只更新和db对应名称的字段.

2881099 commented 1 month ago

Debug一下源代码

easy999000 commented 1 month ago

Debug一下源代码

不太明白这个意思.debug什么. 我说一下我的原始思路, 系统一般会对外开放一个api. 这个api,一般会有一个传入参数dto. 这个dto,并不一定是一个db实体类型.往往都是几个表字段的复核类型.
{订单_订单id, 订单_更新时间, 明细_数量, 明细_价格, 订单_总金额, 订单付款类型 ,用户_余额,用户_下单数量 }. 这个dto中的字段,实际是来源于数据库中的不同的表. 组合成的这个接口的参数dto. 这个dto中的所有字段都是可以null的. int? decimal?. 而db中的字段是完全不可以null的. 那么用户调用这个接口的时候, 可以通过给值赋值的方式,来控制更新哪些字段,不需要更新的字段,保持null即可. 我可以通过设置值是否是null来控制更新哪些字段. 那么2个问题, 1.这个dto类型,不必强制必须是db的实体类型, 2.所有字段必须可null. 但是你修改后的方法原型. IUpdate SetSourceIgnore( T1 source, Func<object, bool> ignore = null); 我只能传入db的实体类型, 那这样我还得把传入的dto强制转换成db类型.这没意义呀. 其次,转成db类型后,大部分字段都是不可hull的,这会导致,整个实体更新,把所有字段给覆盖掉.我还得去数据库里面把原始值查询出来,那这个方法就彻底废了.

所以我认为,应该基于 SetDtoI进行扩展,而不是基于 SetSource进行扩展.

应该添加方法 IUpdate SetDtoIgnore( object source, Func<object, bool> ignore = null);

luoyunchong commented 1 month ago

应当自己决定哪些字段忽略更新,而不是仅通过数据为null,否则如果数据库中 可为空,又无法将数据更新成空,这是存在问题的

easy999000 commented 1 month ago

如果数据库中 可为空

这是api的一个自定义的规则,也是一种便捷的方案.对于需要更新值null的情况,会有其他特定的方案. 我的思路只是想,实现快速开发,用最简便的方法,完成所需要的工作.

关于为什么要设定这样的一个接口,请参考原,讨论记录.https://github.com/dotnetcore/FreeSql/pull/1688#issuecomment-1855756525