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

DeepCloneObjects between two databases

4 REPLIES 4
Reply
Message 1 of 5
jfboyer
2455 Views, 4 Replies

DeepCloneObjects between two databases

The command is 5rep:

docA is the target database, it is where 5rep is entered
docB is the source database, and it's opened by 5rep

5rep is meant to copy objects from docB to docA
It requires a complex selection filter, that's why I need to open docB to get an Editor.

The following simplified code works when deep cloning objects within the same database, i.e docB
It fails when deep cloning objects from docB to docA (see commented portion)

Thanks for any help

Jf

{code}
[CommandMethod("5REP", CommandFlags.Session)]
public void SynchREP()
{
DocumentCollection docs = Application.DocumentManager;

Document docA = docs.MdiActiveDocument;
Database dbA = docA.Database;

Document docB = docs.Open("docB.dwg");
Database dbB = docB.Database;

DocumentLock dlockA = docA.LockDocument();
Transaction trA = dbA.TransactionManager.StartTransaction();
using (trA)
{
BlockTable btA = (BlockTable)trA.GetObject(
dbA.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord msA = (BlockTableRecord)trA.GetObject(
btA[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);

DocumentLock dlockB = docB.LockDocument();
Transaction trB = dbB.TransactionManager.StartTransaction();
using (trB)
{
BlockTable btB = (BlockTable)trB.GetObject(
dbB.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord msB = (BlockTableRecord)trB.GetObject(
btB[BlockTableRecord.ModelSpace],
OpenMode.ForRead
);

Editor edB = docB.Editor;
TypedValue[] tvsB = new TypedValue[]
{
new TypedValue( 67, "0" ),
new TypedValue( (int)DxfCode.Start, "INSERT" )
};
SelectionFilter sfB = new SelectionFilter(tvsB);
PromptSelectionResult psrB = edB.SelectAll(sfB);
SelectionSet ssetB = psrB.Value;
ObjectId[] ena = ssetB.GetObjectIds();
ObjectIdCollection oicB = new ObjectIdCollection(ena);

dbB.DeepCloneObjects(
oicB,
msB.Id, /* <-- targets the same database */
new IdMapping(), /* ...and it works */
false);

/*
dbB.DeepCloneObjects(
oicB,
msA.Id, <-- targets another database
new IdMapping(), ...and fails
false);

It raises an exception:
Autodesk.AutoCAD.Runtime.Exception: eWrongDatabase
in Autodesk.AutoCAD.DatabaseServices.Database.DeepCloneObjects */

trB.Commit();
}
trB.Dispose();
dlockB.Dispose();
}
trA.Dispose();
dlockA.Dispose();
}
{code}
4 REPLIES 4
Message 2 of 5
Anonymous
in reply to: jfboyer


DeepClone (and deepCloneObjects) is only for
within the same database.  For cloning between databases, you must use the
wblockClone mechanism (in your case the wblockCloneObjects()
function).


style="PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
The
command is 5rep: docA is the target database, it is where 5rep is entered docB
is the source database, and it's opened by 5rep 5rep is meant to copy objects
from docB to docA It requires a complex selection filter, that's why I need to
open docB to get an Editor. The following simplified code works when deep
cloning objects within the same database, i.e docB It fails when deep cloning
objects from docB to docA (see commented portion) Thanks for any help Jf
{code} [CommandMethod("5REP", CommandFlags.Session)] public void SynchREP() {
DocumentCollection docs = Application.DocumentManager; Document docA =
docs.MdiActiveDocument; Database dbA = docA.Database; Document docB =
docs.Open("docB.dwg"); Database dbB = docB.Database; DocumentLock dlockA =
docA.LockDocument(); Transaction trA =
dbA.TransactionManager.StartTransaction(); using (trA) { BlockTable btA =
(BlockTable)trA.GetObject( dbA.BlockTableId, OpenMode.ForRead );
BlockTableRecord msA = (BlockTableRecord)trA.GetObject(
btA[BlockTableRecord.ModelSpace], OpenMode.ForWrite ); DocumentLock dlockB =
docB.LockDocument(); Transaction trB =
dbB.TransactionManager.StartTransaction(); using (trB) { BlockTable btB =
(BlockTable)trB.GetObject( dbB.BlockTableId, OpenMode.ForRead );
BlockTableRecord msB = (BlockTableRecord)trB.GetObject(
btB[BlockTableRecord.ModelSpace], OpenMode.ForRead ); Editor edB =
docB.Editor; TypedValue[] tvsB = new TypedValue[] { new TypedValue( 67, "0" ),
new TypedValue( (int)DxfCode.Start, "INSERT" ) }; SelectionFilter sfB = new
SelectionFilter(tvsB); PromptSelectionResult psrB = edB.SelectAll(sfB);
SelectionSet ssetB = psrB.Value; ObjectId[] ena = ssetB.GetObjectIds();
ObjectIdCollection oicB = new ObjectIdCollection(ena); dbB.DeepCloneObjects(
oicB, msB.Id, /* <-- targets the same database */ new IdMapping(), /*
...and it works */ false); /* dbB.DeepCloneObjects( oicB, msA.Id, <--
targets another database new IdMapping(), ...and fails false); It raises an
exception: Autodesk.AutoCAD.Runtime.Exception: eWrongDatabase in
Autodesk.AutoCAD.DatabaseServices.Database.DeepCloneObjects */ trB.Commit(); }
trB.Dispose(); dlockB.Dispose(); } trA.Dispose(); dlockA.Dispose(); }
{code}
Message 3 of 5
jfboyer
in reply to: jfboyer

Thank you Art, it works:

{code}
dbB.WblockCloneObjects(
oicB,
msA.Id,
new IdMapping(),
DuplicateRecordCloning.Replace,
false);
{code}

AutoCAD NET C# copy from a drawing to another: use WblockClone

*edit*: the clone objects don't show up immediately in the target drawing window, although they are actually copied. I'm looking into QueueForGraphicsFlush to update the screen, not sure yet if this is the right way to do it.

Jf Edited by: jfboyer on Jun 12, 2009 12:54 PM
Message 4 of 5
varadan01
in reply to: jfboyer


                private void CloneObjectIds(ObjectIdCollection idsObjEntity, String strFileName)
        {
            try
            {
                Database dbNew = new Database(true, false);
                Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = dbNew.TransactionManager;
                ObjectId idModelSpace;
                using (Transaction mTy = tm.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tm.GetObject(dbNew.BlockTableId, OpenMode.ForRead, false);
                    BlockTableRecord Btr = (BlockTableRecord)tm.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead, false);
                    //idModelSpace = bt[BlockTableRecord.ModelSpace];
                    idModelSpace = Btr.Id;
                }
                IdMapping Mappin = new IdMapping();
                RTA_ApplicationData.Db.WblockCloneObjects(idsObjEntity, idModelSpace, Mappin, DuplicateRecordCloning.Ignore, false);
                

                String strFolderName = strFileName;
                strFileName = strFileName + ".dwg";
                String strPathName;
                String pathName = Assembly.GetExecutingAssembly().Location;
                pathName = pathName.Replace("LayerFilter.dll", "Drawing");
                DirectoryInfo dirInfo = Directory.CreateDirectory(pathName + "\\" + strFolderName);
                if (System.IO.File.Exists(pathName + "\\" + strFolderName))
                {
                    return;
                }
                dbNew.SaveAs(pathName + "\\" + strFolderName + "\\" + strFileName, DwgVersion.Newest);
                strPathName = pathName + "\\Temp\\" + strFileName;                           
            }

}

 

 

 

here i take the objectid collection as xref filter by its layer name.i tried to clone the object in new dwg its shows eWrongdatabase.

 

With Regards,
GVaradarajan
Message 5 of 5
DiningPhilosopher
in reply to: jfboyer

If the document you are deep-cloning the objects into is not the Active document the graphics will not be correctly generated.

 

You can either make the destination document active, or don't open it in the editor (use Database.ReadDwgFile() to open it).

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost