M通用增删改表

要想富,先修路。要想业务代码简单,先写方便的底层方法。之前写M对象保存数据写吐了,都是些毫无含量的体力劳动。

例如下面(都是取参数-往对象赋值保存):

/// XXXX
/// 表字段
/// 
/// d ##Class(XX.ZZ).SaveQCPatVisEvalResultMTHD(166)
ClassMethod SaveQCPatVisEvalResultMTHD(RowID, QCResultDR, TestCodeDR, VisNumber, OldResult, NewResult, Deviation, PatVisEval, EvalConclusion, P9, P10, P11, P12, P13, Sessions, Output RowCount As %String) As %String
{
     
	s RowID=$g(RowID)
	s QCResultDR=$g(QCResultDR)
	s TestCodeDR=$g(TestCodeDR)
	s VisNumber=$g(VisNumber)
	s OldResult=$g(OldResult)
	s NewResult=$g(NewResult)
	s Deviation=$g(Deviation)
	s PatVisEval=$g(PatVisEval)
	s EvalConclusion=$g(EvalConclusion)
	s MaterialDR=""
	s TestDate=""
	i $d(^dbo.QCTestResultD(QCResultDR)) d
	.s MaterialLotDR=$lg($g(^dbo.QCTestResultD(QCResultDR)),2)
	.s TestDate=$lg($g(^dbo.QCTestResultD(QCResultDR)),5)
	.s MaterialDR=$lg($g(^dbo.BTQCMaterialLotD(MaterialLotDR)),3)
	s Sessions=$g(Sessions)
	s RowCount=$g(RowCount)
	s UserDR=$p(Sessions,"^",1)
	s SaveObj=""
	i RowID'="-1" d
	.s SaveObj=##Class(dbo.QCPatVisEvalResult).%OpenId(RowID)
	e  d
	.s SaveObj=##Class(dbo.QCPatVisEvalResult).%New()
	.s SaveObj.AddDate=$zd($h,8)
	.s SaveObj.AddTime=$p($h,",",2)
	.s SaveObj.EvlDate=TestDate
	.s SaveObj.EvlTime=$p($h,",",2)
	.s SaveObj.AddUserDR=UserDR
	s SaveObj.MaterialDR=MaterialDR
	s SaveObj.TestCodeDR=TestCodeDR
	s SaveObj.VisNumber=VisNumber
	s SaveObj.OldResult=OldResult
	s SaveObj.NewResult=NewResult
	s SaveObj.Deviation=Deviation
	s SaveObj.PatVisEval=PatVisEval
	s SaveObj.EvalConclusion=EvalConclusion
	s sc=SaveObj.%Save()
	i ('$SYSTEM.Status.IsOK(sc)) d
	.THROW ##class(%Exception.SystemException).%New("事务委托","D",,"-1^保存数据失败:"_$SYSTEM.Status.GetErrorText(sc))
	q ""
}

/// XXXXX
/// 表字段
/// 
/// d ##Class(XX.ZZ).SaveQCPatVisEvalResultMTHD(166)
ClassMethod DeleteQCPatVisEvalResultMTHD(RowID, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions, Output RowCount As %String) As %String
{
     
	s RowID=$g(RowID)
	s Sessions=$g(Sessions)
	s RowCount=$g(RowCount)
	s UserDR=$p(Sessions,"^",1)
	s ret=##Class(dbo.QCPatVisEvalResult).%DeleteId(RowID)
	i ret'=1 d
	.THROW ##class(%Exception.SystemException).%New("事务委托","D",,"-1^删除数据失败")
	q ""
}

为了避免这块体力劳动,包装基于xml的增、删。改方法

/// 按约定xml操作类表的增、改、删数据
Class ZZ.OperTable Extends %RegisteredObject
{
     

/// 插入数据到表中
/// SaveXml:格式如下
/// 
/// 		测试
/// 		Test
/// 		1
/// 		1
/// 
/// w ##class(ZZ.OperTable).InsertMTHD("测试Test11")
ClassMethod InsertMTHD(SaveXml As %String(MAXLEN=99999999), P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions, Output RowCount As %String) As %String
{
     
	s SaveXml=$g(SaveXml)
	s retVal=""
	s globleNode=""
	SET $ZTRAP="ErrHandler"
	s globleNode=..XmlToGlobleNode(SaveXml)
	s tableName=$o(^TMPXmlGloble(globleNode,""))
	s rset = ##class(%ResultSet).%New()
	d rset.Prepare("select COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='dbo' AND TABLE_NAME='"_$REPLACE(tableName,"dbo.","")_"'")
	s exeret=rset.Execute()
	s colCount=rset.GetColumnCount()
	s dealNum=0
	s PropertyMap=""
    While(rset.Next())
    {
     
	    s colField=rset.GetColumnName(1)
        s ColValue=rset.GetDataByName(colField)
        s PropertyMap(ColValue)=""
    }
    s tableClsName=$tr(tableName,"_")
	s objsave=""
	s ProValList=""
	s ProValIndex=0
	s exestr="(objsave) s objsave=##class("_tableClsName_").%New()"
	x (exestr,.objsave)
	i objsave'="" d
	.s OneProperty="" f  s OneProperty=$o(^TMPXmlGloble(globleNode,tableName,1,OneProperty)) q:OneProperty=""  d
	..i $d(^TMPXmlGloble(globleNode,tableName,1,OneProperty,1)) d
	...s OnePropertyVal=$g(^TMPXmlGloble(globleNode,tableName,1,OneProperty,1))
	...//不存在的属性不保存
	...i '$d(PropertyMap(OneProperty)) q
	...s ProValIndex=ProValIndex+1
	...i ProValIndex=1 s ProValList=$lb(OnePropertyVal)
	...e  s ProValList=ProValList_$lb(OnePropertyVal)
	...s exestr="(objsave,ProValList) s objsave."_OneProperty_"=$lg(ProValList,"_ProValIndex_")"
	...x (exestr,.objsave,ProValList)
	.//删除xml节点
	.k ^TMPXmlGloble(globleNode)
	.s exestr="(objsave,sc) s sc=objsave.%Save()"
	.x (exestr,.objsave,.sc)
	.i ('$SYSTEM.Status.IsOK(sc)) d
	..s retVal= "-1^保存"_tableClsName_"失败:"_$SYSTEM.Status.GetErrorText(sc)
	.e  d
	..s retVal=objsave.RowID
	e  d
	.k ^TMPXmlGloble(globleNode)
	q retVal
	
ErrHandler
	i $l(globleNode) k ^TMPXmlGloble(globleNode)
	s retVal= "-1^"_$ZERROR
    q retVal
}

/// 更新数据到表中
/// SaveXml:格式如下,更新必须带RowID
/// 
///         1
/// 		测试
/// 		Test
/// 		1
/// 		1
/// 
/// w ##class(ZZ.OperTable).UpdateMTHD("1测试Test9991")
ClassMethod UpdateMTHD(SaveXml As %String(MAXLEN=99999999), P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions, Output RowCount As %String) As %String
{
     
	s SaveXml=$g(SaveXml)
	s retVal="1"
	s globleNode=""
	SET $ZTRAP="ErrHandler"
	s globleNode=..XmlToGlobleNode(SaveXml)
	s tableName=$o(^TMPXmlGloble(globleNode,""))
	s rset = ##class(%ResultSet).%New()
	d rset.Prepare("select COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='dbo' AND TABLE_NAME='"_$REPLACE(tableName,"dbo.","")_"'")
	s exeret=rset.Execute()
	s colCount=rset.GetColumnCount()
	s dealNum=0
	s PropertyMap=""
    While(rset.Next())
    {
     
	    s colField=rset.GetColumnName(1)
        s ColValue=rset.GetDataByName(colField)
        s PropertyMap(ColValue)=""
    }
    s tableClsName=$tr(tableName,"_")
    s RowID=..GetXmlValByPath(SaveXml,"/"_tableName_"/RowID")
	s objsave=""
	s ProValList=""
	s ProValIndex=0
	s exestr="(objsave) s objsave=##class("_tableClsName_").%OpenId("_RowID_")"
	x (exestr,.objsave)
	i objsave'="" d
	.s OneProperty="" f  s OneProperty=$o(^TMPXmlGloble(globleNode,tableName,1,OneProperty)) q:OneProperty=""  d
	..i $d(^TMPXmlGloble(globleNode,tableName,1,OneProperty,1)) d
	...s OnePropertyVal=$g(^TMPXmlGloble(globleNode,tableName,1,OneProperty,1))
	...//不存在的属性不保存
	...i '$d(PropertyMap(OneProperty)) q
	...i OneProperty="RowID" q
	...s ProValIndex=ProValIndex+1
	...i ProValIndex=1 s ProValList=$lb(OnePropertyVal)
	...e  s ProValList=ProValList_$lb(OnePropertyVal)
	...s exestr="(objsave,ProValList) s objsave."_OneProperty_"=$lg(ProValList,"_ProValIndex_")"
	...x (exestr,.objsave,ProValList)
	.//删除xml节点
	.k ^TMPXmlGloble(globleNode)
	.s exestr="(objsave,sc) s sc=objsave.%Save()"
	.x (exestr,.objsave,.sc)
	.i ('$SYSTEM.Status.IsOK(sc)) d
	..s retVal= "-1^保存"_tableClsName_"失败:"_$SYSTEM.Status.GetErrorText(sc)
	e  d
	.k ^TMPXmlGloble(globleNode)
	q retVal
	
ErrHandler
	i $l(globleNode) k ^TMPXmlGloble(globleNode)
	s retVal= "-1^"_$ZERROR
    q retVal
}

/// 删除指定数据
/// SaveXml:格式如下,更新必须带RowID
/// 
///         1
/// 
/// w ##class(ZZ.OperTable).DeleteMTHD("1")
ClassMethod DeleteMTHD(SaveXml As %String(MAXLEN=99999999), P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions, Output RowCount As %String) As %String
{
     
	s SaveXml=$g(SaveXml)
	s retVal="1"
	s globleNode=""
	SET $ZTRAP="ErrHandler"
	s globleNode=..XmlToGlobleNode(SaveXml)
	s tableName=$o(^TMPXmlGloble(globleNode,""))
    s tableClsName=$tr(tableName,"_")
    s RowID=..GetXmlValByPath(SaveXml,"/"_tableName_"/RowID")
	s sc=""
	s exestr="(sc) s sc=##class("_tableClsName_").%DeleteId("_RowID_")"
	x (exestr,.sc)
	//删除xml节点
	k ^TMPXmlGloble(globleNode)
	i ('$SYSTEM.Status.IsOK(sc)) d
	.s retVal= "-1^删除"_tableClsName_"失败:"_$SYSTEM.Status.GetErrorText(sc)
	q retVal
	
ErrHandler
	i $l(globleNode) k ^TMPXmlGloble(globleNode)
	s retVal= "-1^"_$ZERROR
    q retVal
}

/// 通过xpath得到xml节点值
/// w ##class(ZZ.OperTable).GetXmlValByPath("10RemoteCacheActiveTestMTHD01^^^^^^JSON","")
/// xml:xml串
/// xpath:不传就默认为检验csp返回格式的xpath,否则传入/Response/RemoteCacheActiveTestMTHD格式层级路径
ClassMethod GetXmlValByPath(xml, xpath)
{
     
	s xml=$g(xml)
	s xpath=$g(xpath)
	set sc = ##class(%XML.TextReader).ParseStream(xml, .reader)
	Set repid=$I(^CacheTemp)
	s ret=""
	k ^TMP($zn,repid,$j)
	while (reader.Read()) {
     
		set Type = reader.NodeType
		set Path = reader.Path
		set Value = reader.Value
		i Type="chars" d
		.s ^TMP($zn,repid,$j,Path)=Value
	}
	i '$l(xpath) d
	.s nodenamePath="/Response/Node"
	.s resNodeName=$g(^TMP($zn,repid,$j,nodenamePath))
	.s xpath="/Response/"_resNodeName_"Result"
	i $l(xpath) s ret=$g(^TMP($zn,repid,$j,xpath))
	k ^TMP($zn,repid,$j)
	q ret
}

/// 通过xpath得到xml节点值,globle在^TMPXmlGloble("返回主节点"上,业务记得用完k掉
/// w ##class(ZZ.OperTable).XmlToGlobleNode("")
/// xml:xml串
/// xpath:不传就默认为检验csp返回格式的xpath,否则传入/Response/RemoteCacheActiveTestMTHD格式层级路径
ClassMethod XmlToGlobleNode(xml)
{
     
	s xml=$g(xml)
	set sc = ##class(%XML.TextReader).ParseStream(xml, .reader)
	Set repid=$I(^CacheTemp)
	s ret=""
	s MainNode=$zn_"-"_repid_"-"_$j
	k ^TMPXmlGloble(MainNode)
	s PathNum=""
	while (reader.Read()) {
     
		set Type = reader.NodeType
		set Path = reader.Path
		set Value = reader.Value
		i Type="element" d
		.i '$d(PathNum(Path)) s PathNum(Path)=0
		.s PathNum(Path)=PathNum(Path)+1
		i Type="chars" d
		.s NodeStr=""
		.s AddPath=""
		.f i=1:1:$l(Path,"/") d
		..s pNode=$p(Path,"/",i)
		..i '$l(pNode) q
		..s AddPath=AddPath_"/"_pNode
		..s AddNum=$g(PathNum(AddPath))
		..i '$l(AddNum) s AddNum="1"
		..s NodeStr=NodeStr_","""_pNode_""","""_AddNum_""""
		.s (@("^TMPXmlGloble("""_MainNode_""""_NodeStr_")"))=Value
	}
	q MainNode
}

}


再把这增、删、改M和C#或者js对接一下就能达到js直接以ajax提交表列名和值的方式增删改数据。js的话太方便了就得考虑安全性了,用C#对接也能简化调写这部分后台的事情。

类似下面:

		/// 
        /// 插入数据到表里
        /// 
        /// 表名字,带下划线的
        /// 属性名字和值
        /// 会话串
        /// 错误信息
        /// 
        public static string Insert(string tableName,Hashtable proVals,string session,out string err)
        {
     
            Parameters para = new Parameters();
            para.P0 = MakeSaveXml(tableName, proVals);
            int retVal = 0;
            string ret=GetCacheDataJSON("ZZ.OperTable", "InsertMTHD", para,session,false,out retVal,out err);
            return ret;
        }

        /// 
        /// 更新数据到表里
        /// 
        /// 表名字,带下划线的
        /// 属性名字和值,必须有RowID的值
        /// 会话串
        /// 错误信息
        /// 
        public static string Update(string tableName, Hashtable proVals, string session, out string err)
        {
     
            Parameters para = new Parameters();
            para.P0 = MakeSaveXml(tableName, proVals);
            int retVal = 0;
            string ret = GetCacheDataJSON("ZZ.OperTable", "UpdateMTHD", para, session, false, out retVal, out err);
            return ret;
        }

        /// 
        /// 删除一个数据
        /// 
        /// 表名字,带下划线的
        /// 属性名字和值,必须有RowID的值
        /// 会话串
        /// 错误信息
        /// 
        public static string Delete(string tableName, Hashtable proVals, string session, out string err)
        {
     
            Parameters para = new Parameters();
            para.P0 = MakeSaveXml(tableName, proVals);
            int retVal = 0;
            string ret = GetCacheDataJSON("ZZ.OperTable", "DeleteMTHD", para, session, false, out retVal, out err);
            return ret;
        }

        /// 
        /// 组装保存xml串
        /// 
        /// 表名
        /// 属性哈希
        /// 
        private static string MakeSaveXml(string tableName, Hashtable proVals)
        {
     
            string retStr = "";
            //遍历属性,构造串
            foreach (string key in proVals.Keys)
            {
     
                //得到属性值
                object value = proVals[key];
                if(value==null)
                {
     
                    value = "";
                }
                string oneProStr = String.Format("<{0}>{1}", key, value.ToString().Replace("&", "&").Replace("'", "'").Replace("\"", """).Replace(">", ">").Replace("<", "<"), key);
                retStr += oneProStr;
            }
            //构造返回串返回
            retStr = "<"+tableName +"> " + retStr + "+ tableName +">";
            return retStr;
        }

此分享面向使用M语言的人

你可能感兴趣的:(Caché,数据库开发)