.NET

.NET

Reply
Contributor
JDM1
Posts: 18
Registered: ‎10-28-2008
Message 1 of 4 (251 Views)
Accepted Solution

Internal Error: dbobji.cpp@8638: ENotOpenForWrite

251 Views, 3 Replies
08-15-2014 06:10 AM

Hello all,

 

I would appreciate any help you can give me.

 

I am using Visual Studio 2013 and Architecture 2015. I have windows 7 64 bit system

I'm trying to learn .net and I don't understand why this code is crashing.

 

It runs fine the firse time. But if I run the code a second time in the same drawing autocad crashes and I get this error.

 

Internal Error: dbobji.cpp@8638: ENotOpenForWrite

 

The code crashes at this line

 

"objHole.SetDatabaseDefaults()"

 

If I remove that line it crashes on the next line.

 

Here is the code.

 

Imports System
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput

 

<Assembly: CommandClass(GetType(Test.Commands))>

 

Namespace Test
Public Class Commands
Public Circle1 As Object
Public Circle2 As Object
Public Circle3 As Object
Public Circle1Center As Object
Public Circle2Center As Object
Public objHole As Circle = New Circle
Public obj2 As Circle = New Circle
Public obj3 As Circle = New Circle

<CommandMethod("start")>
Public Sub DrawCircles()

Dim AcadDoc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = AcadDoc.Database

Circle1 = 36
Circle2 = 48
Circle3 = 58

 

' Prompt the user for the center Point of circle 1
Dim ppr As PromptPointResult = AcadDoc.Editor.GetPoint(vbLf & "Pick a Point")

 

' If user escaped, Quit the command
If ppr.Status <> PromptStatus.OK Then
Exit Sub
End If

 

' Store the specified point of circle1
Circle1Center = ppr.Value

 

' Store the point for circle2
Circle2Center = Circle1Center

 

' Start a transaction to add the circles to the current space
' circle1, circle2, and circle3


Using trans As Transaction = db.TransactionManager.StartTransaction()

' Open the block table for read
Dim BlkTbl As BlockTable
BlkTbl = trans.GetObject(db.BlockTableId, OpenMode.ForRead)

 

' Open the block table record model space for write
Dim acBlkTblRec As BlockTableRecord
acBlkTblRec = trans.GetObject(BlkTbl(BlockTableRecord.ModelSpace), _
OpenMode.ForWrite)

 

' Create a new circle object for circle1
objHole.SetDatabaseDefaults()
objHole.Center = Circle1Center
objHole.Radius = Circle1 / 2

 

' Create a new circle object for circle2
'obj2.SetDatabaseDefaults()
obj2.Center = Circle2Center
obj2.Radius = Circle2 / 2

 

' Create a new circle object for circle3
'obj3.SetDatabaseDefaults()

obj3.Center = Circle2Center
obj3.Radius = Circle3 / 2

 

' Create points for new 3dpoint
Dim pt1 As Double = Circle2Center(0)
Dim pt2 As Double = Circle2Center(1)
Dim pt3 As Double = Circle2Center(2)

 

' Create a matrix and move circle2 and circle3 up
Dim Pt3d As Point3d = New Point3d(pt1, pt2, pt3)
Dim Vec3d As Vector3d = Pt3d.GetVectorTo(New Point3d(pt1, pt2 + Circle1 + Circle2, pt3))

obj2.TransformBy(Matrix3d.Displacement(Vec3d))
obj3.TransformBy(Matrix3d.Displacement(Vec3d))

 

' Add the newly created circle1 to the space
acBlkTblRec.AppendEntity(objHole)
trans.AddNewlyCreatedDBObject(objHole, True)

 

' Add the newly created circle2 to the space
acBlkTblRec.AppendEntity(obj2)
trans.AddNewlyCreatedDBObject(obj2, True)

 

' Add the newly created circle3 to the space
acBlkTblRec.AppendEntity(obj3)
trans.AddNewlyCreatedDBObject(obj3, True)

 

' Commit the changes to the database

trans.Commit()
trans.Dispose()
acBlkTblRec.Dispose()


End Using

 

Application.AcadApplication.zoomextents()
AcadDoc.Editor.Regen()


End Sub


End Class


End Namespace

 

Thanks in advance for any help you can give me.

 

 

I just glanced at it real quick but it looks like you are creating your circles outside the confines of your command.  i.e. at the class level so it is only created once.  It works well the first time through but the second time through you are using the same circle which is not open becuase it was closed the last time you ran the command.

The problem your code has is in the declaration of the 3 Circles at class level:

 

Public objHole As Circle = New Circle
Public obj2 As Circle = New Circle
Public obj3 As Circle = New Circle

 

the problem is that your code not only declare 3 variables, but also instantiate 3 Circel objects.

 

What happens is that when your command runs the first time, the 3 Circle objects are created in memory for the current document. and when the command goes through, the 3 Circles are ModelSpace and the transaction is commited. However, since the 3 variables that hold the 3 Circles are still in scope because they are class leveled, after the transaction is commited, the circles's open state are changed from ForWrite to ForRead, hence the error if you run the command the second time.

 

In your case, you SHOULD NOT declare database residing object with "New" keyword. You ONLY "New" an database residing object inside a transaction, or if you somehow instantiate an entity and do not intend to add it into database, you need to dispose it.

 

Also, in general do not keep an database residing entity instance outside a transaction, keep track its ObjectId instead.

 

So, for your code, you should declare the Circles like this:

 

Private objHole As Circle
Private obj2 As Circle
Private obj3 As Circle

 

and then after the Transaction started,

 

objHole=New Circle

obj2=New Circle

obj3=New Circle

 

and after the transaction

 

objHole=Nothing

obj2=Nothing

obj3=Nothing

 

Better yet, you simple do not declare the Circles at class level. Instead, you place the declareation with "New" after the Transaction started.

 

BTW, why declare variables as Object when they are for holding Double, Point3d values? They should be declaread like

 

Private Circle1 As Double
Private Circle2 As Double
Private Circle3 As Double
Private Circle1Center As Point3d
Private Circle2Center As Point3d

 

Again, based on your code, there is no need to declare them at class level, not to mention to be declared as "Public"

 

*Expert Elite*
Keith.Brown
Posts: 1,236
Registered: ‎03-13-2008
Message 2 of 4 (246 Views)

Re: Internal Error: dbobji.cpp@8638: ENotOpenForWrite

08-15-2014 06:29 AM in reply to: JDM1

I just glanced at it real quick but it looks like you are creating your circles outside the confines of your command.  i.e. at the class level so it is only created once.  It works well the first time through but the second time through you are using the same circle which is not open becuase it was closed the last time you ran the command.


Keith Brown AutoCAD MEP BLOG | RSS Feed
AutoCAD MEP 2014 | Revit 2014 | EastCoast CAD/CAM V6.1 | Visual Studio 2013
────────────────────────────────────
⁞|⁞ Please use Mark Solutions!.Accept as Solution and Give Kudos!Give Kudos as appropriate. Thank you!
*Expert Elite*
norman.yuan
Posts: 1,063
Registered: ‎04-27-2009
Message 3 of 4 (238 Views)

Re: Internal Error: dbobji.cpp@8638: ENotOpenForWrite

08-15-2014 06:48 AM in reply to: JDM1

The problem your code has is in the declaration of the 3 Circles at class level:

 

Public objHole As Circle = New Circle
Public obj2 As Circle = New Circle
Public obj3 As Circle = New Circle

 

the problem is that your code not only declare 3 variables, but also instantiate 3 Circel objects.

 

What happens is that when your command runs the first time, the 3 Circle objects are created in memory for the current document. and when the command goes through, the 3 Circles are ModelSpace and the transaction is commited. However, since the 3 variables that hold the 3 Circles are still in scope because they are class leveled, after the transaction is commited, the circles's open state are changed from ForWrite to ForRead, hence the error if you run the command the second time.

 

In your case, you SHOULD NOT declare database residing object with "New" keyword. You ONLY "New" an database residing object inside a transaction, or if you somehow instantiate an entity and do not intend to add it into database, you need to dispose it.

 

Also, in general do not keep an database residing entity instance outside a transaction, keep track its ObjectId instead.

 

So, for your code, you should declare the Circles like this:

 

Private objHole As Circle
Private obj2 As Circle
Private obj3 As Circle

 

and then after the Transaction started,

 

objHole=New Circle

obj2=New Circle

obj3=New Circle

 

and after the transaction

 

objHole=Nothing

obj2=Nothing

obj3=Nothing

 

Better yet, you simple do not declare the Circles at class level. Instead, you place the declareation with "New" after the Transaction started.

 

BTW, why declare variables as Object when they are for holding Double, Point3d values? They should be declaread like

 

Private Circle1 As Double
Private Circle2 As Double
Private Circle3 As Double
Private Circle1Center As Point3d
Private Circle2Center As Point3d

 

Again, based on your code, there is no need to declare them at class level, not to mention to be declared as "Public"

 

Contributor
JDM1
Posts: 18
Registered: ‎10-28-2008
Message 4 of 4 (227 Views)

Re: Internal Error: dbobji.cpp@8638: ENotOpenForWrite

08-15-2014 07:24 AM in reply to: norman.yuan

Wow that was a very fast responce.

Thanks to both of you. you were both right.

 

@ norman 

 

Thanks you very much for you detailed explanation.

 

When I changed Circle1Center to Double

I get these errors when I try to build the project

that's why I declared them as objects 

 

Error 1 Value of type 'Autodesk.AutoCAD.Geometry.Point3d' cannot be converted to 'Double'. C:\Users\jdm\Documents\Visual Studio 2013\Projects\test\test\myCommands.vb 40 29 test

 

Error 2 Value of type 'Double' cannot be converted to 'Autodesk.AutoCAD.Geometry.Point3d'. C:\Users\jdm\Documents\Visual Studio 2013\Projects\test\test\myCommands.vb 64 34 test

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Do you have 60 seconds to spare? The Autodesk Community Team is revamping our site ranking system and we want your feedback! Please click here to launch the 5 question survey. As always your input is greatly appreciated.