pjm8765 发表于 2019-6-26 06:49:35

创建块后,无法向块添加属性定义

在运行以下代码后尝试保存时,我收到错误“此图形中的一个或多个对象无法保存为指定格式”。
      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 *****

n.yuan 发表于 2019-6-26 13:39:50

在我看来,在“AddMissingAttribute()”方法中,您错过了
事务。AddNewlyCreatedDBObject(属性,true)
在新属性定义附加到“jobDetailBlock”对象后。这就是为什么保存图形时会出现上述错误:新添加的属性定义未包含在事务中,因此无法保存。

pjm8765 发表于 2019-6-27 04:35:30

非常感谢,那太好了。
因此,当创建属性并将其添加到新的块表记录时,会有某种递归功能将所有新的工件添加到事务中,但当我们将它们单独添加到现有的块表记录时,这种情况不会发生。不错的不一致的设计,但我想这是意料之中的事。
请注意,我只是对AddNewlyCreatedDBObject方法中“Add”标志感到好奇,并发现了这个https://www.theswamp.org/index.php?topic=42055.0主题....那值得一笑。

MickD 发表于 2019-6-27 05:02:29

不,事务及其使用方式非常一致,所发生的情况是您正在使用AddMissingAttribute方法创建另一个内部事务,但没有使用该内部事务添加新的属性对象_或提交内部事务,因此它们不会“粘滞”。
hth

pjm8765 发表于 2019-6-27 07:13:55

与其说是交易的使用,不如说是交易。上述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;
      }

我希望看到块中的每个人工制品分别添加到事务中。这不是问题。我只是想理解其中的原因……嗯,在合理的范围内(我这样做不是为了好玩)。

MickD 发表于 2019-6-27 07:35:41

是的,我明白你的意思。
我猜
当一个块被创建/添加到db时,它会查找任何相关的属性记录,然后在通过当前事务添加块时一次将每个记录添加到属性表中。

pjm8765 发表于 2019-6-27 09:06:10

我怀疑数据库结构是这样的,理论上任何对象都可以是任何其他对象的子对象,而块、块引用和其他对象的结构是建立在其上的人工构造(有点像由解析器处理的语言的关键字)....因此这个方法递归地处理每个孩子(以及孩子的孩子,等等)。
无论如何,我已经完成了今天的学习,我将再次关闭我的大脑,继续我的工作。

n.yuan 发表于 2019-6-27 10:03:31


好吧,当您创建一个新的复合DBObject时,例如BlockTableRecord,或带有属性引用的BlockAudi,有两种方法可以将其添加到事务中:
1。您可以创建它的新实例,然后向它们添加子对象。然后您将复合对象添加/附加到数据库的适当所有者,您只需要将此复合对象添加到事务中,而不是其中的每个子对象。
2.您可以创建新的复合对象,将其添加/附加到DB中的适当所有者,然后将其添加到事务中(此时,新的复合对象已成为DB-驻留对象,但您仍然可以通过中止事务来重新跟踪,当然)。现在,您可以将子对象添加到复合对象中,如您所见,对于新添加的子对象,它们需要添加到事务中。
在创建新的复合对象时,使用方法1.将是最自然、最合乎逻辑的,但我确实看到代码不时使用方法2(包括我自己)。在您的情况下,由于您正在向现有的、驻留在DB中的复合对象(BlockTableRecord,这意味着当复合对象在事务中打开时,它本身和它中的所有子对象都在事务中)添加子对象(属性定义),因此您尝试添加的新对象必须添加到事务中(即方法2)。
我们可能会想(正如您所描述的),既然它已经在事务中,为什么欧特克不在添加/附加到复合对象时自动将新的子对象添加到事务中?好吧,考虑方法名称:AddNewlyCreatedDBObject(),它不仅将对象添加到事务中,还将它们标记为“新添加的”,这样如果您想回滚,只有新添加的对象才会从DB驻留的复合对象中删除。
页: [1]
查看完整版本: 创建块后,无法向块添加属性定义