创建块后,无法向块添加属性定义
在运行以下代码后尝试保存时,我收到错误“此图形中的一个或多个对象无法保存为指定格式”。private void EnsureJobHasAllAttrbuteDefinitions()
{
Document thisDrawing = null;
BlockTable blockTable;
ObjectId jobDetailsBlockObjectId;
try
{
thisDrawing = AutoCADUtility.GetDocument();
using (Transaction transaction = thisDrawing.Database.TransactionManager.StartTransaction())
{
blockTable = transaction.GetObject(thisDrawing.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
if (blockTable.Has(BlockNames.JobDetails))
{
jobDetailsBlockObjectId = blockTable;
AddMissingAttribute(jobDetailsBlockObjectId, JobDetailsBlockAttribute.Contractor);
AddMissingAttribute(jobDetailsBlockObjectId, JobDetailsBlockAttribute.Merchant);
AddMissingAttribute(jobDetailsBlockObjectId, JobDetailsBlockAttribute.ProjectName);
AddMissingAttribute(jobDetailsBlockObjectId, JobDetailsBlockAttribute.DrawingName);
AddMissingAttribute(jobDetailsBlockObjectId, JobDetailsBlockAttribute.WideWalls);
AddMissingAttribute(jobDetailsBlockObjectId, JobDetailsBlockAttribute.Depot);
}
transaction.Commit();
}
}
catch (Exception ex)
{
MessageBox.Show("Job.EnsureJobHasAllAttrbuteDefinitions : " + ex.Message, MessageHeadings.ExceptionError);
}
}
private void AddMissingAttribute(ObjectId jobDetailsBlockObjectId, string attributeName)
{
Document thisDrawing;
Transaction transaction;
AttributeDefinition attribute;
BlockTableRecord jobDetailsBlock;
bool attributeExists = false;
try
{
thisDrawing = AutoCADUtility.GetDocument();
transaction = thisDrawing.Database.TransactionManager.TopTransaction;
jobDetailsBlock = transaction.GetObject(jobDetailsBlockObjectId, OpenMode.ForRead) as BlockTableRecord;
if (jobDetailsBlock.HasAttributeDefinitions)
{
foreach (ObjectId entity in jobDetailsBlock)
{
DBObject entityObject = transaction.GetObject(entity, OpenMode.ForRead) as DBObject;
if (entityObject is AttributeDefinition)
{
attribute = entityObject as AttributeDefinition;
if (attribute.Tag == attributeName)
{
attributeExists = true;
}
}
}
}
if (attributeExists == false)
{
//If the attribute has not been found, add it
attribute = new AttributeDefinition(new Point3d(0, 510, 0), "", attributeName, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = false;
attribute.Layer = "0";
attribute.ColorIndex = 256; //Color by layer
jobDetailsBlock.UpgradeOpen();
jobDetailsBlock.AppendEntity(attribute);
}
}
catch (Exception ex)
{
MessageBox.Show("Job.AddMissingAttribute : " + ex.Message, MessageHeadings.ExceptionError);
}
}
我这样做是因为我有额外的属性,我已经添加到一个块中,我需要确保较旧的图形使用这些属性更新这个块。
**** Hidden Message ***** 在我看来,在“AddMissingAttribute()”方法中,您错过了
事务。AddNewlyCreatedDBObject(属性,true)
在新属性定义附加到“jobDetailBlock”对象后。这就是为什么保存图形时会出现上述错误:新添加的属性定义未包含在事务中,因此无法保存。 非常感谢,那太好了。
因此,当创建属性并将其添加到新的块表记录时,会有某种递归功能将所有新的工件添加到事务中,但当我们将它们单独添加到现有的块表记录时,这种情况不会发生。不错的不一致的设计,但我想这是意料之中的事。
请注意,我只是对AddNewlyCreatedDBObject方法中“Add”标志感到好奇,并发现了这个https://www.theswamp.org/index.php?topic=42055.0主题....那值得一笑。 不,事务及其使用方式非常一致,所发生的情况是您正在使用AddMissingAttribute方法创建另一个内部事务,但没有使用该内部事务添加新的属性对象_或提交内部事务,因此它们不会“粘滞”。
hth
与其说是交易的使用,不如说是交易。上述AddMissingAttribute例程中的AddNewlyCreatedObject方法,作为其在首先创建属性定义时的使用:
private ObjectId CreateEasiBaseBlock(EasiBaseProperties easiBaseProperties)
{
ObjectId blockId = ObjectId.Null;
Document thisDrawing;
BlockTable blockTable;
Transaction transaction;
Circle innerCircle;
Circle outerCircle;
AttributeDefinition attribute;
try
{
thisDrawing = AutoCADUtility.GetDocument();
transaction = thisDrawing.Database.TransactionManager.TopTransaction;
blockTable = transaction.GetObject(thisDrawing.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
using (BlockTableRecord blockTableRecord = new BlockTableRecord())
{
blockTableRecord.Name = BlockNames.EasiBase;
// Insert the block near 0,0,0 but not on it
blockTableRecord.Origin = new Point3d(0, 1000, 0);
// Add inner circle to the block
innerCircle = new Circle();
innerCircle.Center = new Point3d(0, 1000, 0);
innerCircle.Radius = 600;
innerCircle.Layer = LayerNames.EasiBase;
innerCircle.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(innerCircle);
// Add inner circle to the block
outerCircle = new Circle();
outerCircle.Center = new Point3d(0, 1000, 0);
outerCircle.Radius = 650;
outerCircle.Layer = LayerNames.EasiBase;
outerCircle.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(outerCircle);
//Add the attributes
attribute = new AttributeDefinition(new Point3d(0, 1800, 0), "", EasiBaseBlockAttribute.SiteRef, EasiBaseBlockAttribute.SiteRef, ObjectId.Null);
attribute.Height = 80;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 1000, 0), "", EasiBaseBlockAttribute.EasiBaseSizeId, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 999, 0), "", EasiBaseBlockAttribute.CoverLevel, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 998, 0), "", EasiBaseBlockAttribute.InvertLevel, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 997, 0), "", EasiBaseBlockAttribute.OverallPREDLReference, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 996, 0), "", EasiBaseBlockAttribute.MouldTypeId, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 995, 0), "", EasiBaseBlockAttribute.SteelRingDepthId, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 994, 0), "", EasiBaseBlockAttribute.NumberOfSeatingRings, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 993, 0), "", EasiBaseBlockAttribute.CoverSlabDepthId, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 992, 0), "", EasiBaseBlockAttribute.NumberOf250Rings, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 991, 0), "", EasiBaseBlockAttribute.NumberOf500Rings, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 990, 0), "", EasiBaseBlockAttribute.NumberOf750Rings, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 989, 0), "", EasiBaseBlockAttribute.NumberOf1000Rings, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
attribute = new AttributeDefinition(new Point3d(100, 990, 0), "", EasiBaseBlockAttribute.EasiBaseId, "", ObjectId.Null);
attribute.Height = 0.5;
attribute.Visible = true;
attribute.Layer = LayerNames.EasiBase;
attribute.ColorIndex = 256; //Color by layer
blockTableRecord.AppendEntity(attribute);
//Add the block to the record
blockTable.UpgradeOpen();
blockTable.Add(blockTableRecord);
transaction.AddNewlyCreatedDBObject(blockTableRecord, true);
blockId = blockTableRecord.Id;
}
}
catch (Exception ex)
{
MessageBox.Show("EasiBase.CreateEasiBaseBlock : " + ex.Message, MessageHeadings.ExceptionError);
}
return blockId;
}
我希望看到块中的每个人工制品分别添加到事务中。这不是问题。我只是想理解其中的原因……嗯,在合理的范围内(我这样做不是为了好玩)。
是的,我明白你的意思。
我猜
当一个块被创建/添加到db时,它会查找任何相关的属性记录,然后在通过当前事务添加块时一次将每个记录添加到属性表中。
我怀疑数据库结构是这样的,理论上任何对象都可以是任何其他对象的子对象,而块、块引用和其他对象的结构是建立在其上的人工构造(有点像由解析器处理的语言的关键字)....因此这个方法递归地处理每个孩子(以及孩子的孩子,等等)。
无论如何,我已经完成了今天的学习,我将再次关闭我的大脑,继续我的工作。
好吧,当您创建一个新的复合DBObject时,例如BlockTableRecord,或带有属性引用的BlockAudi,有两种方法可以将其添加到事务中:
1。您可以创建它的新实例,然后向它们添加子对象。然后您将复合对象添加/附加到数据库的适当所有者,您只需要将此复合对象添加到事务中,而不是其中的每个子对象。
2.您可以创建新的复合对象,将其添加/附加到DB中的适当所有者,然后将其添加到事务中(此时,新的复合对象已成为DB-驻留对象,但您仍然可以通过中止事务来重新跟踪,当然)。现在,您可以将子对象添加到复合对象中,如您所见,对于新添加的子对象,它们需要添加到事务中。
在创建新的复合对象时,使用方法1.将是最自然、最合乎逻辑的,但我确实看到代码不时使用方法2(包括我自己)。在您的情况下,由于您正在向现有的、驻留在DB中的复合对象(BlockTableRecord,这意味着当复合对象在事务中打开时,它本身和它中的所有子对象都在事务中)添加子对象(属性定义),因此您尝试添加的新对象必须添加到事务中(即方法2)。
我们可能会想(正如您所描述的),既然它已经在事务中,为什么欧特克不在添加/附加到复合对象时自动将新的子对象添加到事务中?好吧,考虑方法名称:AddNewlyCreatedDBObject(),它不仅将对象添加到事务中,还将它们标记为“新添加的”,这样如果您想回滚,只有新添加的对象才会从DB驻留的复合对象中删除。
页:
[1]