Author Topic: PropertyDataServices.PropertyExists uses  (Read 5737 times)

0 Members and 1 Guest are viewing this topic.

MexicanCustard

  • Swamp Rat
  • Posts: 705
PropertyDataServices.PropertyExists uses
« on: September 24, 2012, 03:56:14 PM »
Just wondering if anyone has used PropertyDataServices.PropertyExists in ACA/MEP.

Definition per AecPropDataMgd:
public static ObjectId PropertyExists(Database db, String fullPropertyName, out Int32& propertyId);

So how do I know if the property exists?  Will the returned ObjectId be ObjectId.Null or does the value of propertyId represent the existence of the property?  I tried using this where I knew the property didn't exist and it threw an exception error.

Right now the only way I know to find out if the property exist on a DBObject is to exception trap and I hate doing that.
Code - C#: [Select]
  1. var psDict = new DictionaryPropertySetDefinitions(fitting.Database);
  2. var psdId = psDict.GetAt("MyProperty");
  3. PropertySet pSet;
  4. try
  5. {
  6.     var setId = PropertyDataServices.GetPropertySet(fitting, psdId);
  7.     pSet = (PropertySet)setId.GetObject(OpenMode.ForRead, false, true);
  8. }
  9. catch (Exception)
  10. {
  11.     ed.WriteMessage("\nProperty doesn't exist");
  12. }
Revit 2019, AMEP 2019 64bit Win 10

BlackBox

  • King Gator
  • Posts: 3770
Re: PropertyDataServices.PropertyExists uses
« Reply #1 on: September 24, 2012, 04:22:30 PM »
Silly question... Total stab in the dark here (just trying to learn).

Couldn't you declare an *Exception Property in your Class, then in your 'check' Method return true if the property exists, or use the Catch block to store the Exception Object in this Property, and return false to the calling Method, which includes a finally block to handle the Exception (if != null)?  :?
"How we think determines what we do, and what we do determines what we get."

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: PropertyDataServices.PropertyExists uses
« Reply #2 on: September 25, 2012, 09:15:35 AM »
Silly question... Total stab in the dark here (just trying to learn).

Couldn't you declare an *Exception Property in your Class, then in your 'check' Method return true if the property exists, or use the Catch block to store the Exception Object in this Property, and return false to the calling Method, which includes a finally block to handle the Exception (if != null)?  :?

Yeah, thats kind of what I've done. This code snippet is in a property of a static class that I call and return the value of the property or return null.  Then I check the return value for null.

I just don't like using exception trapping to find out if a value exist or not.  IMO its bad programming for Autodesk not to provide a way to check its existence in the API.
Revit 2019, AMEP 2019 64bit Win 10

BlackBox

  • King Gator
  • Posts: 3770
Re: PropertyDataServices.PropertyExists uses
« Reply #3 on: September 25, 2012, 10:27:41 AM »
Sorry I could not be of any help.
"How we think determines what we do, and what we do determines what we get."

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: PropertyDataServices.PropertyExists uses
« Reply #4 on: September 25, 2012, 12:43:02 PM »
Sorry I could not be of any help.

Hey, thanks for trying.  Looks like no one else knows how its suppose to work either.
Revit 2019, AMEP 2019 64bit Win 10

Jeff H

  • Needs a day job
  • Posts: 6150
Re: PropertyDataServices.PropertyExists uses
« Reply #5 on: September 25, 2012, 12:49:22 PM »
Seems familar and will try to see if I can find an example but I gave up on ACA/MEP API since Autodesk gave up on it.

BlackBox

  • King Gator
  • Posts: 3770
Re: PropertyDataServices.PropertyExists uses
« Reply #6 on: September 25, 2012, 03:05:09 PM »
Seems familar and will try to see if I can find an example but I gave up on ACA/MEP API since Autodesk gave up on it.

As it happens, my manager wanted to know that we already have the AMEP software we'd need for this project he was just brought into as a sub... Mind you, we're now seeking some internal training on the product, as we've never used it for production (we normally use Civil 3D)... So the fact that the MEP API isn't as novice developer friendly as the Civil 3D API :roll:, is excellent to hear. 

:-D
"How we think determines what we do, and what we do determines what we get."

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: PropertyDataServices.PropertyExists uses
« Reply #7 on: September 26, 2012, 07:56:26 AM »
The new post over at the AEC Developer Blog is how to add a PropertySet to an object.  I posted a comment over there asking how to test if an object has a PropertySet.  I'll post any response they give me in here.
Revit 2019, AMEP 2019 64bit Win 10

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: PropertyDataServices.PropertyExists uses
« Reply #8 on: October 29, 2012, 10:36:32 PM »
MexicanCustard,

Did you ever find a solution to this problem?  I am trying to create a utility to attach property sets to objects automatically and I would like to check if the property set exists before adding the property set.  Below is the code that I have so far (mainly a reprint from the sample file).

Code - C#: [Select]
  1.  
  2.             /// <summary>
  3.             /// Creates a property set on a given object.
  4.             /// </summary>
  5.             /// <param name="objObjectId">The objectID of the object to create the property set on.</param>
  6.             /// <param name="PropertySetObjectId">The objectID of the property set to create on the object </param>
  7.             /// <returns> True if the property set was created on the object, or false if there was a failure. </returns>
  8.             public bool CreatePropertySetOnObject(ObjectId objObjectId, ObjectId PropertySetObjectId)
  9.             {
  10.                 Database db = HostApplicationServices.WorkingDatabase;
  11.                 AcadDb.TransactionManager tm = db.TransactionManager;
  12.                 using (Transaction trans = tm.StartTransaction())
  13.                 {
  14.                     // Try to attach the property set to the object.
  15.                     try
  16.                     {
  17.                         // First check to see if the property set already exists on the object
  18.                         // ADD CODE HERE TO CHECK AND SEE IF PROPERTY SET ALREADY EXISTS
  19.                        
  20.                         // Get the object, open it for write and then attach the property set
  21.                         AcadDb.DBObject dbobj = tm.GetObject(objObjectId, OpenMode.ForWrite, false, false);
  22.                         AecPropDb.PropertyDataServices.AddPropertySet(dbobj, PropertySetObjectId);
  23.                     }  // End Try Block
  24.  
  25.                     // If there is an error catch it and return false
  26.                     catch (Autodesk.AutoCAD.Runtime.Exception)
  27.                     {
  28.                         return false;
  29.                     }  // end Catch Block
  30.  
  31.                     // At this point the property set was successfully attached so commit the transaction
  32.                     trans.Commit();
  33.                 }  // end Try-Catch Block
  34.  
  35.                 // The property set has been attached and the transaction committed
  36.                 // So we can finish up and return true
  37.                 return true;
  38.  
  39.             }  // End CreatePropertySetOnObject Method
  40.  
  41.  
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: PropertyDataServices.PropertyExists uses
« Reply #9 on: October 30, 2012, 09:57:41 AM »
Keith, I did not find a better solution.  I am still encapsulating .GetPropertySet within a try/catch. Wish I had better news.
Revit 2019, AMEP 2019 64bit Win 10

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: PropertyDataServices.PropertyExists uses
« Reply #10 on: October 30, 2012, 11:16:10 AM »
Thanks.  I will go ahead and try that method.  Is it possible to have a try-catch inside of a try-catch or do I just need to catch the specific error that will arise from the .getpropertyset in my main catch block?
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: PropertyDataServices.PropertyExists uses
« Reply #11 on: October 30, 2012, 01:18:16 PM »
Thanks.  I will go ahead and try that method.  Is it possible to have a try-catch inside of a try-catch or do I just need to catch the specific error that will arise from the .getpropertyset in my main catch block?

Yes, you can have try/catch nested.  So put a try/catch just around .GetPropertySet and catch Autodesk.Runtime.Exception.  That should trap it and not affect your "real" try/catch block.
Revit 2019, AMEP 2019 64bit Win 10

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: PropertyDataServices.PropertyExists uses
« Reply #12 on: October 30, 2012, 10:37:12 PM »
I thought I would post my solution for anyone that is interested and wants to critique it.  I am always open for suggestions.

Code - C#: [Select]
  1. Namespace MEPUtilities
  2. {
  3.  
  4.     /// <summary>
  5.     /// A collection of methods related to property sets.
  6.     /// </summary>
  7.     public static class PropertySetUtilities
  8.     {
  9.  
  10.         /// <summary>
  11.         /// Finds a property set by its ObjectId on a given object.
  12.         /// </summary>
  13.         /// <param name="dbobj">The object to find the property set on.</param>
  14.         /// <param name="PropertySetId">The property set ObjectId to find on the object.</param>
  15.         /// <returns> True if the property set with the given ObjectId was found, or false otherwise. </returns>
  16.         public static bool IsPropertySetAttachedToObject(AcadDb.DBObject dbobj, ObjectId PropertySetId)
  17.         {
  18.  
  19.             // Create and set a temporary ObjectID to Null
  20.             ObjectId psId = ObjectId.Null;
  21.  
  22.             try
  23.             {
  24.                 // Attempt to set the temporary ObjectID equal to the objectID of the
  25.                 // of the property set we are attempting to find on the object.
  26.                 // If the property set exists on the object then the temporary ObjectId
  27.                 // will be assigned a value
  28.                 psId = AecPropDb.PropertyDataServices.GetPropertySet(dbobj, PropertySetId);
  29.             } // End Try Block
  30.  
  31.             // If the property set does not exist on the object then an error will be raised
  32.             catch (Autodesk.AutoCAD.Runtime.Exception)
  33.             {
  34.                 // More than likely eKeyNotFound, so this is a more specific
  35.                 // place to handle a "failed to find" condition.
  36.             } // End Catch Block
  37.  
  38.             // If the temp ObjectId is not null then we found the property set on the object
  39.             if (!psId.IsNull)
  40.                 return true;
  41.  
  42.             // If we are at this point then the property set was not found on the object
  43.             // and we can return false.
  44.             return false;
  45.  
  46.         } // End IsPropertySetAttachedToObject Method
  47.  
  48.         /// <summary>
  49.         /// Creates a property set on a given object.
  50.         /// Requires that the property set exists in the current database and
  51.         /// that the property set applies to the object.
  52.         /// </summary>
  53.         /// <param name="objObjectId">The objectID of the object to create the property set on.</param>
  54.         /// <param name="PropertySetObjectId">The objectID of the property set to create on the object </param>
  55.         /// <returns> True if the property set was created on the object, or false if there was a failure. </returns>
  56.         public static bool CreatePropertySetOnObject(ObjectId objObjectId, ObjectId PropertySetId)
  57.         {
  58.             Database db = Application.DocumentManager.MdiActiveDocument.Database;
  59.             AcadDb.TransactionManager tm = db.TransactionManager;
  60.             using (Transaction trans = tm.StartTransaction())
  61.             {
  62.                 // Try to attach the property set to the object.
  63.                 try
  64.                 {
  65.                     // First check to see if the property set already exists on the object
  66.                        
  67.                     // create a database object based on the ObjectId of the object
  68.                     AcadDb.Entity dbObject = (AcadDb.Entity)tm.GetObject(objObjectId, OpenMode.ForRead, true);
  69.                      
  70.                     // Check to see if the property set is already attached to the object
  71.                     if (!IsPropertySetAttachedToObject(dbObject, PropertySetId))
  72.                     {
  73.                         // Attach the property set to the object
  74.                         AcadDb.DBObject dbobj = tm.GetObject(objObjectId, OpenMode.ForWrite, false, false);
  75.                         AecPropDb.PropertyDataServices.AddPropertySet(dbobj, PropertySetId);
  76.                     } // End If Block
  77.                 }  // End Try Block
  78.  
  79.                 // If there is an error catch it and return false
  80.                 catch (Autodesk.AutoCAD.Runtime.Exception)
  81.                 {
  82.                     return false;
  83.                 }  // End Catch Block
  84.  
  85.                 // At this point the property set was successfully attached so commit the transaction
  86.                 trans.Commit();
  87.             }  // End Try-Catch Block
  88.  
  89.             // The property set has been attached and the transaction committed
  90.             // So we can finish up and return true
  91.             return true;
  92.  
  93.         }  // End CreatePropertySetOnObject Method
  94.     }  // End PropertySetUtilities Class
  95. } // End MEPUtilities Namespace

And now my test command.

Code - C#: [Select]
  1.     [CommandMethod("CreatePipeObjectPropertySetonObject")]
  2.     public void Command_CreatePipeObjectPropertySetOnObject()
  3.     {
  4.         Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  5.         try
  6.         {
  7.             PromptEntityOptions EntOpts = new PromptEntityOptions("\r\nSelect an entity to add the pipeobject property set to: ");
  8.             PromptEntityResult Ent = null;
  9.             try
  10.             {
  11.                 Ent = ed.GetEntity(EntOpts);
  12.             }
  13.             catch
  14.             {
  15.                 ed.WriteMessage("\r\nPlease select a valid entity");
  16.                 return;
  17.             }
  18.  
  19.             if (Ent.Status != PromptStatus.OK)
  20.                 return;
  21.  
  22.             ObjectId PropertySetId = MEPUtilities.PropertySetUtilities.GetPropertySetDefinitionIdByName("pipeobject");
  23.             if (PropertySetId.IsNull)
  24.             {
  25.                 ed.WriteMessage("\r\nThere are no pipeobject property sets");
  26.                 return;
  27.             }
  28.             ObjectId EntId = Ent.ObjectId;
  29.  
  30.             if (MEPUtilities.PropertySetUtilities.CreatePropertySetOnObject(EntId, PropertySetId))
  31.                 ed.WriteMessage("\r\nSuccessfully created pipeobject property set");
  32.             else
  33.                 ed.WriteMessage("\r\nUnable to create pipeobject property set on object");
  34.         }
  35.         catch (Autodesk.AutoCAD.Runtime.Exception)
  36.         {
  37.         }
  38.     }
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: PropertyDataServices.PropertyExists uses
« Reply #13 on: October 31, 2012, 11:09:45 AM »
Thats pretty much how I've been doing it.
Revit 2019, AMEP 2019 64bit Win 10