Hmmm...the ActiveX item method would still be using an internal loop to find
the record????
I think I would prefer to do the loop myself in native C# if you know what I
mean.
And yes, this is a potential source of some VERY annoying bugs.
Again, thanks for the input.
Cheers,
Glenn.
"Tony Tanzillo" wrote in message
news:4918048@discussion.autodesk.com...
WRT the workaround (iterating over the entire layer
table to find the desired entry), I spoke too soon.
The easy solution is to use ActiveX to get the
AcadLayer object, and then use FromAcadObject
to get the ObjectId.
--
http://www.caddzone.com
AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006
http://www.acadxtabs.com
"Glenn Ryan" wrote in message
news:4918031@discussion.autodesk.com...
Tony,
I had already come to the same conclusion and had adjusted my code
acccordingly - thanks for the confirmation.
Thinking out loud, I know the *preferred* way in .net is to have a default
indexer [], but it would be nice to have AcDbSymbolTable::getAt
exposed directly as well, because, as you mentioned, it effects ALL derived
classes as well.
Cheers,
Glenn.
"Tony Tanzillo" wrote in message
news:4917010@discussion.autodesk.com...
The fact that you're getting an eDuplicateRecord error
serves to confirm that the problem is what I said it
was initially, which is that the default indexer for the
SymbolTable managed wrapper class, is incorrectly (IMO)
calling AcDbSymbolTable::getAt() with the third argument
set to true. That will cause it to return the first matching
entry, even if it is erased.
Hence, that effectively makes the default indexer for the
SymbolTable and all derived classes, useless (unless you
want it to return deleted symbol table records, which is
generally not the case).
The only way around it is to iterate over the entire layer
table, to locate the entry with the specified name.
--
http://www.caddzone.com
AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006
http://www.acadxtabs.com
"Glenn Ryan" wrote in message
news:4916851@discussion.autodesk.com...
Tony,
If you follow these steps, with the revised code below, you will get the
eDuplicateRecord error:
1. Start blank new drawing.
2. Run code.
3. Set layer 0 current.
4. Purge
5. Run code.
6. Run code.
Revised code (the only thing that has changed is the TRUE branch of the main
IF statement):
[CommandMethod("LayerTest")]
public void test() // This method can have any name
{
Document pDoc = AcadApp.DocumentManager.MdiActiveDocument;
// Get a pointer to the current doc's dbase...
Database pDb = pDoc.Database;
// While we're at it, get a pointer to the editor...
Editor pEd = pDoc.Editor;
// Our 'test' layer name...
string layerName = "Test";
// Our test layer's objectIdnl
ObjectId layerId = ObjectId.Null;
// Kick off a transaction in the current dbase...
using (Transaction pTr = pDb.TransactionManager.StartTransaction())
{
try
{
// Try and open the layer table for write...
LayerTable pLayerTable = (LayerTable)pTr.GetObject(pDb.LayerTableId,
OpenMode.ForRead);
// Does it contain our layer?
if (pLayerTable.Has(layerName))
{
layerId = pLayerTable[layerName];
if (layerId.IsErased)
{
LayerTableRecord pExLtr = (LayerTableRecord)pTr.GetObject(layerId,
OpenMode.ForWrite, true);
pExLtr.Erase(false);
}
}
else // Nope, so create it...
{
LayerTableRecord pNewLTR = new LayerTableRecord();
// Set the name...
pNewLTR.Name = layerName;
// Add it...
pLayerTable.UpgradeOpen();
layerId = pLayerTable.Add(pNewLTR);
// Let the transaction know about it...
pTr.AddNewlyCreatedDBObject(pNewLTR, true);
}//else
// Commit the transaction...
pTr.Commit();
// Set the current layer...
pDb.Clayer = layerId;
}//try
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
pEd.WriteMessage("\nError: " + ex.Message);
}
}//using transaction
}//command test
Cheers,
Glenn.
"Tony Tanzillo" wrote in message
news:4916734@discussion.autodesk.com...
If you unerase and re-use the existing entry, where does
the eDuplicateKey error occur?
I don't like the idea of unerasing and re-using a layer
table record (who knows what can be attached to it,
or where it is referenced), but it may be the only way
to do it.
--
http://www.caddzone.com
AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006
http://www.acadxtabs.com
"Glenn Ryan" wrote in message
news:4916612@discussion.autodesk.com...
Hi Tony,
Thanks for the reply. That was my suspicion as well,
and I have already tried unerasing the layer if ObjectId.IsErased is true.
You then get an eDuplicateKey error...go figure...anymore suggestions?
Cheers,
Glenn.
"Tony Tanzillo" wrote in message
news:4916128@discussion.autodesk.com...
The default indexer for SymbolTable is calling
AcDbSymbolTable::getAt() and passing true
as the third argument (true = get erased record).
I'm not sure about AcDbSymbolTable::has(), but
since it is not specified in the docs, it is possible
that it is also returning true if an erased record
exists.
My suggestion would be to check the IsErased
property on any ObjectId returned by the default
indexer, and if it is true, then just unerase it.
My guess about why this may be necessary, is that
it's quite possible that symbol tables cannot have
more than one entry with the same name, even if
all but one of them are erased.
--
http://www.caddzone.com
AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006
http://www.acadxtabs.com
"Glenn Ryan" wrote in message
news:4915935@discussion.autodesk.com...
Hello everyone,
I've run into some strange behaviour with regards to transactions and
SymbolTableRecords.
If you follow these steps with the code below, you will get an exception of
either eWasErased or eDuplicateRecord.
Steps:
1. Create a brand new drawing.
2. Run the code below.
3. Erase all entities in the drg.
4. Set the current layer to 0.
5. Purge the drawing.
6. Run the code again.
7. Run the code again.
At step 7 you will receive the exception. I've also tried these steps with
all the Adesk supplied samples and labs that I could find that create layers
(in particular) and they all suffer the same fate...any ideas as to why and
how to overcome it?
The code:
using System ;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime ;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
[assembly: CommandClass(typeof(ClassLibrary.tcgsClass))]
namespace ClassLibrary
{
///
/// Summary description for tcgsClass.
///
public class tcgsClass
{
public tcgsClass()
{
//
// TODO: Add constructor logic here
//
}
// Define Command "LayerTest"
[CommandMethod("LayerTest")]
public void test() // This method can have any name
{
Document pDoc = AcadApp.DocumentManager.MdiActiveDocument;
// Get a pointer to the current doc's dbase...
Database pDb = pDoc.Database;
// While we're at it, get a pointer to the editor...
Editor pEd = pDoc.Editor;
// Our 'test' layer name...
string layerName = "Test";
// Our test layer's objectIdnl
ObjectId layerId = ObjectId.Null;
// Kick off a transaction in the current dbase...
using (Transaction pTr = pDb.TransactionManager.StartTransaction())
{
try
{
// Try and open the layer table for write...
LayerTable pLayerTable = (LayerTable)pTr.GetObject(pDb.LayerTableId,
OpenMode.ForWrite, true);
// Does it contain our layer?
if (pLayerTable.Has(layerName))
layerId = pLayerTable[layerName];
else // Nope, so create it...
{
LayerTableRecord pNewLTR = new LayerTableRecord();
// Set the name...
pNewLTR.Name = layerName;
// Add it...
layerId = pLayerTable.Add(pNewLTR);
// Let the transaction know about it...
pTr.AddNewlyCreatedDBObject(pNewLTR, true);
}//else
// Commit the transaction...
pTr.Commit();
// Set the current layer...
pDb.Clayer = layerId;
}//try
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
pEd.WriteMessage("\nError: " + ex.Message);
}
}//using transaction
}//command test
}//class
}//namespace