【转】DICOM医学图像处理:DIMSE消息发送与接收“大同小异”之DCMTK fo-dicom mDCM

转自:https://my.oschina.net/zssure/blog/354816

背景:

        从DICOM网络传输一文开始,相继介绍了C-ECHO、C-FIND、C-STORE、C-MOVE等DIMSE-C服务的简单实现,博文中的代码给出的实例都是基于fo-dicom库来实现的,原因只有一个:基于C#的fo-dicom库具有高封装性。对于初学者来说实现大多数的DIMSE-C、DIMSE-N服务几乎都是“傻瓜式”操作——构造C-XXX-RQ、N-XXX-RQ然后绑定相应的OnResponseReceived处理函数即可。本博文希望在前几篇预热的基础上,对比DCMTK、fo-dicom、mDCM三种库构建DIMSE消息的具体操作,来分析一下三者对于DIMSE消息的发送和接收的实现,为后续搭建简易版的Dicom Server服务器做准备。

DIMSE:

        DIMSE,是DICOM Message Service Element的简称。DICOM3.0第7部分指出:DIMSE为对等DICOM应用实体进行医学影像及相关信息交换提供了一种应用服务元素定义(Application Service Element),包括服务和协议(DIMSE Service 和DIMSE Protocol)。

DIMSE Protocol:

        DIMSE基于DIMSE协议来提供服务,DIMSE协议规定了构造消息必需的编码规则。一条DICOM MESSAGE由固定的指令集合(Command Set),外加可选择的数据集合(Data Set)构成,如下截图所示:

 

 

        可以简单的理解为Command Set就是本博文即将要介绍的各种服务的请求和应答消息;而Data Set可以认为类似于DCM后缀的文件,是我们希望在对等DICOM实体间进行传输的信息。但是从本质上来说Command Set和Data Set两者都遵循DICOM3.0协议中IOD的定义都是“以(Group Number,Element Number)对”来进行标记的Data Element元素的集合,更形象一点的说明可参考早期的博文(http://blog.csdn.net/zssureqh/article/details/9275271)。

        DIMSE Protocol指出Message可能会分片(fragmented,这与传统的TCP/IP中的概念类似),消息的具体传输是基于ASSOCIATE(DICOM3.0第8部分)中的P-DATA Service(博文http://blog.csdn.net/zssureqh/article/details/41016091中有介绍)。

DIMSE Services:

        DIMSE服务因操作SOP类型的不同分为DIMSE-C ServicesDIMSE-N Services,DIMSE-C服务支持在对等DICOM实体间进行Composite SOP Instance操作,主要包括C-ECHO、C-FIND、C-STORE、C-MOVE、C-GET等;而DIMSE-N服务支持Normalized SOP Instance操作,主要包括N-EVENT-REPORT、N-GET、N-SET、N-CREATE、N-ACTION、N-DELETE。

 

 

        从上图可以看出DIMSE-C服务只提供操作服务,即对等DICOM实体一方请求另一方对Composite SOP Instance进行操作(operation);而DIMSE-N服务除了提供操作以外,还提供通知(notification)服务。DIMSE中的所有操作和通知都是确认服务(confirmed services),即一方发出的请求都需要得到对方的应答(原文:All DIMSE operations and notifications are confirmed services. The performing DIMSE-service-user shall report the response of each operation or notificationover the same Association on which the operation or notification was invoked.)。每种服务具体方式不同,例如某些操作可能会触发后续的子操作、某些操作可能需要多个响应等等,如下图:

 

 

DCMTK、fo-dicom、mDCM构建DIMSE-C消息:

        DIMSE-C服务在医学领域应用最广泛,常见的PACS、HIS、RIS、LIS等系统都会用到,而DIMSE-N服务主要应用在MPPS和DICOM打印中,日常学习中可能没有实际应用和测试的机会,因此这里就暂时不介绍,主要以DIMSE-C消息的构造为主,来分别介绍三种库的具体操作。

DCMTK:

        博文http://blog.csdn.net/zssureqh/article/details/41016091之前简单介绍了一下DCMTK对于网络传输方面的封装,更多的是偏重于协议的各层(Layer),例如对最底层的基于TCP/IP的Dicom Upper Layer的封装以DUL_为前缀;对实体连接层的封装以ASC_为前缀;最顶层的是DIMSE层,以DIMSE_为前缀。本博文会从DIMSE Services中的DIMSE-C各种消息入手,介绍DCMTK对于消息的封装和操作:

DCMTK之C-ECHO:

        DCMTK开源库相较于其他两者来说最大的优势是有完整的说明文档、稳定的维护团队,同时也有成功的商业产品。在源码中也给出了各种服务工具包,前面的好多博文都已经介绍过DCMTK的工具包,例如针对于C-ECHO的echoscu.exe(博文后续的工程实例是用dcmqrscp.exe作为mini DICOM服务端进行测试的)

DCMTK对DIMSE-C中的各种消息的定义在dimse.h头文件中,其中C-ECHO-RQ消息定义如下:

 

/* C-ECHO */
struct T_DIMSE_C_EchoRQ {
DIC_US MessageID; /* M */
DIC_UI AffectedSOPClassUID; /* M */
T_DIMSE_DataSetType DataSetType; /* M */
} ;
struct T_DIMSE_C_EchoRSP {
DIC_US MessageIDBeingRespondedTo; /* M */
DIC_UI AffectedSOPClassUID; /* U(=) */
T_DIMSE_DataSetType DataSetType; /* M */
DIC_US DimseStatus; /* M */
unsigned int opts; /* which optional items are set */
#define O_ECHO_AFFECTEDSOPCLASSUID 0x0001
} ;

 

 

        dimse.h中对于每一种DIMSE-C服务的请求消息(request)和响应消息(response)都给出了定义,并以union方式来统一了DICOM Message结构,如下所示:

 

/*
* Composite DIMSE Message
*/
struct T_DIMSE_Message {
T_DIMSE_Command CommandField; /* M */
union {
/* requests */
T_DIMSE_C_StoreRQ CStoreRQ;
T_DIMSE_C_EchoRQ CEchoRQ;
T_DIMSE_C_FindRQ CFindRQ;
T_DIMSE_C_GetRQ CGetRQ;
T_DIMSE_C_MoveRQ CMoveRQ;
T_DIMSE_C_CancelRQ CCancelRQ;
T_DIMSE_N_EventReportRQ NEventReportRQ;
T_DIMSE_N_GetRQ NGetRQ;
T_DIMSE_N_SetRQ NSetRQ;
T_DIMSE_N_ActionRQ NActionRQ;
T_DIMSE_N_CreateRQ NCreateRQ;
T_DIMSE_N_DeleteRQ NDeleteRQ;
/* responses */
T_DIMSE_C_StoreRSP CStoreRSP;
T_DIMSE_C_EchoRSP CEchoRSP;
T_DIMSE_C_FindRSP CFindRSP;
T_DIMSE_C_GetRSP CGetRSP;
T_DIMSE_C_MoveRSP CMoveRSP;
T_DIMSE_N_EventReportRSP NEventReportRSP;
T_DIMSE_N_GetRSP NGetRSP;
T_DIMSE_N_SetRSP NSetRSP;
T_DIMSE_N_ActionRSP NActionRSP;
T_DIMSE_N_CreateRSP NCreateRSP;
T_DIMSE_N_DeleteRSP NDeleteRSP;
} msg;
};

 

 

        DICOM3.0第7部分中有关于C-ECHO消息的参数说明以及具体指令编码,正如前文所述Command同样也是以(Group Number,Element Number)标记的Data Element元素的集合,因此按照DICOM3.0标准中的要求只要向C-ECHO-RQ或者C-ECHO-RSP指令中插入规定的Data Element元素即可。

 

 

        如上图所示,构造T_DIMSE_CEchoRQ需要填充MessageID/Affected SOP Class UID等,具体构造代码如下:(代码封装在DIMSE_echoUser函数中)

 

T_DIMSE_Message req, rsp;
T_ASC_PresentationContextID presID;
const char *sopClass = UID_VerificationSOPClass;
bzero((char*)&req, sizeof(req));
bzero((char*)&rsp, sizeof(rsp));
req.CommandField = DIMSE_C_ECHO_RQ;
req.msg.CEchoRQ.MessageID = msgId;
strcpy(req.msg.CEchoRQ.AffectedSOPClassUID,
sopClass);
req.msg.CEchoRQ.DataSetType = DIMSE_DATASET_NULL;

 

 

        上面代码中的rsp与我们自己构建的req类似,唯一不同的是req是在C-ECHO SCU端构造,而rsp是在C-ECHO SCP端构造并通过网络传送过来的。

      (具体的测试代码可参见博文后文给出的连接)

DCMTK之C-FIND:

        下面我们看一下比较复杂的消息C-FIND,相较于C-ECHO消息,C-FIND中需要给出我们希望查询的目标属性列表(记住:同样也是一个DcmDataset类型,即Dicom Element集合)。

 

 

        C-FIND-RQ消息的构造代码如下:

 

//定义临时变量
T_ASC_PresentationContextID presId;
T_DIMSE_C_FindRQ req;
T_DIMSE_C_FindRSP rsp;
DcmFileFormat dcmff;
OFString temp_str;
presId=ASC_findAcceptedPresentationContextID(assoc,abstractSyntax);
//构造C-FIND-RQ消息
bzero(OFreinterpret_cast(char*, &req), sizeof(req));
strcpy(req.AffectedSOPClassUID,abstractSyntax);
req.DataSetType=DIMSE_DATASET_PRESENT;
req.Priority=DIMSE_PRIORITY_LOW;
req.MessageID=assoc->nextMsgID++;
//构造数据体,即我们具体希望在C-FIND SCP端获得的信息
DcmDataset* dcmdataset=new DcmDataset();
dcmdataset->putAndInsertString(DCM_StudyInstanceUID,"");
dcmdataset->putAndInsertString(DCM_StudyDate,"");
dcmdataset->putAndInsertString(DCM_QueryRetrieveLevel,"STUDY");
DcmDataset *statusDetail = NULL;
//在DIMSE_findUser内部会将dcmdataset数据合并到req中,统一构成T_DIMSE_Message
OFCondition cond=DIMSE_findUser(assoc,presId,&req,dcmdataset,NULL,NULL,blockMode,dimse_timeout,&rsp,&statusDetail);

 

 

        上述代码比较复杂的是需要构造参数列表中的Identifier元素,该元素包含了我们希望从C-FIND SCP服务端提供查询获得的属性,上面选择了STUDY级别的查询,因此需要添加DCM_QueryRetrieveLevel元素、StudyInstanceUID等(DCM_QueryRetrieveLevel元素必须添加,有时候会误认为添加了AffectedSOPClassUID后就不需要了,这是错误的。否则服务端会返回如下错误,如下图)。

 

 

        注:关于Patient、Study、Series等不同级别的查询的详细介绍可参考DICOM3.0标准第4部分的附录C。

DCMTK之C-STORE:

        C-STORE与C-FIND类似,同样需要添加额外的数据,不同于C-FIND添加查询属性列表的是,C-STORE添加的是准备发送的DCM文件的数据体,即下图中的Data Set。

 

OFCondition cond = EC_Normal;
T_DIMSE_Message req, rsp;
DcmDataset 
bzero((char*)&req, sizeof(req));
bzero((char*)&rsp, sizeof(rsp));
/* set corresponding values in the request message variable */
req.CommandField = DIMSE_C_STORE_RQ;
request->DataSetType = DIMSE_DATASET_PRESENT;
request->req.msg.CStoreRQ = *request;

 

 

        暂时我们就只介绍C-ECHO、C-FIND和C-STORE三种服务的请求消息构造方法,其他的类似。

fo-dicom:

        fo-dicom是基于C#开发的,封装性更强,封装思路更倾向于按DICOM消息流来进行,即fo-dicom库开发者在实现了整个DIMSE消息流框架的基础上,通过给用户预留各阶段的接口来方便用户定制自己的实现。对于DIMSE消息流框架的封装在DicomService.cs文件中(同时也有类似于DCMTK中的ASC_方面的封装,主要指的是A-ASSOCIATE服务及协议,在DICOM3.0第8部分有详细介绍),对于网络底层的封装放在DicomServer.cs文件中(等同于DCMTK中的DUL_层)。

        DICOM Message消息的基类在DicomMessage.cs文件中,然后根据请求和应答派生了两个基类DicomRequest和DicomResponse。从fo-dicom库的封装以及fo-dicom对于Dataset的设计可以看出Command和Dataset都是数据集合,不同的是两者存储的元素类型不同。

        在fo-dicom库中构造各类消息很方便,可谓是“傻瓜式”操作,详情如下:

fo-dicom之C-ECHO:

 

DicomCEchoRequest cechoRQ=new DicomCEchoRequest();

 

 

        一行代码就顺利的构建了一个C-ECHO-RQ请求指令。分析源码可知DicomCEchoRequest继承自DicomRequest,DicomReqeust继承自DicomMessage。逐级查看各类的构造函数可以发现。虽然我们调用的是DicomCEchoRequest的默认构造函数,但是在相继调用了基类DicomRequest(DicomCommandField.CEchoRequest, DicomUID.Verification, priority)和DicomMessage()后,顺利的完成了对C-ECHO-RQ指令中各个参数构造,其中DicomMessage中构造了空的Command Set和DataSet,DicomRequest中对MessageID、Priority、SOPClassUID以及CommandFieldType进行了赋值,这简直是太容易啦,不过也正因为此,刚入手的时候可能不知道如何来定制化自己的请求,以为fo-dicom库留给我们的可操作性太少,其实不然,继续往下看。

fo-dicom之C-FIND:

 

DicomCFindRequest cfind=DicomCFindRequest.CreateStudyQuery(patientId:”12345”);
cfind.OnResponseReceived=(rq,rsp)=>
{
//接收到C-FIND-RSP响应消息后,本机C-FIND SCU进行的操作
//例如可以输出到屏幕或其他窗口
Console.WriteLine("PatientAge:{0} PatientName:{1}", rsp.Dataset.Get<string>(DicomTag.PatientAge), rsp.Dataset.Get<string>(DicomTag.PatientName));
}

 

 

        通过对比fo-dicom与DCMTK中C-FIND的构造,是不是觉得很容易。但是越容易学习和上手的东西,倘若不掌握其本质越容易忘。查看DicomCFindRequest.cs源码,可以发现CreateStudyQuery函数已经帮助我们添加了Study查询级别所需的所有字段,也就是上文中提到的Identifier参数部分。代码如下:

 

        那么如果我们想像DCMTK那样自由添加字段怎么办?例如在已知服务端是自己定制实现的基础上来查询我们的私有字段。很简单直接覆盖一下CreateStudyQuery函数即可。另外fo-dicom还有一个比价便利的地方是将每种消息的回调函数直接绑定到消息中,程序写起来比较方便,逻辑上更清晰。

fo-dicom之C-STORE:

 

DicomCStoreRequest cstore=new DicomCStoreRequest(@”c:\\test4.dcm”);

 

 

        在DicomCStoreRequest一级只需要数据要发送的dcm文件名(全路径名),同样通过逐级来完成CommandSet和Dataset的赋值。基本流程如下:

 

/// <summary>/// Initializes DICOM C-Store request to be sent to SCP./// </summary>/// <param name="file">DICOM file to be sent</param>/// <param name="priority">Priority of request</param>public DicomCStoreRequest(DicomFile file, DicomPriority priority = DicomPriority.Medium) : base(DicomCommandField.CStoreRequest, file.Dataset.Get<DicomUID>(DicomTag.SOPClassUID), priority) {File = file;Dataset = file.Dataset;SOPInstanceUID = File.Dataset.Get<DicomUID>(DicomTag.SOPInstanceUID);}
<span style="white-space:pre">		</span>//DicomRequest.cs文件protected DicomRequest(DicomCommandField type, DicomUID affectedClassUid, DicomPriority priority) : base() {Type = type;SOPClassUID = affectedClassUid;MessageID = GetNextMessageID();Priority = priority;Dataset = null;}
<span style="white-space:pre">		</span>//DicomMessage.cs文件public DicomMessage() {Command = new DicomDataset();Dataset = null;}

 

mDCM:

        mDCM库与fo-dicom库其实是相同的,只不过fo-dicom利用了最新的C#技术来重构mDCM。如博文http://blog.csdn.net/zssureqh/article/details/39621533中给出的mDCM库的继承图所示,在顶层基类DcmNetworkBase中实现了DIMSE消息流的基本框架,然后按照Client和Server进行了两路派生。mDCM的封装有点处于DCMTK和fo-dicom之间的状况,既未做到像DCMTK那样完全提供各个层面底层操作函数,也没有像fo-dicom那样更抽象的封装

        下面来看一下mDCM对各种消息的构造:

mDCM之C-ECHO:

 

//DcmAssociation assoction;//已经顺利建立的DICOM对等实体间的连接
byte pcid=associate.FindAbstractSyntax(DicomUID.VerificationSOPClass;
SenCEchoRequest(pcid,NextMessageID(),Priority);

 

        mDCM比较特殊,对于DIMSE-C服务请求的参数赋值流程与fo-dicom类似,大多参数赋值都在基类中完成,例如DcmClientBase中完成了MaxPDU、Priority,DicomClient完成CallingAE和CalledAE等;而对于整体请求消息的拼接却又类似DCMTK,在SendCEchoRequest函数内部调用CreateRequest来完成。

mDCM之C-FIND:

 

byte pcid = Associate.FindAbstractSyntax(FindSopClassUID);
if (Associate.GetPresentationContextResult(pcid) == DcmPresContextResult.Accept) {
DcmDataset dataset = query.ToDataset(Associate.GetAcceptedTransferSyntax(pcid));
SendCFindRequest(pcid, NextMessageID(), Priority, dataset);

 

        在query.ToDataset函数内部完成了查询级别QueryRetrieveLevel的赋值,另外需要注意的是此时在ToDataset函数内部调用了一个虚函数AdditonalMembers用于方便派生添加自已要查询的Identifier元素。最终还是在SendCFindRequest函数内部利用CreateRequest创建C-FIND-RQ消息(在mDCM中的类型是DcmCommand)。

mDCM之C-STORE:

 

internal void SendCStoreRequest(byte pcid, DicomUID instUid, Stream stream) {SendCStoreRequest(pcid, NextMessageID(), instUid, Priority, stream);}internal void SendCStoreRequest(byte pcid, DicomUID instUid, DcmDataset dataset) {SendCStoreRequest(pcid, NextMessageID(), instUid, Priority, dataset);}

 

        在CStoreClient类内部通过Load来载入dcm文件,提取DcmDataset数据体,然后调用SendCStoreRequest来发送C-STORE-RQ请求(DicomCStoreClient中有两种类型的SendCStoreRequest,一种是发送DcmDataset类型数据,一种是发送Stream类型数据)。

总结:

        通过对比分析三种开源库对DIMSE-C服务消息的构造方式,可以更清晰的了解DCMTK、fo-dicom、mDCM三者各自的优势。如果想了解DICOM协议的细节及底部代码的具体实现,自然DCMTK是首选,其按照Dicom Upper Layer、A-ASSOCIATE、DIMSE三层来划分的结构更方便我们研究DICOM网络传输的机制。并且DCMTK最新的3.6.1版本也逐渐开始按服务来对DUL_、ASC_、DIMSE_三类函数进行封装,已经实现了C-ECHO、C-STORE服务,即DcmSCU/DcmSCP和DcmStorageSCU/DcmStorageSCP。如果想快速入手,实现DICOM的相关服务,fo-dicom自然是首选,想必这对于C#程序员来说轻而易举(mDCM可以看做是DCMTK与fo-dicom的中间地带)。

DCMTK工程实例:

百度网盘:http://pan.baidu.com/s/1jGvaSr8

后续博文介绍:

fo-dicom搭建简单的DICOM Server

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436166.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

公司间交易学习笔记---概述

本系列笔记是我在学习公司间交易的过程中的随笔&#xff0c;有些是我自己的想法&#xff0c;内容可能跟教程有所出入&#xff0c;由于对AX的应用部分理解得很浅&#xff0c;所以如果错误还请多多指教。 为了处理集团公司中各个分公司之间的交易&#xff0c;AX采用了InterCompan…

用VS2005开发WinCE程序调试图文教程

一、WinCE 模拟器通过ActiveSync 6.1(即Windows Mobile设备中心)连接PC ActiveSync 6.1&#xff1a;http://www.cr173.com/soft/26994.html 1.启动WinCE模拟器 命令行&#xff1a; start .\DeviceEmulator.exe WINCE镜像\Wince5.bin /memsize 256 /video 480x272x16 /sharedf…

【转】 ADO.NET最佳实践

本文转自&#xff1a;http://blog.csdn.net/spidertan/archive/2003/12/13/17110.aspx 概述&#xff1a; 本文在微软站点资源的基础上加工整理而成&#xff0c;意在介绍在你的ADO.NET应用程序中执行和完成性能优化、稳定性和功能性方面提供最佳的解决方案&#xff1b;同…

php 变量文件间传递,同一文件的两个JS函数之间如何传变量?

满意答案ed_ch2013.11.06采纳率&#xff1a;44% 等级&#xff1a;12已帮助&#xff1a;8801人定义成全局变量就可以了var style_key;function change_mystyle(my){style_keymy.options[my.selectedIndex].value;if(style_key 114la){document.getElementById(shoostyleicon…

获取 Web 设计的免费资源

Web 开发人员可以找到很多免费资源&#xff0c;尽管其中一些资源会比另外一些资源更加自由。如果您正在设计网站或 Web 应用程序&#xff0c;那么不管是静态的还是所有可以想到的动态 Ajax 内容&#xff0c;都能找到减轻您的劳动强度并为网站增色的资源。本文从免费图标到 Web …

设计模式C++实现(1)——工厂模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性&#xff1a;封装、继承、多态&#xff0c;真正领悟设计模式的精髓是可能一个漫长的过程&#xff0c;需要大量实践经验的积累。最近看设计模式的书&#xff0…

java对象间的转型,详细讲述Java中的对象转型

向上转型&#xff1a;子类对象转为父类&#xff0c;父类可以是接口。公式&#xff1a;Father f new Son();Father是父类或接口&#xff0c;son是子类。向下转型&#xff1a;父类对象转为子类。公式&#xff1a;Son s (Son)f;我们将形参设为父类Animal类型&#xff0c;当执行t…

C++设计模式之一 工厂模式(简单工厂、工厂和抽象工厂)

今天开始这个系列之前&#xff0c;心里有些恐慌&#xff0c;毕竟园子里的高手关于设计模式的经典文章很多很多&#xff0c;特别是大侠李会军、吕震宇 老师的文章更是堪称经典。他们的文笔如行云流水&#xff0c;例子活泼生动&#xff0c;讲解深入浅出。好在他们都是用C#描述&am…

【转】Windows消息传递机制详解

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka Windows是一个消息&#xff08;Message&#xff09;驱动系统。Windows的消息提供了应用程序之间、应用程序与Windows系统之间进行通信的手段。应用程序想要实现的功能由消息来触发&#xff0c;并且靠对消…

设计模式C++实现(2)——单例模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性&#xff1a;封装、继承、多态&#xff0c;真正领悟设计模式的精髓是可能一个漫长的过程&#xff0c;需要大量实践经验的积累。最近看设计模式的书&#xff0…

设计模式C++实现(3)——建造者模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性&#xff1a;封装、继承、多态&#xff0c;真正领悟设计模式的精髓是可能一个漫长的过程&#xff0c;需要大量实践经验的积累。最近看设计模式的书&#xff0…

宽字符串忽略大小写比较的实现(原)

宽字符串忽略大小写比较的实现(原) 孙文涛 2008-07-24 在Mac机器平台上没有wcsicmp 或 wcscasecmp之类的函数实现对宽字符忽略大小写的比较&#xff0c;所以实现了好几种方法。 一个自然的思路是: (1) wcscpy 原字符串到tmp字符串; (2) tolower tmp字符串; (3) 然后调用仅存的w…

有关JAVA考试中数据库的题,javaee期末考试题库,用javaEE编写一个题库系统,要怎么做...

javaEE数据库简单问题。你插入2113数据库的时候是把5261它封装为一4102个对象插入的吗&#xff1f;1653如果封装为一个User对象版的权话(User对象有ID和LEVEL两个属性)ResultSet rs ps.executeQuery();User user new User();if(rs.hasNext()){user rs.next();}关于javaee 中j…

oracle 12c sql图形化,Oracle 12c PL/SQL程序设计终极指南

Oracle 12c PL/SQL程序设计终极指南作者&#xff1a;孙风栋;王澜;郭晓惠出版日期&#xff1a;2015年06月文件大小&#xff1a;11.73M支持设备&#xff1a;&#xffe5;60.00在线试读适用客户端&#xff1a;言商书局iPad/iPhone客户端&#xff1a;下载 Android客户端&#xff1a…

oracle 存储同步,Oracle数据库知识——存储过程篇

在线QQ客服&#xff1a;1922638专业的SQL Server、MySQL数据库同步软件存储过程是一组用于完成特定功能的SQL语句&#xff0c;该语句已编译并存储在数据库中。用户通过指定存储过程的名称并提供参数(如果存储过程具有参数)来执行它。存储过程是数据库中的重要对象。任何设计良好…

使用MvcContrib的FormHelper

MvcContrib的FormHelper提供了三大Helper Html辅助 验证HelperGrid表格Helper下载 下载后将MvcContrib.dll与MvcContrib.Samples.FormHelper.dll引用到Asp.net MVC工程 在Web.Config pages.namespaces加入以下节点 <add namespace"MvcContrib.UI.Tags"/><ad…

WinCE控制面板添加应用程序

WinCE系统中的控制面板和Windows系统中的控制面板原理是一样的&#xff0c;里面就是包含了一些应用程序。WinCE系统的控制面板由Ctlpnl.exe&#xff0c;Control.exe和一些.cpl文件组成&#xff0c;其中Ctlpnl.exe和Control.exe用于控制控制面板的文件夹显示和架构&#xff0c;而…

oracle 游标 904,如何解决Oracle数据库游标连接超出问题

如何解决Oracle数据库游标连接超出问题发布时间&#xff1a;2020-07-21 10:57:35来源&#xff1a;亿速云阅读&#xff1a;103作者&#xff1a;小猪这篇文章主要讲解了如何解决Oracle数据库游标连接超出问题&#xff0c;内容清晰明了&#xff0c;对此有兴趣的小伙伴可以学习一下…

用多媒体库 Bass.dll 播放 mp3 [15] - 设置与获取播放速度

本例效果图:代码文件:unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ComCtrls;typeTForm1 class(TForm)OpenDialog1: TOpenDialog;Button1: TButton;Button2: TButton;Button3: TButton;TrackBar1:…

【转】Dicom文件解析!!!!!!

转自&#xff1a;https://blog.csdn.net/leaf6094189/article/details/8510325 Dicom全称是医学数字图像与通讯&#xff0c;这里讲的暂不涉及通讯那方面的问题 只讲*.dcm 也就是diocm格式文件的读取&#xff0c;读取本身是没啥难度的 无非就是字节码数据流处理。只不过确实比较…