ThinkGeo.com    |     Documentation    |     Premium Support

EditTools.CommitTransaction IComparer Crash

I am getting a crash upon CommitTransaction on an InMemoryFeatureLayer.  I am adding 34 features to the layer one after the other and receive this crash on the same five records each time I attempt to add them.  Odd thing is that even though the CommitTransaction crashes these five records are still in the layer even though a Rollback Transaction is invoked.


The keys of all 34 records are unique, but they are being added out of sort sequence.


These crashes only occur when running in non-debug mode.  Running in VS2010 debug they do not occur.


Below is the .NET error.


Any ideas on what the cause of this might be?  I have debugged for several days now and cannot find any issues with my code per se.


Any words of advice are appreciated.


Regards,


Dennis


 



Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. x: 'GisSharpBlog.NetTopologySuite.Index.Strtree.STRtree+AnonymousAbstractNodeImpl', x's type: 'AnonymousAbstractNodeImpl', IComparer: 'GisSharpBlog.NetTopologySuite.Index.Strtree.STRtree+AnonymousYComparerImpl'.




 Hi Dennis,


 


We can't recreate your problem in our side, could you please provide us a self-contained sample that can recreate your problem?


 


Here is the sample code we tested:



        private void WpfMap_Loaded(object sender, RoutedEventArgs e)

        {

            Map1.MapUnit = GeographyUnit.DecimalDegree;

            InMemoryFeatureLayer inmLayer = new InMemoryFeatureLayer();

            inmLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.Capital1;

            inmLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

            inmLayer.Open();

            inmLayer.FeatureSource.BeginTransaction();

 

            for (int i = 0; i < 35; i++)

            { inmLayer.FeatureSource.AddFeature(new Feature(i, i)); }

            inmLayer.FeatureSource.RollbackTransaction();

            inmLayer.FeatureSource.CommitTransaction();

 

            LayerOverlay layerOverlay = new LayerOverlay();

            layerOverlay.Layers.Add(inmLayer);

 

            Map1.CurrentExtent = inmLayer.GetBoundingBox();

            Map1.Overlays.Add(layerOverlay);

 

            Map1.Refresh();

        }

Gary



Gary,


My code is a bit more complex.  


This is how the columns are defined:



 



// add columns

fscColumn =


 


fscColumn =


 


fscColumn =


 



new FeatureSourceColumn("KeySymbol", "string", 116);this.TrackingLayer.Columns.Add(fscColumn);new FeatureSourceColumn("KeyItem", "string", 32);this.TrackingLayer.Columns.Add(fscColumn);new FeatureSourceColumn("Label", "string", 48);this.TrackingLayer.Columns.Add(fscColumn);

Example Key -- 01FDCF750E75000000000000000000



Example Key -- 01FEMA000EMA600000000000000000



 


 


Here is how the feature is created:



oTracking.ItemPoint =


oTracking.ItemPoint.Id = oTracking.sKey;


myFeature =


myFeature.ColumnValues.Add(


myFeature.ColumnValues.Add(


myFeature.ColumnValues.Add(



new PointShape(myVertex.X, myVertex.Y);new Feature(oTracking.ItemPoint);"Label", oTracking.sLabel );"KeyItem", oTracking.sKey );"KeySymbol", oTrackingLayerSymbol.sKey);

It would seem that the EditTools.Add and EditTools.CommitTransaction methods are doing some behind-the-scenes sorting as evidenced by the crash of the IComparer.


Your example code does not appear to make use of the 'Id' property in the PointShape.


My code does a separate Open, BeginTransaction, Add, CommitTransaction, Close for each of the features.  The features are being passed individually in real-time from an outside source and I do not know how many there will be which is why it is done this way.  There are no map refreshes that are done while all these are added.


 


Your thoughts?


Dennis


 




Gary,


your website corrupted the code i pasted so attached is a file with the code snippets.


Dennis


 



InMemoryFeatureLayerSnippets.txt (1.46 KB)

 Hi Dennis,


 We have tested with the code you provided, but we still didn’t recreate your problem, here is our test code:



        private void WpfMap_Loaded(object sender, RoutedEventArgs e)

        {

            // create layer

            InMemoryFeatureLayer TrackingLayer = new InMemoryFeatureLayer();

            TrackingLayer.Open();

            TrackingLayer.Name = "TrackingLayerName";

 

            TrackingLayer.DrawingExceptionMode = DrawingExceptionMode.DrawException;

            //TrackingLayer.DrawnException += new EventHandler<DrawnExceptionLayerEventArgs>(TrackingLayer_DrawnException);

 

            FeatureSourceColumn fscColumn1 = new FeatureSourceColumn("KeySymbol", "string", 116);

            FeatureSourceColumn fscColumn2 = new FeatureSourceColumn("KeyItem", "string", 32);

            FeatureSourceColumn fscColumn3 = new FeatureSourceColumn("Label", "string", 48);

            TrackingLayer.Columns.Add(fscColumn2);

            TrackingLayer.Columns.Add(fscColumn1);

            TrackingLayer.Columns.Add(fscColumn3);

 

            TrackingLayer.BuildIndex();

            TrackingLayer.Close();

 

            //Create 34 features

            Collection<Feature> features = new Collection<Feature>();

            for (int i = 0; i < 34; i++)

            {

                PointShape point = new PointShape(i, i);

                Feature myFeature = new Feature(point);

                point.Id = i.ToString();

                myFeature.ColumnValues.Add("Label", "label" + i.ToString());

                myFeature.ColumnValues.Add("KeyItem", "KeyItem" + i.ToString());

                myFeature.ColumnValues.Add("KeySymbol", "KeySymbol" + i.ToString());

                features.Add(myFeature);

            }

 

            //use edittool to add 34 features

            foreach (Feature feature in features)

            {

                TrackingLayer.Open();

                TrackingLayer.EditTools.BeginTransaction();

                TrackingLayer.FeatureSource.AddFeature(feature);

                TrackingLayer.EditTools.CommitTransaction();

                TrackingLayer.Close();

            }

            MessageBox.Show("add successed");

        }

Regards, 


Gary



hi Gary,


I see that your sample code uses:


    TrackingLayer.FeatureSource.AddFeature(feature);




Where my code uses:


    TrackingLayer.EditTools.Add(feature);


What is the difference between these two methodologies?

 


Regards,


Dennis


 



Hi Dennis, 
  
 They are the same, because inside TrackingLayer.EditTools.add(feature), it will call TrackingLayer.FeatureSource.AddFeature(feature). 
  
 Hope it helps 
  
 Gary 


Gary,


I changed my code to make use of the AddFeature method with the same results, which according to your explanation would make sense.


Couple observations on this issue...


This is a MapSuite crash as I have try/catch logic around the EditTools.CommitTransaction and it is trapped.  In my opinion MapSuite should never crash.


The TransactionResult always returns a status of Succes, the FailureCount and SuccessCount are always 0, which makes no sense as one of them should be a 1.  And the FailureReasons collection is also always empty.


The CommitTransaction method is attempting some kind of sorting in its own collection and is encountering an error, so what's it attempting to do and why does it not trap its own error?


Dennis


 


 



 Hi Dennis,


Sorry, we tried what you described but still didn’t recreate your problem, could you please provide us a self-contained sample to recreate?


Here is the sample code we tested



private void WpfMap_Loaded(object sender, RoutedEventArgs e)

        {

            // create layer

            InMemoryFeatureLayer TrackingLayer = new InMemoryFeatureLayer();

            TrackingLayer.Open();

            TrackingLayer.Name = "TrackingLayerName";

 

            TrackingLayer.DrawingExceptionMode = DrawingExceptionMode.DrawException;

            //TrackingLayer.DrawnException += new EventHandler<DrawnExceptionLayerEventArgs>(TrackingLayer_DrawnException);

 

            FeatureSourceColumn fscColumn1 = new FeatureSourceColumn("KeySymbol", "string", 116);

            FeatureSourceColumn fscColumn2 = new FeatureSourceColumn("KeyItem", "string", 32);

            FeatureSourceColumn fscColumn3 = new FeatureSourceColumn("Label", "string", 48);

            TrackingLayer.Columns.Add(fscColumn2);

            TrackingLayer.Columns.Add(fscColumn1);

            TrackingLayer.Columns.Add(fscColumn3);

 

            TrackingLayer.BuildIndex();

            TrackingLayer.Close();

 

            //Create 34 features

            Collection<Feature> features = new Collection<Feature>();

            for (int i = 0; i < 34; i++)

            {

                PointShape point = new PointShape(i, i);

                Feature myFeature = new Feature(point);

                point.Id = i.ToString();

                myFeature.ColumnValues.Add("Label", "label" + i.ToString());

                myFeature.ColumnValues.Add("KeyItem", "KeyItem" + i.ToString());

                myFeature.ColumnValues.Add("KeySymbol", "KeySymbol" + i.ToString());

                features.Add(myFeature);

            }

 

            //use edittool to add 34 features

            foreach (Feature feature in features)

            {

                TrackingLayer.Open();

                TrackingLayer.EditTools.BeginTransaction();

                TrackingLayer.FeatureSource.AddFeature(feature);

                try

                {

                    TransactionResult result = TrackingLayer.EditTools.CommitTransaction();

                    Debug.WriteLine("SuccessCount:" + result.TotalSuccessCount + "/////" + "FailureCount:" + result.TotalFailureCount.ToString());

                }

                catch (Exception ex)

                { MessageBox.Show("there is a exception"); }

                TrackingLayer.Close();

            }

            MessageBox.Show("add successed");

        }

Regards, 


Gary



Gary,


This is a timing related issue and as I said in my initial post these problems do not occur while running in the VS2010 debugger.


I doubt very much you will be able to recreate this problem with simple test code.


I'd like to see this passed on to MapSuite engineers.


My application is, as most are, rather complex with lots of things going on.  I will attempt to put together some sample code using real-life data.


Regards,


Dennis


 



Hello Dennis, 



We have tested in vs11,vs2008 and vs2010, we still don’t see your problem, we have to recreate the problem before resolve the problem, is that possible you can give a video and your data?  You can send to forumsupport@thinkgeo.com



Sorry for the inconvenience. 



Gary



Gary,


I am attempting to put together a standalone application that has the same crash that I can send to you.  It may take me another day however.


I prefer to email it to you.  Do you have an email address so I can do that?


Regards,


Dennis


 



 Hello Dennis,


 
Thanks for your help, you can send to forumsupport@thinkgeo.com, only the support guy can get this email and all your code will be private.
 
Regards,
 
Gary

Gary, 
  
 We are having exactly the same problem, although we are using the WinForms edition of MapSuite. And, as described above, we can only reproduce the bug outside the VS 2010 ide. Did you guys ever discover a solution? 
  
 Thanks, 
  
 Steve

Hi Steven, 
  
 Thanks for your post, but sorry to say that we haven’t received a sample and didn’t recreate the problem for a long time, would you please provide us a sample to recreate the problem? 
  
 Thanks, 
 Edgar

Johnny,


I struggle when asked for sample code from the MapSuite Team.  Mine is a real-world application that is highly integrated.  For example, my code is not simple straight-line code that loads layers and sets styles, etc.  All setting of layers, styles, icons, etc are done through a set of configuration tables.  It is nearly impossible to provide sample code.  I would have to send you my entire application, configuration, and data layers.


The CommitTransaction and DrawnException I had in the past and was able to code-around and prevent these errors.  On my original post MapSuite had asked for sample code and at the time I had attempted to provide, but was unable.


How else can we attack these issues?  For example, on the DrawnException it states 'Destination array was not long enough. Check destIndex and length, and the array's lower bounds'  It seems to me that this is some error within MapSuite and is out of application control.  Or is there some property of the InMemoryFeature Layer that has to be set to ensure that interal arrays are large enough?


And the .NET exception that I received is not in the application, but somewhere in MapSuite.


Thanks,


Dennis


 



 Hi Steven and Dennis,



Thanks for the detailed information and sorry for the delay.


Just checking the stack trace shown in the first post of this thread, I guess the problem should come from the “BuildIndex()” method of InMemoryFeatureSource, because here is the only place we use the NTS, where the exception comes from.  So there are 2 options for you guys:


1.Use the code as following to avoid the “BuildIndex()” methods, but it will make the InMemoryFeatureLayer work without built-in index. In other words, if you would like to load huge data into it, the query will become slower. Following is the code that you can try:


 


            foreach (Feature feature in features)


            {


                TrackingLayer. InternalFeatures.Add(feature);


            }


2. Use a varietas of #1 option, still add the feature following the code shown in #1, but outside of “foreach”, we call “TrackingLayer.BuildIndex()” manually, it make the InMemoryFeatureLayer work with index as well. But I’m not sure whether you guys will have the same problem when doing the “BuildIndex()”, but anyway, you can catch “BuildIndex()” method’s exception by yourself to check its detailed information. If you get it, please send the detailed more information to me.



 


Hope It helps,


Thanks,


Johnny 



 Dennis and Steven,



 Not until recently, we isolated this issue with the help of one customer. Generally it’s a .NET 4.0 bug from Microsoft where after using OLEDB on an X86 system, it throws that “Unable to sort because the IComparer.Compare() method returns inconsistent results” exception when calling ArrayList.Sort(). The attached BuidIndexIssueTest.zip is the sample to recreate, it doesn’t reference dlls from Map Suite, and we’ve created a post in MSDN already with the sample and video. Here is the link:  social.msdn.microsoft.com/Fo...7b69042554


 Some Notes here:



        
  1. The attached sample BuildIndexIssuesTest.zip is a Console program, it throws that exception when we directly run it.

  2.     
  3. This exception only raises after executing the SQL command. If we use parameter –i [BuildIndexIssueTest.exe -i] to skip executing SQL command the exception will not be thrown. 


The exception is only thrown in certain circumstances:



        
  • This exception is thrown when running on .NET 4.0, everything goes well on .NET 4.5.

  •     
  • This issue can be reproduced by compiling under X86 platform, it goes well on X64.  

  •     
  • The compare target must implement an interface and it must be casted to an interface before doing the compare, otherwise the exception will not be thrown. Please see the code snippet below, if we use a specific class (Range), everything is fine.

        

  •     
  • The interface must have at least two properties. It works fine if it only has one double property in the interface.    


The workaround we provided to that customer is checking the current platform, use Microsoft.ACE.OLEDB.12.0 if on X64 system and use Microsoft.Jet.OLEDB.4.0 if on X86 system. We can do it by checking the static variable IntPtr.Size, if it equals to 4 it’s under X86. 


 


I hope that makes sense. Let us know if you have any issues. 


 Thanks,


 Ben



BuildIndexIssueTest.zip (16.5 KB)