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?
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.
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;
}
}
}