• M拷贝表行数据


    在开发业务功能时候经常有需要实现复制功能。这种对应数据库后台就是拷贝数据,以前我还傻乎乎的一个个属性从老对象复制给新对象,如果一个表有80属性,就写80行赋值,扩表了再加。

    其中拷贝数据又有两个情况:
    1.从一份数据往一个不存在的数据拷贝
    2.从一个数据拷贝更新另一个数据

    对于全新拷贝数据可以借助M的对象保存的方法%ConstructClone实现,如下:

    Class OTH.TestClone Extends %RegisteredObject
    {
    
    /// w ##Class(OTH.TestClone).CloneSave()
    ClassMethod CloneSave()
    {
    	s objSave=##Class(dbo.Test).%OpenId(1)
    	//s objSave.Code="1"
    	//s objSave.CName="1"
    	//s ret=objSave.%Save()
    	s objClone=objSave.%ConstructClone()
    	s objClone.RowID=""
    	s ret=objClone.%Save()
    	zw ret
    	q ""
    	
    	
    }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    测试的Test表

    Class dbo.Test Extends %Persistent [ ClassType = persistent, DdlAllowed, Owner = {UnknownUser}, ProcedureBlock, SqlRowIdPrivate, SqlTableName = Test ]
    {
    
    /// DDL Primary Key Specification
    Index PKTEST On RowID [ PrimaryKey, SqlName = PK_TEST, Type = index, Unique ];
    
    /// 主键
    Property RowID As %Library.Integer(MAXVAL = 2147483647, MINVAL = -2147483648) [ Identity, SqlColumnNumber = 2 ];
    
    /// 代码
    Property Code As %Library.String(MAXLEN = 10) [ Required, SqlColumnNumber = 3 ];
    
    /// 名称
    Property CName As %Library.String(MAXLEN = 128) [ SqlColumnNumber = 4 ];
    
    Storage Default
    {
    <Data name="TestDefaultData">
    <Value name="1">
    <Value>%%CLASSNAME</Value>
    </Value>
    <Value name="2">
    <Value>Code</Value>
    </Value>
    <Value name="3">
    <Value>CName</Value>
    </Value>
    </Data>
    <DataLocation>^dbo.TestD</DataLocation>
    <DefaultData>TestDefaultData</DefaultData>
    <IdLocation>^dbo.TestD</IdLocation>
    <IndexLocation>^dbo.TestI</IndexLocation>
    <StreamLocation>^dbo.TestS</StreamLocation>
    <Type>%Library.CacheStorage</Type>
    }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    全新拷贝很好说,拷贝结构OK,今天主要说第二种情况。比如我遇到的功能就是复制粘贴菌结果。这时候是把一个RowID的数据和他子表数据拷贝到另一个RowID的数据和他子表。这时候借助%ConstructClone就会报错,报RowID不可修改。

    如下是会报错的,报RowID不可修改

    Class OTH.TestClone Extends %RegisteredObject
    {
    
    /// w ##Class(OTH.TestClone).CloneSave()
    ClassMethod CloneSave()
    {
    	//把1的属性值拷贝到2里面
    	s objSave=##Class(dbo.Test).%OpenId(1)
    	s objClone=objSave.%ConstructClone()
    	s objClone.RowID=2
    	s ret=objClone.%Save()
    	zw ret
    	q ""
    	
    	
    }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    报错如下:
    在这里插入图片描述

    为此实现自己的拷贝属性方法

    /// 拷贝相同表的两个对象属性
    /// w ##Class(LIS.WS.DHCLISServiceBase).CopyTableRow()
    /// SourceObj:源对象
    /// PerObj:目标对象
    /// NoCopyList:不复制列名列表 s NoCopyMap=$lb("aa","bb")
    ClassMethod CopyTableRow(SourceObj, PerObj, NoCopyList)
    {
    	s SourceObj=$g(SourceObj)
    	s PerObj=$g(PerObj)
    	s NoCopyList=$g(NoCopyList)
    	s NoCopyMap=""
    	i $l(NoCopyList) d
    	.f i=1:1:$ll(NoCopyList) d
    	..s NoCopyMap($lg(NoCopyList,i))=""
    	s TableName=$CLASSNAME(SourceObj)
    	s rset = ##class(%ResultSet).%New()
    	d rset.Prepare("select COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='dbo' AND REPLACE(TABLE_NAME,'_','')='"_$REPLACE(TableName,"dbo.","")_"' Order by ORDINAL_POSITION")
    	s exeret=rset.Execute()
    	While(rset.Next())
        {
    	    s colField=rset.GetColumnName(1)
            s ColValue=rset.GetDataByName(colField)
            i (ColValue'="RowID")&&('$d(NoCopyMap(ColValue))) d
            .s exeStr="(SourceObj,PerObj) s PerObj."_ColValue_"=SourceObj."_ColValue
            .x (exeStr,.SourceObj,.PerObj)
        }
        q 1
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    这样多表拷贝就变成如下代码实现了
    借助了托管事务保证事务性,托管事务参照托管事务
    托管事务使用

    /// 拷贝结果
    /// w ##Class(IDP.WS.BLL.DHCIDPResult).CopyOrgResMTHD("6281","6295","","","","","","","","","","","","","")
    /// SourceResDR:源报告结果主键
    /// PerResDR:目标报告结果主键
    ClassMethod CopyOrgResMTHD(SourceResDR, PerResDR, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions, Output RowCount As %String) As %String
    {
    	s SourceResDR=$g(SourceResDR)
    	s PerResDR=$g(PerResDR)
    	//托管事务拷贝菌结果
    	q ##Class(LIS.WS.DHCLISServiceBase).DeclarativeTrans("IDP.WS.BLL.DHCIDPResult","CopyOrgResDo",SourceResDR, PerResDR, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions)
    }
    
    /// 拷贝结果执行
    /// w ##Class(IDP.WS.BLL.DHCIDPResult).CopyOrgResMTHD(15,"","","","","","","","","","","","","","")
    /// SourceResDR:源报告结果主键
    /// PerResDR:目标报告结果主键
    ClassMethod CopyOrgResDo(SourceResDR, PerResDR, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions, Output RowCount As %String) As %String
    {
    	s SourceResDR=$g(SourceResDR)
    	s PerResDR=$g(PerResDR)
    	s PerReportDR=$lg($g(^dbo.RPVisitNumberReportResultD(PerResDR)),2)
    	s PerReportStatus=$lg($g(^dbo.RPVisitNumberReportD(PerReportDR)),22)
    	i PerReportStatus="30" s PerReportStatus="3"
    	i PerReportStatus="3" q "-1^目标报告已经审核,不允许粘贴结果!"
    	
    	s SourceRes=##Class(dbo.RPVisitNumberReportResult).%OpenId(SourceResDR)
    	s PerRes=##Class(dbo.RPVisitNumberReportResult).%OpenId(PerResDR)
    	//不拷贝的列,RowID默认不拷贝
    	s NoCopyList=$lb("VisitNumberReportDR","RPVisitNumberTestSetDR","TestCodeDR")
    	d ##Class(LIS.WS.DHCLISServiceBase).CopyTableRow(SourceRes,PerRes,NoCopyList)
    	s sc=PerRes.%Save()
    	i ('$SYSTEM.Status.IsOK(sc)) d
    	.THROW ##class(%Exception.SystemException).%New("事务委托","D",,"-1^更新报告结果失败:"_$SYSTEM.Status.GetErrorText(sc))
    	
    	//遍历拷贝药敏
    	s AntibioticsDR="" f  s AntibioticsDR=$o(^dbo.RPVisitNumberReportResSenI("IndexAntibiocs",SourceResDR,AntibioticsDR)) q:AntibioticsDR=""  d
    	.s SenDR="" f  s SenDR=$o(^dbo.RPVisitNumberReportResSenI("IndexAntibiocs",SourceResDR,AntibioticsDR,SenDR)) q:SenDR=""  d
    	..s PerSenDR=""
    	..i $d(^dbo.RPVisitNumberReportResSenI("IndexAntibiocs",PerResDR,AntibioticsDR)) d
    	...s PerSenDR=$o(^dbo.RPVisitNumberReportResSenI("IndexAntibiocs",PerResDR,AntibioticsDR,""))
    	..s SourceSen=##Class(dbo.RPVisitNumberReportResSen).%OpenId(SenDR)
    	..i '$l(PerSenDR) s NewSenObj=##Class(dbo.RPVisitNumberReportResSen).%New()
    	..e  s NewSenObj=##Class(dbo.RPVisitNumberReportResSen).%OpenId(PerSenDR)
    	..d ##Class(LIS.WS.DHCLISServiceBase).CopyTableRow(SourceSen,NewSenObj)
    	..s NewSenObj.VisitNumberReportResultDR=PerRes.RowID
    	..s sc=NewSenObj.%Save()
    	..i ('$SYSTEM.Status.IsOK(sc)) d
    	...THROW ##class(%Exception.SystemException).%New("事务委托","D",,"-1^更新药敏结果失败:"_$SYSTEM.Status.GetErrorText(sc))
    	
    	//遍历拷贝耐药机制
    	s ResistanceItemDR="" f  s ResistanceItemDR=$o(^dbo.RPVisitNumberRepResRstI("IndexDataMaster",SourceResDR,ResistanceItemDR)) q:ResistanceItemDR=""  d
    	.s RstDR="" f  s RstDR=$o(^dbo.RPVisitNumberRepResRstI("IndexDataMaster",SourceResDR,ResistanceItemDR,RstDR)) q:RstDR=""  d
    	..s PerRstDR=""
    	..i $d(^dbo.RPVisitNumberRepResRstI("IndexDataMaster",PerResDR,ResistanceItemDR)) d
    	...s PerRstDR=$o(^dbo.RPVisitNumberRepResRstI("IndexDataMaster",PerResDR,ResistanceItemDR,""))
    	..s SourceRst=##Class(dbo.RPVisitNumberRepResRst).%OpenId(RstDR)
    	..i '$l(PerRstDR) s NewRstObj=##Class(dbo.RPVisitNumberRepResRst).%New()
    	..e  s NewRstObj=##Class(dbo.RPVisitNumberRepResRst).%OpenId(PerRstDR)
    	..d ##Class(LIS.WS.DHCLISServiceBase).CopyTableRow(SourceRst,NewRstObj)
    	..s NewRstObj.VisitNumberReportResultDR=PerRes.RowID
    	..s sc=NewRstObj.%Save()
    	..i ('$SYSTEM.Status.IsOK(sc)) d
    	...THROW ##class(%Exception.SystemException).%New("事务委托","D",,"-1^更新耐药机制结果失败:"_$SYSTEM.Status.GetErrorText(sc))
    	q ""
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    借助%ConstructClone和自己封装的拷贝方法从而优雅的实现复制粘贴功能

  • 相关阅读:
    解决request.patch参数data传参问题
    LeetCode第622题—设计循环队列
    Rust模式匹配
    挑战30天学完Python:Day1火力全开-初识Python(含系列大纲)
    【linux命令讲解大全】006.网络工具简介:bzdiff 和 clockdiff 的用途和功能
    Go ZIP压缩文件读写操作
    85-Java阶段实战案例:模拟电影购票系统
    app在线客服系统怎么对接
    Ant-design-vue Table 列表 columns 将作为导出功能入参
    SpringBoot面试题2:SpringBoot与SpringCloud 区别?SpringBoot和Spring、SpringMVC的区别
  • 原文地址:https://blog.csdn.net/zhanglianzhu_91/article/details/126310836