要想富,先修路。要想业务代码简单,先写方便的底层方法。之前写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("测试 Test 1 1 ")
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 测试 Test 999 1 ")
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("1 0 RemoteCacheActiveTestMTHD 0 1 ^^^^^^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}{2}>", key, value.ToString().Replace("&", "&").Replace("'", "'").Replace("\"", """).Replace(">", ">").Replace("<", "<"), key);
retStr += oneProStr;
}
//构造返回串返回
retStr = "<"+tableName +"> " + retStr + ""+ tableName +">";
return retStr;
}
此分享面向使用M语言的人