zfbj 发表于 2005-8-2 23:34:00

[讨论]这两种方法创建实体有什么不同?

<P>在.net开发ObjectARX程序时,可以使用两种方法来创建一个实体。可以手工操作块表、块表记录,将实体添加到模型空间的块表记录中,完成实体的创建:<BR><BR>&nbsp;&nbsp;static public void ZffCreateEnt() // This method can have any name<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp; Point3d ptStart = new Point3d(0, 0, 0);<BR>&nbsp;&nbsp; Point3d ptEnd = new Point3d(100, 100, 0);<BR>&nbsp;&nbsp; Line line = new Line(ptStart, ptEnd);</P>
<P>&nbsp;&nbsp; ObjectId btId = HostApplicationServices.WorkingDatabase.BlockTableId;<BR>&nbsp;&nbsp; BlockTable blkTbl = (BlockTable)btId.Open(OpenMode.ForRead);</P>
<P>&nbsp;&nbsp; ObjectId btrId = blkTbl;<BR>&nbsp;&nbsp; BlockTableRecord blkTblRcd = (BlockTableRecord)btrId.Open(OpenMode.ForWrite);<BR>&nbsp;&nbsp; blkTbl.Close();</P>
<P>&nbsp;&nbsp; ObjectId lineId = blkTblRcd.AppendEntity(line);<BR>&nbsp;&nbsp; blkTblRcd.Close();<BR>&nbsp;&nbsp; line.Close();<BR>&nbsp;&nbsp;}</P>
<P>Autodesk建议的方式是通过事物来辅助完成实体的创建:<BR><BR>&nbsp;&nbsp;static public void ZffCreateLine()<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp; Point3d startPoint = new Point3d(4.0, 2.0, 0.0);<BR>&nbsp;&nbsp; Point3d endPoint = new Point3d(10.0, 7.0, 0.0);<BR>&nbsp;&nbsp; Line line = new Line(startPoint,endPoint);<BR>&nbsp;&nbsp; ObjectId lineId;<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; // 获得当前活动图形文档的图形数据库<BR>&nbsp;&nbsp; Database db=Application.DocumentManager.MdiActiveDocument.Database;<BR>&nbsp;&nbsp; // 获得事务管理器<BR>&nbsp;&nbsp; DBTransMan tm=db.TransactionManager;<BR>&nbsp;&nbsp; // 开始记录事物<BR>&nbsp;&nbsp; using(Transaction trans=tm.StartTransaction())<BR>&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;BlockTable bt=(BlockTable)tm.GetObject(db.BlockTableId,OpenMode.ForRead);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;BlockTableRecord btr=(BlockTableRecord)tm.GetObject(<BR>&nbsp;&nbsp;&nbsp;&nbsp; bt,OpenMode.ForWrite);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;// 将实体添加到图形数据库的块表记录中<BR>&nbsp;&nbsp;&nbsp;&nbsp;lineId=btr.AppendEntity(line);<BR>&nbsp;&nbsp;&nbsp;&nbsp;tm.AddNewlyCreatedDBObject(line,true);<BR>&nbsp;&nbsp;&nbsp;&nbsp;trans.Commit();</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;trans.Dispose();<BR>&nbsp;&nbsp; }<BR>&nbsp;&nbsp;}</P>
<P>这两种方法有什么不同?欢迎大家发表自己的意见。</P>

zfbj 发表于 2005-8-2 23:34:00

从代码上来看,似乎仅仅是事务辅助处理时不需要手工关闭打开或者新建的对象(这一操作在VC++的ObjectARX中非常普遍)。

zfbj 发表于 2005-8-2 23:58:00

大意了…编译的时候第一种方法通不过,开发教程中居然还有这样的代码,晕。发现Autodesk对.net开发的帮助文件极不负责,已经发现了不少错误。

zhf7878 发表于 2005-8-3 13:37:00

第一种方法是可以的,只不过编译的时候出现警告而已。

月海临风 发表于 2005-8-11 13:26:00

<P>事务在对连续操作出错时可以回滚,所以对添加块表记录和添加实体对象操作时使用事务包起来</P>
<P>呵呵,个人理解</P>

topirol 发表于 2005-8-11 18:00:00

<P>跟楼上想法一样</P>

zfbj 发表于 2005-8-12 10:13:00

楼上两位说的,在传统的ARX中确实如此,但是这里似乎并不是完全为了这个目的…

simengliu 发表于 2005-8-13 10:54:00

<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align=center>以下内容是我译的关于事务的部分内容,完整译文在附件里,其中的问题请指出,共勉!</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align=center>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align=center>事务管理器概述<SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-char-indent-count: 2.0">事务模式将多个客户对多个对象的若干个操作封装于个很小的动作中,它叫事务。在一个事务边界内,客户们可以通过对象的<SPAN lang=EN-US>ID而获得指向它的指针。直到事务被用户结束或中止之前,对象的指针都是有效的。如果事务成功的结束,则所有对对象的操作都被提交;如果事务被中断则作用于对象上的操作也被取消。<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-char-indent-count: 2.0">采用这个机制完成的操作相对于常规的打开和关闭(详见第<SPAN lang=EN-US>5章,《数据库对象》)办法有如下几个优点。打开关闭机制适用于对单个或少量对象的简单操作。而且,打开关闭机制在打开对象时有某些限制。例如,当一个对象打开用于读出,则此时你不能再打开用于写入。同样,当一个对象打开用于写入时,你不能同时打开用于读出。关于打开关闭对象时的一些可能引发的错误和限制见第5章。然而事务模式则显得更宽容,当对象与一个事务相关联之后,通过它的ID获得用于特定用途的对象指针一般都会成功。<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align=left>Depending upon your application, there can be other disadvantages to using the open and close mechanism. If your application opens and closes the same object a number of times in the course of one operation—for example, a command—you'll incur serious inefficiencies due to these multiple opens and closes. A number of time-consuming operations are associated with closing an object. If you open an object for write, modify it, and then close it, the undo records of the modification are committed to the undo file, graphics for the object are generated, and notifications are fired. All these operations are performed every time the object is closed. If you transact your operation and obtain a pointer to the object using a transaction, all the activities mentioned above happen only once, at the end of the transaction. The result is improved efficiency and a smaller undo file, because the number of records going into the undo file is reduced. <o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-char-indent-count: 2.0" align=left>当你开发某些应用程序时,采用打开关闭机制还可能有另外一些不便。如果程序在一个过程(比如一个命令)中多次打开、关闭同一个对象,由于这样的多次打开关闭操作应用程序的效率会很低。关闭对象伴随着很多是极耗时间的操作。当程序打开一个对象用于写入后,修改对象,然后关闭它,接着撤消操作的记录被写入到<SPAN lang=EN-US>undo文件中,之后对象的图形重新生成,最后通知被发出。每一次关闭对象时,所有的这些动作都会随之而来。换成事务模式,如果采用事务,通过事务获得对象的指针,则(关闭多个对象后)上面提到的各项操作仅在事务的最后发生一次。事务机制提高了执行的效率,使得undo文件较小因为写入文件中的记录数减少了。<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align=left>Also, if you have a complex network where objects refer to each other by object ID, you want to be able to obtain a pointer to an object in any module of your program without worrying if another module or another application has that object opened. These activities are only possible using the transaction model because transactions group operations and allow obtaining pointers from object IDs across module boundaries. <o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-char-indent-count: 2.0" align=left>同时,如果有一组彼此之间通过<SPAN lang=EN-US>ID相互引用的对象,你可以在任何一个模块中取得某个对象的指针而不用担心别的模块或程序已经将其打开了。这种行为只有采用事务机制才能实现,因为事务将多个操作集中在一起完成,而且能跨越模块的边界并可以借助对象ID而得到它的指针。<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align=left>The transaction manager is a global manager object, similar to the editor, that is in charge of maintaining transactions. It is an instance of AcTransactionManager and is maintained in the system registry. You can obtain it from the system registry using the macro, which expands to <o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-char-indent-count: 2.0" align=left>事务管理器是一个全局的管理对象(这与<SPAN lang=EN-US>editor相似),作用是负责维护事务。它是AcTransactionManager的实例而且在系统注册表中管理。你可以用系统注册的宏actrTransactionManager 来取得它,如下 所示:<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align=left>#define actrTransactionManager<SPAN style="mso-spacerun: yes">&nbsp; \<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align=left>AcTransactionManager::cast(<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align=left><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; acrxSysRegistry()-&gt;at(AC_TRANSACTION_MANAGER_OBJ))<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align=left>The transaction manager should be used to start, end, or abort transactions. It can also provide information such as the number of active transactions at any moment (see the following section, <A href="mk:@MSITStore:E:\Downloads\docs\arxdev.chm::/xdg_214.html#388392" target="_blank" ><SPAN style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">Nesting Transactions</A>) and a list of all the objects whose pointers have been obtained in all the transactions. The transaction manager maintains a list of reactors to notify clients of events such as the start, end, or abort of a transaction. <o:p></o:p></SPAN></P>

slyd 发表于 2010-10-21 19:17:00

Very Good! 3Q
页: [1]
查看完整版本: [讨论]这两种方法创建实体有什么不同?