Author Topic: Commit vs Abort  (Read 9164 times)

0 Members and 1 Guest are viewing this topic.

Glenn R

  • Guest
Commit vs Abort
« on: September 19, 2006, 07:42:23 PM »
I found the following piece of information here: http://through-the-interface.typepad.com/

Quote
// Although no changes were made, use Commit()
// as this is much quicker than rolling back
tr.Commit();

Also notice the Dispose pattern that the Autodesk guys seem to be using...

Thoughts anyone?

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Commit vs Abort
« Reply #1 on: September 19, 2006, 09:02:30 PM »
Glen, the documentation seems to support the way Kean is demonstrating.
(see Piccy)

I believe the Dispose is used because the Managed objects refer to the unmanaged ARX objects ... bla, bla
... something to do with freeing memory resulting from references to the base types


kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Commit vs Abort
« Reply #2 on: September 19, 2006, 10:24:37 PM »
 .. Though I dont imagine there's anything new for you in what I've posted ..

a bit of a side issue,
I have noticed the samples don't make a lot of use of using 
Code: [Select]
using (Transaction trans = ... blabla


kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
Re: Commit vs Abort
« Reply #3 on: September 19, 2006, 11:14:22 PM »
Code: [Select]
foreach (ObjectId objId in objIds)

            {

              Entity ent =

                (Entity)tr.GetObject(objId, OpenMode.ForRead);

              // In this simple case, just dump their properties

              // to the command-line using list

              ent.List();

              ent.Dispose();

            }

            // Although no changes were made, use Commit()

            // as this is much quicker than rolling back

            tr.Commit();


I was more refering to his comment about it being quicker to call Commit on a transaction that you have only used for read purposes, rather than calling Abort or letting it drop out of a using scope.

Also, notice in his foreach loop, he's calling Dispose on the Entity reference he retrieved - I was under the impression this was not necessary....
« Last Edit: September 19, 2006, 11:15:23 PM by Glenn R »

Glenn R

  • Guest
Re: Commit vs Abort
« Reply #4 on: September 20, 2006, 12:11:26 AM »
Kerry, I noticed the lack of using statements as well. Also, in that latest example on thru-the-interface, he doesn't even dispose of his transaction...naughty, naughty.

Cheers,
Glenn.

MickD

  • King Gator
  • Posts: 3637
  • (x-in)->[process]->(y-out) ... simples!
Re: Commit vs Abort
« Reply #5 on: September 20, 2006, 01:35:26 AM »
This is the problem with hll's (especially relatively new ones like the .net group), they have too many ways that 'seem' to accomplish the same thing. This can lead to confusion and subtle errors.
If I had time I'd look at which way was most efficient (not convenient) and stick to it. I generally use the try/catch/finally, you explicitly do what you have to do and can handle/control all side effects of your code in both the catch and the finally.
Using the 'using' directive may save typing but pretty much has to do the same thing (clean up) in the background anyway and if a class doesn't implement the IDisposable interface correctly you could have problems. This may be ok when using libraries such as the acad managed wrappers and then you are relying on the classes being coded correctly  :-o but if you create your own you may run into trouble.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

TonyT

  • Guest
Re: Commit vs Abort
« Reply #6 on: September 20, 2006, 03:21:20 AM »


Also, notice in his foreach loop, he's calling Dispose on the Entity reference he retrieved - I was under the impression this was not necessary....


Quite correct.

Dispose() is only required if the entity is not database-resident,  and not transaction-resident.

The purpose of Dispose() for a DBObject is to do two things:

1.  If the object is not transaction-resident, it calls close()  or cancel() (otherwise, the transaction takes care of doing that).

2.  If the object is not database-resident (e.g, it wraps a 'in-memory' AcDbObject that was allocated on the heap using the 'new' operator), then it calls delete to deallocate the AcDbObject.

Keep in mind that if an AcDbObject is database-resident, its life is managed by the AcDbDatabase, in which case the delete operator should never be called on it.

If we're critiquing Kean's code, then there is something else that may not be obvious, which is that when a CommandMethod is declared with the UsePickSet command flag, you do not need to call SelectImplied(), because GetSelection() will implicitly return any pickfirst selection set if one exists, or prompt for a selection otherwise.

Generally, using SelectImplied() (or (ssget"i") in LISP) is largely pointless, unless you need to know if the resulting selection set was selected in advance of issuing the command, rather than selected in response to the "Select objects: " prompt that would otherwise occur after the command starts.

So, if you want a command that calls GetSelection() to support the pickfirst selection set, just add the CommandFlags.UsePickSet flag to the CommandMethod attribute, and that's all you really need.

TonyT

  • Guest
Re: Commit vs Abort
« Reply #7 on: September 20, 2006, 03:26:17 AM »
Kerry, I noticed the lack of using statements as well. Also, in that latest example on thru-the-interface, he doesn't even dispose of his transaction...naughty, naughty.

Cheers,
Glenn.

Well, it's not required if you explicitly call Commit() or Abort().

For a Transaction, Dispose() simply ensures that the transaction is ended

Having said that, I find it to be helpful to alwys follow the same pattern (e.g., the using() clause or try/finally and Dispose()) for all objects that require it).

TonyT

  • Guest
Re: Commit vs Abort
« Reply #8 on: September 20, 2006, 03:42:55 AM »
This is the problem with hll's (especially relatively new ones like the .net group), they have too many ways that 'seem' to accomplish the same thing. This can lead to confusion and subtle errors.
If I had time I'd look at which way was most efficient (not convenient) and stick to it. I generally use the try/catch/finally, you explicitly do what you have to do and can handle/control all side effects of your code in both the catch and the finally.
Using the 'using' directive may save typing but pretty much has to do the same thing (clean up) in the background anyway and if a class doesn't implement the IDisposable interface correctly you could have problems. This may be ok when using libraries such as the acad managed wrappers and then you are relying on the classes being coded correctly  :-o but if you create your own you may run into trouble.

Most coming from a C++ background might prefer the using() pattern rather than try/catch/finally. OTOH, those with Object Pascal experience might be more comfortable with the latter. I've used both C++ and OP extensively, and prefer the more implicit C++ style of the using() construct.

That's mainly because a destructor in C++ is commonly used to do what Dispose() does in managed code, and because a C++ object's destructor is automatically called on any automatic variable created on the stack when the variable goes out of scope:

Code: [Select]

{
    CMyObject myObject;   // CMyObject() constructor called here
 
    // use myObject here.

}  // ~CMyObject() d'tor is implicitly called here.


The basic idea behind using() is to make it more like C++ :-)


Draftek

  • Guest
Re: Commit vs Abort
« Reply #9 on: September 20, 2006, 07:55:38 AM »
Wow, thanks guys!

*Bookmarked*

Chuck Gabriel

  • Guest
Re: Commit vs Abort
« Reply #10 on: September 20, 2006, 07:59:06 AM »

LE

  • Guest
Re: Commit vs Abort
« Reply #11 on: September 20, 2006, 09:46:20 AM »

Glenn R

  • Guest
Re: Commit vs Abort
« Reply #12 on: September 20, 2006, 06:21:12 PM »
Good discussion - it confirmed what I have always believed to be correct - thanks Tony. If the database owns it - don't try to 'delete' it.

I also miss the 'scoping' constructs of C++. I used to declare a smart pointer, then wrap the use of it in curly braces to be as tight as possible - when the scope ends, pointer deleted/cleaned up - nice.

Now, C# does have scoping that you can use like this - just not with objects and destructors/dispose  8-)

On another note, if Autodesk want to set up this blog business and post examples, they of all people should post well designed and at the very least, syntactically correct, code examples - it just leads to confusion otherwise.

Quote
Having said that, I find it to be helpful to alwys follow the same pattern (e.g., the using() clause or try/finally and Dispose()) for all objects that require it).

Wholeheartedly agree!

Thoughts on the Commit vs Abort speed thing with respect to a 'read-only' op?

Cheers,
Glenn.

TonyT

  • Guest
Re: Commit vs Abort
« Reply #13 on: September 20, 2006, 09:50:32 PM »

Thoughts on the Commit vs Abort speed thing with respect to a 'read-only' op?


I'm not privy to the internal details, and I've never done any profiling. If performance is an issue, I generally avoid using transactions entirely and use ObjectId.Open() to access objects on a read-only basis.

Transactions also wrap the UNDO Begin/End/U mechanism. That is, starting a transaction implies an UNDO/Begin (hence an undo 'Group' is analagous to a transaction), and comitting one imples an UNDO/End. Aborting a transaction implies both UNDO/End, followed by 'U'.

I think I mentioned that outiside the context of a registered command handler, I've had problems using transactions for read-only object access, regardless of whether they are committed or aborted (the manifestation is that it disables REDOing of the operation(s) after the transaction is ended, if they are undone).


« Last Edit: September 20, 2006, 09:52:40 PM by TonyT »

TonyT

  • Guest
Re: Commit vs Abort
« Reply #14 on: September 20, 2006, 10:10:11 PM »
Glen, the documentation seems to support the way Kean is demonstrating.
(see Piccy)

I believe the Dispose is used because the Managed objects refer to the unmanaged ARX objects ... bla, bla
... something to do with freeing memory resulting from references to the base types

The docs you cite, may be intended to apply to all supported releases of .NET, and keeping in mind that in VS2002/NET 1.0, there was no 'using' clause, so it was necessary to use the try/catch/finally pattern for disposing.

Also, I woudln't regard those docs as holy scripture. There is really no reason why objects must be accessed via transactions, especially given the problems with using transactions in some contexts, which can result in disabling REDO. In native ObjectARX, this is no such requirement.