Hi,
Trying to write a little function to return all block reference ObjectIds for a specific name I began this way:
let GetBlockReferences (db : Database) (bName : string) =
use tr = db.TransactionManager.StartTransaction()
let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
if bt.Has(bName) then
let btr = tr.GetObject(bt.[bName], OpenMode.ForRead) :?> BlockTableRecord
btr.GetBlockReferenceIds(true, false)
|> Seq.cast<_>
|> Seq.filter (fun id ->
let br = tr.GetObject(id, OpenMode.ForRead)
let owner = tr.GetObject(br.OwnerId, OpenMode.ForRead) :?> BlockTableRecord
owner.IsLayout)
else Seq.empty
But:
let br = tr.GetObject(id, OpenMode.ForRead)
within the the anonymous function for Seq.filter made AutoCAD crash (fatal error).
I can solve it using a nested transaction but can't understand why it's needed.
This code works:
let GetBlockReferences (db : Database) (bName : string) =
use tr = db.TransactionManager.StartTransaction()
let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
if bt.Has(bName) then
let btr = tr.GetObject(bt.[bName], OpenMode.ForRead) :?> BlockTableRecord
btr.GetBlockReferenceIds(true, false)
|> Seq.cast<_>
|> Seq.filter (fun id ->
use trx = db.TransactionManager.StartTransaction()
let br = trx.GetObject(id, OpenMode.ForRead)
let owner = trx.GetObject(br.OwnerId, OpenMode.ForRead) :?> BlockTableRecord
owner.IsLayout)
else Seq.empty
But I don't need to use a nested transaction in the Seq.choose function of this test command:
[<CommandMethod("test")>]
let test() =
let doc = AcAp.DocumentManager.MdiActiveDocument
let db = doc.Database
let ed = doc.Editor
use tr = db.TransactionManager.StartTransaction()
tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
|> Seq.cast<_>
|> Seq.choose (fun id ->
let btr = tr.GetObject(id, OpenMode.ForRead) :?> BlockTableRecord
let name = btr.Name
if name.ToUpper().Contains("_SPACE") then None else Some name)
|> Seq.iter (fun n -> ed.WriteMessage("\n{0} = {1}", n, GetBlockReferences db n |> Seq.length))