ThinkGeo.com    |     Documentation    |     Premium Support

Adding features with MSSql2008FeatureLayer

I am having trouble adding features to an MsSql2008FeatureLayer.  The code appears to run properly, but the record is not added to the feature table.  Are there any known issues here?


 



   MsSql2008FeatureLayer MapLayer = new MsSql2008FeatureLayer(MapConnString, Tablename, "ID");
   MapLayer.Srid = 0;
   MapLayer.Open();

   Dictionary<string, string> DictionaryValues = new Dictionary<string, string>(feature.ColumnValues);
   DictionaryValues["Id"] = NextGenProject.DataInterface.GetNextID(MapLayer.TableName).ToString();
   DictionaryValues["FeatureType"] = genFeature.GetWellKnownType().ToString();
                
   if (genFeature.GetWellKnownType() != WellKnownType.Point)
   {
       DictionaryValues["Angle"] = "";
       DictionaryValues["FeatureText"] = "";
       DictionaryValues["RScale"] = "";
       DictionaryValues["DBText"] = "";
       DictionaryValues["PSymbol"] = "";
       DictionaryValues["TextJust"] = "";
   }
   DictionaryValues["ZoomLevel"] = i.ToString();
   MapLayer.EditTools.BeginTransaction();
   MapLayer.EditTools.Add(genFeature, DictionaryValues);
   MapLayer.EditTools.CommitTransaction();
   MapLayer.Close();


Some code is missing.  genFeature is new feature modified from an existing feature.  I want to add it as a new feature.  I have changed the Id field value (the FeatureID column).  I know the feature is valid because I was able to add it throough SQL Server using the WellKnownText for the feature. 
  
 Charles

Charles,


Thanks for your post and code sample.
 
So, the table should contains the following columns: ID, FeatureType and ( Angle, FeatureText, RScale, DBText, PSymbol, TextJust) if not point. And the genFeature should a valid shape. Right?
 
Try to notice the result when commit transaction.

TransactionResult result = MapLayer.EditTools.CommitTransaction();

 
Besides, you could hook up the event to see what the sql statement is to be excuted in the SQL Server.

((MsSql2008FeatureSource)(MapLayer.FeatureSource)).ExecutingSqlStatement += new EventHandler<ExecutingSqlStatementMsSql2008FeatureSourceEventArgs>(CreateAGraticuleAdornmentLayer_ExecutingSqlStatement);
void CreateAGraticuleAdornmentLayer_ExecutingSqlStatement(object sender, ExecutingSqlStatementMsSql2008FeatureSourceEventArgs e)
{
    if (e.ExecutingSqlStatementType == ExecutingSqlStatementType.CommitTransactionEx)
    {
        string sql = e.SqlStatement;
    }
}

 
Any more questions just feel free to let me know.
 
Thanks.
 
Yale

Yale, 
  
 Let me throw you a few curves.  I have two fields in every geometry table called Id and FeatureId.  The Id field is the primary key for the feature geometry table and the FeatureId field links the Id (primary key) field in the feature attribute table.  We have used the field name “Id” for our primary key field since our product was originally written in C++ and VB3 (~1990).  To make things even more interesting, the primary key field name is configurable.  From all appearances, you use the field named FeatureId as the primary key by default.  When I created the MsSql2008FeatureLayer I specified the field named Id as the “FeatureId” field. 
  
 MsSql2008FeatureLayer MapLayer = new MsSql2008FeatureLayer(MapConnString, Tablename, “Id”); 
  
  
 The SQL statement for the CommitTransaction operation came back as: 
  
 “INSERT INTO AmpsGeometry (Location,Id,FeatureId,FeatureType,MapName,Layer,Angle,FeatureText,RScale,DBText,LineStart,LineEnd,PSymbol,TextJust,ZoomLevel) VALUES(Geometry::STGeomFromWKB(@Geometry,0),‘3358b86d-3e82-473b-9b12-670576b8064c’,‘3’,‘Polygon’,‘35761869.MSI’,‘736’,‘0’,’’,‘0’,‘0’,‘0’,‘0’,‘0’,‘0’,‘11’);” 
  
 If you count the fields listed there are 15.  This includes all of the fields in the geometry table.  If you count values listed there are 14.  The statement left off the Id field value which should be ‘36’ in this case. 
  
 This would seem to be a bug, don’t you think? 
  
 Charles

Charles,


Thanks for your post.


Accroding to the SQL statement, the columns and values are as following which seems coreponded and correct.


Columns:


1)   Location

2)   Id

3)   FeatureId

4)   FeatureType

5)   MapName

6)   Layer

7)   Angle

8)   FeatureText

9)   RScale

10) DBText

11) LineStart

12) LineEnd

13) PSymbol

14) TextJust

15) ZoomLevel


VALUES


1)  Geometry::STGeomFromWKB(@Geometry,0)

2) '3358b86d-3e82-473b-9b12-670576b8064c'

3) '3'

4) 'Polygon'

5) '35761869.MSI'

6) '736'

7) '0'

8) ''

9) '0',

10) ‘0'

11) '0'

12) '0'

13) '0'

14) '0'

15) '11'


So if I am not misunderstanding anythingl, the problem is the SQL statement seems only insert a record with 15 columns and values while in fact, its table should contains 16 columns.


Could you call the following API  to query the columns to see if it is 15 columns or 16 columns:

sqlFeatrueLayer.Open();

Collection<FeatureSourceColumn> allColumns = sqlFeatrueLayer.QueryTools.GetColumns();


Is it possible to send me a backup of the SQL data and I will try to recreaet the problem?


Any more questions just feel free to let me know.


Thanks.


Yale


 



Yale,



Sorry, my mistake there are 15 fields and values.  The columns are correct.  I didn't recognize '3358b86d-3e82-473b-9b12-670576b8064c' as a possible value for the Id field.  If I look at the values in DictionaryValues I see DictionaryValues["Id"] = '36'.  the data type for the Id field is int.  It is primary key.  There is a foreign key on the FeatureId field of the AmpsGeometry table linking it to the Id field of the Amps table and causing a cascading delete if I delete the Amps record.



 



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        string ConnString = @"Server=Mapcom061\SQLEXPRESS2008;Database=NGRichDemo;Trusted_Connection=Yes;";
        MsSql2008FeatureLayer MapLayer = new MsSql2008FeatureLayer(ConnString, "AmpsGeometry", "Id");
        MapLayer.Open();
        PolygonShape polygon = new PolygonShape(@"POLYGON((11803825.47 3738681.07, 11803825.47 3738671.07,11803725.47 3738681.07,11803725.47 3738671.07,11803925.47 3738671.07,11803925.47 3738681.07,11804025.47 3738671.07,11804025.47 3738681.07,11803825.47 3738681.07))");
        int i = 11;
        Dictionary<string, string> DictionaryValues = new Dictionary<string, string>();
        DictionaryValues["Id"] = GetNextID(MapLayer.TableName).ToString();
        DictionaryValues["FeatureId"] = "3";
        DictionaryValues["FeatureType"] = "POLYGON";
        DictionaryValues["MapName"] = "35761869.MSI";
        DictionaryValues["Layer"] = "736";
        DictionaryValues["Angle"] = "0";
        DictionaryValues["FeatureText"] = "";
        DictionaryValues["RScale"] = "0";
        DictionaryValues["DBText"] = "0";
        DictionaryValues["LineStart"] = "0";
        DictionaryValues["LineEnd"] = "0";
        DictionaryValues["PSymbol"] = "0";
        DictionaryValues["TextJust"] = "0";
        DictionaryValues["ZoomLevel"] = i.ToString();
        MapLayer.EditTools.BeginTransaction();
        MapLayer.EditTools.Add(polygon, DictionaryValues);
        TransactionResult result = MapLayer.EditTools.CommitTransaction();
        MapLayer.Close();
    }
    private int GetNextID(string Tablename)
    {
        string SQLText = "SELECT Max(ID) AS MaxID FROM " + Tablename;
        OleDbConnection conn = new OleDbConnection(@"Provider=SQLOLEDB;Server=Mapcom061\SQLEXPRESS2008;Database=NGRichDemo;Trusted_Connection=Yes;");
        conn.Open();
        OleDbDataAdapter DA = new OleDbDataAdapter(SQLText, conn);
        DataSet DS = new DataSet();
        DA.Fill(DS);
        DA.Dispose();
        conn.Close();
        int nextid = 1;
        if (DS.Tables[0].Rows.Count > 0)
        {
            DataRow DR = DS.Tables[0].Rows[0];
            if (DR["MaxID"] != DBNull.Value)
                nextid = Convert.ToInt32(DR["MaxID"]) + 1;
        }
        DS.Dispose();
        return nextid;
    }
}

 

 


I have attached a backup of a truncated data set.  I get the same error with this code.



Charles



2088-NGRichDemoConverted.zip (192 KB)

Charles,


Thanks for your post and data.
 
Try following code which set the polygon id to a correct value explicitly before commit transaction should fix your problem.

 

MapLayer.EditTools.BeginTransaction();
 
polygon.Id = DictionaryValues["Id"];
MapLayer.EditTools.Add(polygon, DictionaryValues);
TransactionResult result = MapLayer.EditTools.CommitTransaction();
MapLayer.Close();


Any more questions just feel free to let me know.
 
Thanks.
 
Yale

Yale, 
  
 That seems to have done the trick.  Thanks! 
  
 Charles

Charles, 
  
 Thanks for letting me know the status. 
  
 Any more questions just feel free to let me know. 
  
 Thanks. 
  
 Yale