@_gile wrote:
@stefanome wrote:
I had never seen the ObjectID.Open, then I noticed that the IDE is reporting it as obsolete and it says I should use GetObject. I haven't tested, but I assume they are equivalent (maybe you are using Open simply because you are used to the old way).
The two codes I posted are equivalent. The OpenCloseTransaction is a wrapper for the Open / Dispose way which ensure the the DBObjects opened with or added to the OpenCloseTransaction are disposed when the transaction is disposed (this is why I use a 'using statement' for all objects opened with ObjectId.Open).
I'm not 'used to the old way', I simply wanted to show how to doi it without a Transaction as suggested by @daniel_cadext in reply #2.
Hi @_gile. The two examples you posted are not exactly equivalent.
The difference between them. is what happens in the event that an exception causes control to prematurely exit the using() block that disposes the OpenCloseTransaction (in the first example) or the using() block that disposes the DBObject (in the second example).
DBObject.Dispose() always calls AcDbObject::close(), which commits any changes made to the DBObject.
OpenCloseTransaction.Dispose() without a prior call to Commit(), calls AcDbObject::cancel() on each DBObject opened with the Transaction, which discards any changes made to the objects (that example is missing the call to Transaction.Commit() BTW, but I'm going on the assumption that it should).
So, in your first example (using OpenCloseTransaction), if an exception causes execution to exit the using() block before the call to Commit() is reached, changes made to any DBObjects are rolled-back, whereas in your second example, if an exception causes execution to exit the using() block, changes made to any DBObjects are not rolled-back, and instead are committed.
In order to make the two examples precisely-equivalent, you would need to refactor the second example, by placing all code that modifies the DBObject inside a try block that is followed by a catch() block that calls DBObject.Cancel(), and then rethrows the exception.
The general pattern would be:
static void ModifyWithObjectIdOpen(ObjectId id)
{
using(DBObject obj = id.Open(OpenMode.ForWrite, false, false))
{
try
{
/// all changes to the opened object must occur here
}
catch
{
obj.Cancel();
throw;
}
}
}
Which is precisely-equivalent to:
static void ModifyWithOpenCloseTransaction(ObjectId id)
{
using(var tr = new OpenCloseTransaction())
{
DBObject obj = tr.GetObject(id, OpenMode.ForWrite, false, false));
/// all changes to the opened object must occur here
tr.Commit();
}
}
So in fact, using ObjectId.Open() to modify DBObjects is not as simple as it may first appear, and is so much-more complicated that I strongly advise anyone to avoid using it it for anything but read-only purposes.