ApplicationServices.TransactionManger vs. DatabaseServices.TransactionManager

bakerrWZ69Z
Participant
Participant

ApplicationServices.TransactionManger vs. DatabaseServices.TransactionManager

bakerrWZ69Z
Participant
Participant

I have noticed something strange when I use the DatabaseServices.TransactionManager property to create an OpenCloseTransaction compared to using the ApplicationServices.TransactionManager property to create a Transaction.

When I look at the OpenCloseTransaction in the Visual Studio Watch window it indicates the TransactionManager property threw an exception.  However, the TransactionManager property on the Transaction shows no exception.

What I am trying to figure out is if the OpenCloseTransaction class it causing the exception or if I have done something in my code or project settings to cause the problem.

Note:  In one case I am using the Document TransactionManager to create a transaction and in the other I am using a Database TransactionManager to create the transaction.

Here is the information shown in the Watch window.

bakerrWZ69Z_0-1719956436675.png

Here is the code I used to produce these results.


Autodesk.AutoCAD.ApplicationServices.TransactionManager docTranMgr = AcAppServicesApp.DocumentManager.MdiActiveDocument.TransactionManager;

Transaction docTran = docTranMgr.StartTransaction();

Autodesk.AutoCAD.DatabaseServices.TransactionManager dbTranMgr = AcAppServicesApp.DocumentManager.MdiActiveDocument.Database.TransactionManager;

OpenCloseTransaction dbTran = dbTranMgr.StartOpenCloseTransaction();

0 Likes
Reply
Accepted solutions (1)
523 Views
6 Replies
Replies (6)

ActivistInvestor
Advisor
Advisor

OpenCloseTransaction has no associated TransactionManager, and if you try to reference its TransactionManager property, it throws an exception. That's because it isn't associated with any database or document. It's not really a transaction in the same sense as those returned by StartTransaction().  It exists as a way to open objects without opening them in a 'real transaction' because there are some scenarios where object's can't be opened in a transaction (e.g., from event handlers, overrule overrides, etc).

0 Likes

bakerrWZ69Z
Participant
Participant

Then why is OpenCloseTransaction derived off of Transaction and why is a transaction manager used to create it?

It seems to me that when the transaction manager StartOpenCloseTransaction method was used to create the OpenCloseTransaction it failed to initialize the TransactionManager read-only property.

Still my main questions is:  Can I ignore the exception message?

Even though I have a catch that will catch a Autodesk.AutoCAD.Runtime.Exception it never executes my catch code so I am assuming the exception is being caught somewhere else.

0 Likes

ActivistInvestor
Advisor
Advisor

@bakerrWZ69Z wrote:

Then why is OpenCloseTransaction derived off of Transaction and why is a transaction manager used to create it?


OpenCloseTransaction derives from Transaction so that it looks like a Transaction, and can be used interchangeably with code that uses any Transaction (with the exception of the TransactionManager property).  I have hundreds of APIs that take a Transaction as an argument. I can pass them either type of transaction (depending on the use case and context), and they will work with either type of transaction passed to them.

 

If OpenCloseTransaction wasn't derived from Transaction, you would have to write different code to work with it.

 


It seems to me that when the transaction manager StartOpenCloseTransaction method was used to create the OpenCloseTransaction it failed to initialize the TransactionManager read-only property.

It isn't failing to initialize the TransactionManager property. TransactionManagers are database-specific. Every Database has a TransactionManager, and every TransactionManager is owned by a single Database.

 

OpenCloseTransactions are not database-specific, which is why there is no TransactionManager.

 

Here is the source code for StartOpenCloseTransaction():

 

// Acdbmgd, Version=25.0.0.0, Culture=neutral, PublicKeyToken=null
// Autodesk.AutoCAD.DatabaseServices.TransactionManager

public virtual OpenCloseTransaction StartOpenCloseTransaction()
{
   return new OpenCloseTransaction();
}

 

As we can see, all it does is call the constructor for OpenCloseTransaction, and doesn't pass it any arguments. 

 

I routinely use OpenCloseTransactions by calling the constructor just as the method above does. I can't remember the last time I called StartOpenCloseTransaction().  There's no point to it, since all it does is call the constructor.

 

That works, because an OpenCloseTransaction is not associated with any database, and in fact, you can use the same OpenCloseTransaction to open DBObjects from different databases. An OpenCloseTransaction is functionally like a List<DBObject> that contains open DBObjects that you got by calling GetObject(). When you call Commit(), it calls Close() on each open DBObject in the list. When you call Abort(), it calls Cancel() on each open DBObject in the list. Dispose() calls Abort(), and that's about all there is to it.

 


Still my main questions is:  Can I ignore the exception message?

Even though I have a catch that will catch a Autodesk.AutoCAD.Runtime.Exception it never executes my catch code so I am assuming the exception is being caught somewhere else.

It depends on what you're using the TransactionManager property for. With an OpenCloseTransaction, there is no TransactionManager, so I can't really tell you how to deal with that without knowing why you need to use the TransactionManager. As far as catching the exception it throws, I don't know what good that would be if your code subsequently needs to use the TransactionManager. 

bakerrWZ69Z
Participant
Participant
Accepted solution

I am not actually trying to use the TransactionManager property on the OpenCloseTransaction.  I only noticed the exception when I used Visual Studio Debugger to look at the properties of the OpenCloseTransaction object I created.  When it shows me the properties it displays the exception message as the value for the TransactionManager property.

I have had other cases where I try to view the properties of an AutoCAD .NET objects using the Visual Studio Debugger and it will actually crash AutoCAD.  It typically happens if I try to view an AutoCAD .NET object before it has been added to the drawing file.  I assume it crashes AutoCAD because certain values have not been set yet.

So since the Debugger appears to be causing the exception message when viewing the object's properties I guess I will ignore it.

0 Likes

ActivistInvestor
Advisor
Advisor

Indiscriminate viewing of all properties of a managed wrapper in the debugger or in another similar browsing context will usually result in exceptions (most notably, eNotApplicable). It's considered normal, and when accessing those properties from actual code, the programmer must check to see if the properties are 'applicable' or usable. How they do that depends mostly on the property that's being accessed.

 

 

0 Likes

bakerrWZ69Z
Participant
Participant

Here is a little background.  For a long time I have written programs for AutoCAD using AutoLisp or ObjectARX.  As a result, I am quite knowledgeable on how to access and modify AutoCAD objects.  Only recently have I started writing AutoCAD .NET programs using C#.

 

I ran into a problem where my C# program was crashing AutoCAD when it was compiled in Release mode and it reported an Access  Violation message.  As a result, when I looked at the OpenCloseTransaction.TransactionManager property and it reported an Access Violation I thought maybe that was causing my crash.

 

Since then I have read up on memory management, transactions and using statements and based on that information I have revised my code to make sure the AutoCAD resources inside the .NET classes are disposed as soon as possible.  So far I haven't gotten any more crashes.  Hopefully, that will continue. 

0 Likes