MMPK m:n Relationships

759
2
01-25-2019 08:38 AM
MarkCederholm
Occasional Contributor III

I see that at 100.4, QueryRelatedFeaturesAsync works with m:n relationships in a MMPK, at least in one direction.  However, it still fails in the reverse direction with an "Item not found in the database" exception.  Is this known behavior?

0 Kudos
2 Replies
MarkCederholm
Occasional Contributor III

At 100.5, no m:n related features are returned at all from a mmpk. 

Now my mmpk queries are working fine in both directions.  I don't know what I was doing wrong before.

Also, querying m:n related features from a service feature table exhibits interesting behavior:

1) If a related feature is found, multiple duplicate results are returned

2) If a related feature is not found, the query throws an "Item not found in database" exception

3) Nonetheless, the query does work in both directions, M>N and N>M.

0 Kudos
MarkCederholm
Occasional Contributor III

I figured it out!!!!  QueryRelatedFeaturesAsync will not work if the FeatureLayer is a sublayer of a GroupLayer.  Here's the example code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

using Esri.ArcGISRuntime.ArcGISServices;
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.UI.Controls;

namespace RelTest
{

	static class MobileMapTest
	{

		static readonly bool bAddGroupLayers = true;

		const string sMMPKPath = @"C:\apps\FieldApp\Data";
		static readonly string[] MMPKNames = { "AZLandbase.mmpk", "AZGas.mmpk" };
		const int iMapIndex = 0;
		const int iRelID = 4; 
		const string sForwardTableName = "RegulatorStation"; 
		const int iForwardFeatureID = 2912; 

		public static async Task OpenMMPK()
		{

			// Open mobile map

			MapView mv = MainWindowModel.Current.MapViewContainerContent;
			Map MyMap = new Map();
			Viewpoint vp = null;
			foreach (string sMMPKName in MMPKNames)
			{
				string sMMPK = Path.Combine(sMMPKPath, sMMPKName);
				MobileMapPackage mmpk = await MobileMapPackage.OpenAsync(sMMPK);
				Map map = mmpk.Maps[iMapIndex];
				if (vp == null)
					vp = map.InitialViewpoint;
				LayerCollection Sublayers;
				if (bAddGroupLayers)
				{
					GroupLayer gLyr = new GroupLayer()
					{
						Name = Path.GetFileNameWithoutExtension(sMMPKName),
						Id = Guid.NewGuid().ToString(),
						IsVisible = true
					};
					MyMap.OperationalLayers.Add(gLyr);
					Sublayers = gLyr.Layers;
				}
				else
					Sublayers = MyMap.OperationalLayers;
				foreach (Layer lyr in map.OperationalLayers.ToList())
				{
					map.OperationalLayers.Remove(lyr);
					Sublayers.Add(lyr);
				}
			}
			MyMap.InitialViewpoint = vp;
			mv.Map = MyMap;
			await MyMap.LoadAsync();

		}

		public static async Task QueryTest()
		{

			// Get feature layer

			MapView mv = MainWindowModel.Current.MapViewContainerContent;
			FeatureLayer fLyr = FindLayer(mv.Map.OperationalLayers, sForwardTableName);
			if (fLyr == null)
				return;
			ArcGISFeatureTable fTab = fLyr.FeatureTable as ArcGISFeatureTable;

			// Get feature for forward test

			QueryParameters qp = new QueryParameters();
			qp.ObjectIds.Add(iForwardFeatureID);
			FeatureQueryResult queryResult = await fTab.QueryFeaturesAsync(qp);
			ArcGISFeature feat = queryResult.FirstOrDefault() as ArcGISFeature;

			// Get forward M:N relationship

			RelationshipInfo relInfo = null;
			foreach (RelationshipInfo info in fTab.LayerInfo.RelationshipInfos)
			{
				if (info.Id != iRelID)
					continue;
				relInfo = info;
				break;
			}

			// Forward related query test
			// 100.5 BUG: This will fail if the feature layer is a sublayer of a group layer

			RelatedQueryParameters param = new RelatedQueryParameters(relInfo);
			bool bForwardSuccess = true;
			IReadOnlyList<RelatedFeatureQueryResult> Results = await fTab.QueryRelatedFeaturesAsync(feat, param);
			if (Results == null)
				bForwardSuccess = false;
			else if (Results.Count == 0)
				bForwardSuccess = false;
			else
			{
				RelatedFeatureQueryResult relResult = Results.FirstOrDefault();
				bForwardSuccess = (relResult.Count() > 0);
			}
			StringBuilder sb = new StringBuilder();
			sb.Append("Query test (with");
			if (!bAddGroupLayers)
				sb.Append("out");
			sb.Append(" group layers): ");
			if (bForwardSuccess)
				sb.Append("Success");
			else
				sb.Append("Fail");
			MessageBox.Show(sb.ToString());

		}

		private static FeatureLayer FindLayer(IEnumerable<Layer> Layers, string sTableName)
		{
			foreach (Layer lyr in Layers)
			{
				if (lyr is FeatureLayer fLyr)
				{
					if (!(fLyr.FeatureTable is ArcGISFeatureTable fTab))
						continue;
					if (fTab.TableName != sTableName)
						continue;
					return fLyr;
				}
				else if (lyr is GroupLayer gLyr)
				{
					FeatureLayer fl = FindLayer(gLyr.Layers, sTableName);
					if (fl == null)
						continue;
					return fl;
				}
			}
			return null;
		}


	}

}
0 Kudos