.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

eWasOpenForWrite

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
SRSDS
2703 Views, 6 Replies

eWasOpenForWrite

Hi,

 

Can someone please try to spot what's wrong to get an eWasOpenForWrite on the line

 db.Clayer = acLyrTbl("DIM")

 

 Private Sub doc_CommandWillStart(ByVal sender As Object, ByVal e As CommandEventArgs)
        If PauseEvents = False Then
            If e.GlobalCommandName = "DIMLINEAR" Or e.GlobalCommandName = "DIMALIGNED" Or e.GlobalCommandName = "DIMANGULAR" Or e.GlobalCommandName = "DIMCONTINUE" Then
                Using trans As Transaction = Application.DocumentManager.MdiActiveDocument.TransactionManager.StartOpenCloseTransaction : trcnt = trcnt + 1
                    Dim LayerName As String = "DIM"
                    Dim lyrId As ObjectId = Nothing
                    Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
                    Try
                        Dim lyrTbl As LayerTable = trans.GetObject(db.LayerTableId, OpenMode.ForRead, False)
                        Using ltypTbl As LinetypeTable = trans.GetObject(db.LinetypeTableId, OpenMode.ForRead, False)
                                Using myLayer As LayerTableRecord = New LayerTableRecord
                                If lyrTbl.Has(LayerName) = False Then
                                    myLayer.Name = LayerName
                                    lyrTbl.UpgradeOpen()
                                    lyrTbl.Add(myLayer)
                                    trans.AddNewlyCreatedDBObject(myLayer, True)
                                End If
                                lyrId = lyrTbl.Item(LayerName)
                                End Using
                            End Using
                        Dim acLyrTbl As LayerTable = trans.GetObject(db.LayerTableId, OpenMode.ForRead)
                        If acLyrTbl.Has("DIM") = True Then
                            db.Clayer = acLyrTbl("DIM")
                        End If
                        trans.Commit() 
                    Catch ex As Exception
                    MsgBox(Reflection.MethodBase.GetCurrentMethod.Name() + " Exception: " + ex.Message)
                    End Try
                End Using
            End If
        End If
    End Sub
6 REPLIES 6
Message 2 of 7
_gile
in reply to: SRSDS


@SRSDS  a écrit :

Hi,

 

Can someone please try to spot what's wrong to get an eWasOpenForWrite on the line

 db.Clayer = acLyrTbl("DIM")

 

 Private Sub doc_CommandWillStart(ByVal sender As Object, ByVal e As CommandEventArgs)
        If PauseEvents = False Then
            If e.GlobalCommandName = "DIMLINEAR" Or e.GlobalCommandName = "DIMALIGNED" Or e.GlobalCommandName = "DIMANGULAR" Or e.GlobalCommandName = "DIMCONTINUE" Then
                Using trans As Transaction = Application.DocumentManager.MdiActiveDocument.TransactionManager.StartOpenCloseTransaction : trcnt = trcnt + 1
                    Dim LayerName As String = "DIM"
                    Dim lyrId As ObjectId = Nothing
                    Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
                    Try
' here you open the layer table for read Dim lyrTbl As LayerTable = trans.GetObject(db.LayerTableId, OpenMode.ForRead, False) Using ltypTbl As LinetypeTable = trans.GetObject(db.LinetypeTableId, OpenMode.ForRead, False) Using myLayer As LayerTableRecord = New LayerTableRecord If lyrTbl.Has(LayerName) = False Then myLayer.Name = LayerName
' here you upgrade open the layer table (for write) lyrTbl.UpgradeOpen() lyrTbl.Add(myLayer) trans.AddNewlyCreatedDBObject(myLayer, True) End If lyrId = lyrTbl.Item(LayerName) End Using End Using
' here you open layer table again which is already opened for write Dim acLyrTbl As LayerTable = trans.GetObject(db.LayerTableId, OpenMode.ForRead) If acLyrTbl.Has("DIM") = True Then db.Clayer = acLyrTbl("DIM") End If trans.Commit() Catch ex As Exception MsgBox(Reflection.MethodBase.GetCurrentMethod.Name() + " Exception: " + ex.Message) End Try End Using End If End If End Sub

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 7
SRSDS
in reply to: _gile

Hi Gile,

That second section of code was moved in from another subroutine to try to show the problem a little more simply.

Without changing the code what would I need to add to 'close' the layer table.

I've tried:

lyrTbl.DownradeOpen 

lyrTbl.Dispose 

but they don't work.

 

If I use StartTransaction instead of StartOpenCloseTransaction the problem goes away but it's in an event handler so I believe I need to use the latter.

 

Message 4 of 7
_gile
in reply to: SRSDS

I'm not very comfortable with VB (actually, I hate VB) but try this 'corrected' code:

 

    Private Sub doc_CommandWillStart(ByVal sender As Object, ByVal e As CommandEventArgs)
        If Not PauseEvents Then 'Not booleanValue is clearer and less verbose than than booleanValue = False
            If e.GlobalCommandName = "DIMLINEAR" Or e.GlobalCommandName = "DIMALIGNED" Or e.GlobalCommandName = "DIMANGULAR" Or e.GlobalCommandName = "DIMCONTINUE" Then
                Using trans As Transaction = Application.DocumentManager.MdiActiveDocument.TransactionManager.StartOpenCloseTransaction : trcnt = trcnt + 1
                    Dim LayerName As String = "DIM"
                    Dim lyrId As ObjectId = ObjectId.Null 'ObjectId type is a non nullable type
                    Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
                    Try
                        Dim lyrTbl As LayerTable = trans.GetObject(db.LayerTableId, OpenMode.ForRead) 'False arg is useless a table cannot be erased
                        If Not lyrTbl.Has(LayerName) Then
                            Using myLayer As LayerTableRecord = New LayerTableRecord
                                myLayer.Name = LayerName
                                lyrTbl.UpgradeOpen()
                                lyrTbl.Add(myLayer)
                                trans.AddNewlyCreatedDBObject(myLayer, True)
                                lyrId = lyrTbl.Item(LayerName)
                            End Using
                        End If
						'use the lyrTbl variable which already contains the current layer table
                        If lyrTbl.Has("DIM") Then 'lyrTbl.Has("DIM") = True is verbose, simply use: lyrTbl.Has("DIM") instead
                            db.Clayer = lyrTbl("DIM")
                        End If
                        trans.Commit() 
                    Catch ex As Exception
                        MsgBox(Reflection.MethodBase.GetCurrentMethod.Name() + " Exception: " + ex.Message)
                    End Try
                End Using
            End If
        End If
    End Sub


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 7
SRSDS
in reply to: _gile

I shouldn't have tried to compact the code to explain the issue.

The problem I'm facing is that I have a one subroutine to add a new layer 

and another that sets the current layer.

 

After I add a new layer the layer table is left open; for write I guess and I can't close it.

 

And when I try to set the current layer using the SetCurrentLayer subroutine it creates the error:

 

    Public Sub SetCurrentLayer(ByVal sLayerName As String, ByRef trans As Transaction)
        Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
        Try
            Dim acLyrTbl As LayerTable = trans.GetObject(db.LayerTableId, OpenMode.ForRead)
            If acLyrTbl.Has(sLayerName) = True Then
                db.Clayer = acLyrTbl(sLayerName)
            End If
        Catch ex As Exception
            MsgBox(Reflection.MethodBase.GetCurrentMethod.Name() + " Exception: " + ex.Message)
        End Try
    End Sub

 

 

 

 

 

Message 6 of 7
_gile
in reply to: SRSDS

If you call two different method, it would be safer to use a different 'transaction' for each method.

        public ObjectId GetOrCreateLayer(Database db, string layerName)
        {
            ObjectId id;
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var layerTable = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
                if (layerTable.Has(layerName))
                {
                    id = layerTable[layerName];
                }
                else
                {
                    layerTable.UpgradeOpen();
                    var layer = new LayerTableRecord();
                    layer.Name = layerName;
                    id = layerTable.Add(layer);
                    tr.AddNewlyCreatedDBObject(layer, true);
                }
                tr.Commit();
            }
            return id;
        }

        public bool TrySetCurrentLayer(Database db, string layerName)
        {
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var layerTable = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
                if (layerTable.Has(layerName))
                {
                    db.Clayer = layerTable[layerName];
                    return true;
                }
            }
            return false;
        }

But, if I do not misunderstand, using the upper GetOrCreatelayer() method, you do not need the second method, you can simply do:

db.Clayer = GetOrCreatelayer(db, "DIM");

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 7
SRSDS
in reply to: _gile

That clears things up and also given me several tips.

Thanks again.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators


Autodesk Design & Make Report