Using TableDefinition and FindField

2052
25
Jump to solution
10-15-2018 08:21 AM
BrianBulla
Occasional Contributor III

Hi,

I'm using the following code to determine if a field exists in the current layer:

var currentLayer = map.FindLayers(layer.Name).FirstOrDefault() as BasicFeatureLayer;
                        
//Does current layer have FACILITYID field??
Boolean facID_field = false;

TableDefinition tableDef = currentLayer.GetTable().GetDefinition();
if (tableDef.FindField("FACILITYID") >= 0)
      facID_field = true;

When I do not have a Join setup on the layer everything is fine, but with a Join I will get an "InvalidOperationException" error on the TableDefinition line of code:

An exception of type 'System.InvalidOperationException' occurred in ArcGIS.Core.dll but was not handled in user code

Additional information: The dataset 'SAN_Manhole_MH_dbf' does not have a valid definition.

In this case, the layername is 'SAN_Manhole' and the joined table is 'MH_dbf'.

Is there another way I should be looking for fields in a layer??  Or is there just an issue with Joined layers going on in the background.

Thanks,

1 Solution

Accepted Solutions
RichRuh
Esri Regular Contributor

Hi Brian,

I've been working on this with Uma Harano‌.  When you create a Join between two different workspaces, the join has to be computed client-side, so you cannot get a Definition from it.  When both tables exist in the same workspace, sometimes the underlying database can create a database View, which we can use to create a definition.  

There is another routine that might help you- BasicFeatureLayer.GetFieldDescriptions()

facID_field = currentLayer.GetFieldDescriptions().Any(f => f.Alias == "FACILITYID");

Should help you with the specific answer you have listed above.

I hope this helps,

--Rich

View solution in original post

25 Replies
UmaHarano
Esri Regular Contributor

Hi Brian

I ran your code to find a field in a layer that has a Join. It worked fine for me. I was able to find a field in the base layer and in the "joined" layer's fields.

Not sure why this is crashing for you.  Is there anything unique about your dataset? I used a file gdb on my local machine.

Thanks

Uma

0 Kudos
BrianBulla
Occasional Contributor III

Hi Uma,

No, nothing fancy.  My feature layer is in SDE, and the table is in the project file GDB.  I will try exporting the feature layer to the file GDB and report back.

Thanks,

0 Kudos
BrianBulla
Occasional Contributor III

OK, so with both in the same FGDB I can get past that bit of code.  Is there anything you can suggest I look for within my original setup to get things to work??

In ArcMap, I have similar code which works on the same SDE feature class and table combination.

0 Kudos
RichRuh
Esri Regular Contributor

Hi Brian,

I've been working on this with Uma Harano‌.  When you create a Join between two different workspaces, the join has to be computed client-side, so you cannot get a Definition from it.  When both tables exist in the same workspace, sometimes the underlying database can create a database View, which we can use to create a definition.  

There is another routine that might help you- BasicFeatureLayer.GetFieldDescriptions()

facID_field = currentLayer.GetFieldDescriptions().Any(f => f.Alias == "FACILITYID");

Should help you with the specific answer you have listed above.

I hope this helps,

--Rich

BrianBulla
Occasional Contributor III

Hi RRuh-esristaff‌ and UHarano-esristaff

Thanks!  That definitely helps.  Now that I have gotten past that, there is another line of code that is getting an exception, but again, only when a Join is present.  Here is a screen shot....hopefully you can help with this too:

Basically, the GetIntersectingField returns a string value to populate the DEPOTAREA field.  It only crashes when a Join is present.  Again, I'm not really sure why.  By stepping through the code the proper values are getting returned.  Manually I can do the same edit to the DEPOTAREA field through the Attributes pane without any problems.

Here is the code for the GetIntersectingField, but it seems to be working fine.  The DEPOTAREA field is associated with a domain if that makes any difference, but the code works fine with no Join present.

        //This does a SpatialQuery using the current feature point and a layer to get the intersecting field value
        public string GetIntersectingField(MapPoint point, string fieldName, FeatureLayer sourceLayer)
        {
            try
            {
                SpatialQueryFilter spatialFilter = new SpatialQueryFilter();
                spatialFilter.FilterGeometry = point;
                spatialFilter.SpatialRelationship = SpatialRelationship.Intersects;
                spatialFilter.SubFields = fieldName;

                string fieldValue = "";
                int i = 0;

                RowCursor gridCursor = sourceLayer.Search(spatialFilter);
                Feature feature;
                while (gridCursor.MoveNext())
                {
                    using (feature = (Feature)gridCursor.Current)
                    {
                        int fieldPosition = feature.FindField(fieldName);
                        fieldValue = feature[fieldPosition].ToString();
                        i++;
                    }
                }

                //if CONTRACTNO and more than one intersecting boundary, then show a message box and populate field with nothing
                if ((fieldName == "CONTRACTNO") && (i > 1))
                {
                    fieldValue = null;
                    ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("There is more than one intersecting Contract Boundary for ??.  Please enter this field in manually.", "Contract Number");
                }

                return fieldValue;
            }
            catch (Exception ex)
            {
                ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(ex.ToString());
                return null;
            }
        }
0 Kudos
RichRuh
Esri Regular Contributor

The first thing I would do is to try hard-coding an assignment to the DEPOTAREA field in code.  E.g.,

insp["DEPOTAREA"] = "value here";

Where "Value here" is a valid domain code for the depot area field.  I *think* the code is crashing on this assignment, not inside GetIntersectingField(), but this would confirm it.

Then I would check to make sure there is a field called DEPOTAREA in the result, and that the index of the field makes sense.

0 Kudos
BrianBulla
Occasional Contributor III

Hi Rich Ruh‌.  Sorry for the delay getting back to you, but I am back in the office now.

I've done some more testing, but I am still getting the same error even when hard-coding the value in as you describe above....but ONLY when I have a join on that layer.  Without a join, the same code works fine.  Is there anything else you think I should test??

0 Kudos
RichRuh
Esri Regular Contributor

Have you tried just using FeatureLayer.GetFieldDescriptions() to walk the list of fields and see which fields are available?  The only thing I can think of is that the field is being renamed because of the join.

0 Kudos
BrianBulla
Occasional Contributor III

Hi,

Using the .GetFieldDesciptions I can see that the name without the join is "DEPOTAREA" and with the join it is "GISWRKS1.WORKS.SAN_Manhole.DEPOTAREA".  But....the three lines of code before the DEPOTAREA assignment are working properly, so I'm confused as to why the DEPOTAREA field is not working.  GRIDNO, LocalMunicipality and SettlementArea are not causing me any problems.

In ArcObjects I would use this line of code to do basically the same thing, and never ran into problems related to Joins:

feature.set_Value(feature.Fields.FindField("DEPOTAREA"), UpdateByLandFeature(feature, depotAreaFLayer, "DEPOTAREA"));

Is there a recommended way for editing fields that I am not doing right??  I never know when a user may/may not have a join and I would like this to work for all instances, just like in ArcMap.

Thanks!

0 Kudos