[mapguide-commits] r8280 - in sandbox/jng/convenience_apis: Common/MapGuideCommon/MapLayer Common/PlatformBase/MapLayer UnitTest/WebTier/DotNet/TestCommon/ExternalTests

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri Jul 4 03:14:44 PDT 2014


Author: jng
Date: 2014-07-04 03:14:44 -0700 (Fri, 04 Jul 2014)
New Revision: 8280

Modified:
   sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.cpp
   sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.h
   sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.cpp
   sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.h
   sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/ConvenienceTests.cs
Log:
This submission adds and modifies some of the convenience APIs we've introduced to MgLayerBase:
 - InsertFeatures/UpdateMatchingFeatures/DeleteFeatures have been modified to accept an MgTransaction parameter, if not null the relevant operation will execute under that transaction
 - A new overload of UpdateFeatures() that accepts a MgTransaction parameter. The original UpdateFeatures() method will still internally use a transaction if supported. This overload you can choose to use transactions (if supported) or not (by passing a null MgTransaction).
 - A new BeginTransaction() convenience method to start a new transaction for the layer's feature source
 - A new GetSpatialContexts() convenience method

New .net tests have been added to the new APIs added and existing .net tests have been modified to reflect the API changes.

Modified: sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.cpp
===================================================================
--- sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.cpp	2014-07-04 08:45:30 UTC (rev 8279)
+++ sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.cpp	2014-07-04 10:14:44 UTC (rev 8280)
@@ -457,111 +457,102 @@
     }
 }
 
-MgFeatureReader* MgLayer::InsertFeatures(MgPropertyCollection* properties)
+MgTransaction* MgLayer::BeginTransaction()
 {
+    Ptr<MgTransaction> ret;
+
+    MG_TRY()
+
+    Ptr<MgResourceIdentifier> resourceId = new MgResourceIdentifier(m_featureSourceId);
     Ptr<MgFeatureService> featureService = dynamic_cast<MgFeatureService*>(
         GetMap()->GetService(MgServiceType::FeatureService));
-    Ptr<MgResourceIdentifier> resourceId = new MgResourceIdentifier(m_featureSourceId);
 
-    Ptr<MgFeatureReader> ret;
-    Ptr<MgTransaction> trans;
-    MG_TRY()
+    ret = featureService->BeginTransaction(resourceId);
 
-    if (UseTransaction(featureService, GetProviderName()))
-        trans = featureService->BeginTransaction(resourceId);
+    MG_CATCH_AND_THROW(L"MgLayer.BeginTransaction")
 
-    ret = featureService->InsertFeatures(resourceId, m_featureName, properties);
-    if (NULL != trans.p)
-        trans->Commit();
+    return ret.Detach();
+}
 
-    MG_CATCH(L"MgLayer.InsertFeatures")
+MgPropertyCollection* MgLayer::UpdateFeatures(MgFeatureCommandCollection* commands, MgTransaction* transaction)
+{
+    Ptr<MgPropertyCollection> propCol;
 
-    if (NULL != trans.p)
-        trans->Rollback();
+    MG_TRY()
 
-    MG_THROW()
+    Ptr<MgResourceIdentifier> resourceId = new MgResourceIdentifier(m_featureSourceId);
+    // Determine if the provider supports transactions.
+    Ptr<MgFeatureService> featureService = dynamic_cast<MgFeatureService*>(
+        GetMap()->GetService(MgServiceType::FeatureService));
 
-    return ret.Detach();
+    propCol = featureService->UpdateFeatures(resourceId, commands, transaction);
+
+    MG_CATCH_AND_THROW(L"MgLayer.UpdateFeatures")
+
+    return propCol.Detach();
 }
 
-MgFeatureReader* MgLayer::InsertFeatures(MgBatchPropertyCollection* properties)
+MgFeatureReader* MgLayer::InsertFeatures(MgPropertyCollection* properties, MgTransaction* transaction)
 {
     Ptr<MgFeatureService> featureService = dynamic_cast<MgFeatureService*>(
         GetMap()->GetService(MgServiceType::FeatureService));
     Ptr<MgResourceIdentifier> resourceId = new MgResourceIdentifier(m_featureSourceId);
 
     Ptr<MgFeatureReader> ret;
-    Ptr<MgTransaction> trans;
     MG_TRY()
 
-    if (UseTransaction(featureService, GetProviderName()))
-        trans = featureService->BeginTransaction(resourceId);
+    ret = featureService->InsertFeatures(resourceId, m_featureName, properties, transaction);
 
-    ret = featureService->InsertFeatures(resourceId, m_featureName, properties);
-    if (NULL != trans.p)
-        trans->Commit();
+    MG_CATCH_AND_THROW(L"MgLayer.InsertFeatures")
 
-    MG_CATCH(L"MgLayer.InsertFeatures")
+    return ret.Detach();
+}
 
-    if (NULL != trans.p)
-        trans->Rollback();
+MgFeatureReader* MgLayer::InsertFeatures(MgBatchPropertyCollection* properties, MgTransaction* transaction)
+{
+    Ptr<MgFeatureService> featureService = dynamic_cast<MgFeatureService*>(
+        GetMap()->GetService(MgServiceType::FeatureService));
+    Ptr<MgResourceIdentifier> resourceId = new MgResourceIdentifier(m_featureSourceId);
 
-    MG_THROW()
+    Ptr<MgFeatureReader> ret;
+    MG_TRY()
 
+    ret = featureService->InsertFeatures(resourceId, m_featureName, properties, transaction);
+
+    MG_CATCH_AND_THROW(L"MgLayer.InsertFeatures")
+
     return ret.Detach();
 }
 
-INT32 MgLayer::UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING filter)
+INT32 MgLayer::UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING filter, MgTransaction* transaction)
 {
     Ptr<MgFeatureService> featureService = dynamic_cast<MgFeatureService*>(
         GetMap()->GetService(MgServiceType::FeatureService));
     Ptr<MgResourceIdentifier> resourceId = new MgResourceIdentifier(m_featureSourceId);
 
     INT32 updated = -1;
-    Ptr<MgTransaction> trans;
     MG_TRY()
 
-    if (UseTransaction(featureService, GetProviderName()))
-        trans = featureService->BeginTransaction(resourceId);
+    updated = featureService->UpdateMatchingFeatures(resourceId, m_featureName, properties, filter, transaction);
+    
+    MG_CATCH_AND_THROW(L"MgLayer.UpdateMatchingFeatures")
 
-    updated = featureService->UpdateMatchingFeatures(resourceId, m_featureName, properties, filter);
-    if (NULL != trans.p)
-        trans->Commit();
-
-    MG_CATCH(L"MgLayer.UpdateMatchingFeatures")
-
-    if (NULL != trans.p)
-        trans->Rollback();
-
-    MG_THROW()
-
     return updated;
 }
 
-INT32 MgLayer::DeleteFeatures(CREFSTRING filter)
+INT32 MgLayer::DeleteFeatures(CREFSTRING filter, MgTransaction* transaction)
 {
     Ptr<MgFeatureService> featureService = dynamic_cast<MgFeatureService*>(
         GetMap()->GetService(MgServiceType::FeatureService));
     Ptr<MgResourceIdentifier> resourceId = new MgResourceIdentifier(m_featureSourceId);
 
     INT32 deleted = -1;
-    Ptr<MgTransaction> trans;
     MG_TRY()
 
-    if (UseTransaction(featureService, GetProviderName()))
-        trans = featureService->BeginTransaction(resourceId);
+    deleted = featureService->DeleteFeatures(resourceId, m_featureName, filter, transaction);
 
-    deleted = featureService->DeleteFeatures(resourceId, m_featureName, filter);
-    if (NULL != trans.p)
-        trans->Commit();
+    MG_CATCH_AND_THROW(L"MgLayer.DeleteFeatures")
 
-    MG_CATCH(L"MgLayer.DeleteFeatures")
-
-    if (NULL != trans.p)
-        trans->Rollback();
-
-    MG_THROW()
-
     return deleted;
 }
 
@@ -773,4 +764,19 @@
     MG_CATCH_AND_THROW(L"MgLayer.GenerateLegendImage");
 
     return ret.Detach();
+}
+
+MgSpatialContextReader* MgLayer::GetSpatialContexts(bool bActiveOnly)
+{
+    Ptr<MgSpatialContextReader> ret;
+
+    MG_TRY()
+
+    Ptr<MgFeatureService> svcFeature = dynamic_cast<MgFeatureService*>(GetMap()->GetService(MgServiceType::FeatureService));
+    Ptr<MgResourceIdentifier> fsId = new MgResourceIdentifier(m_featureSourceId);
+    ret = svcFeature->GetSpatialContexts(fsId, bActiveOnly);
+
+    MG_CATCH_AND_THROW(L"MgLayer.GetSpatialContexts");
+
+    return ret.Detach();
 }
\ No newline at end of file

Modified: sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.h
===================================================================
--- sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.h	2014-07-04 08:45:30 UTC (rev 8279)
+++ sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.h	2014-07-04 10:14:44 UTC (rev 8280)
@@ -262,6 +262,97 @@
     ///
     virtual MgPropertyCollection* UpdateFeatures(MgFeatureCommandCollection* commands);
 
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Starts a transaction on the this layer. The FDO provider indicated by the layer's 
+    /// Feature Source must support transactions.
+    ///
+    /// \remarks
+    /// The XML returned by MgFeatureService::GetCapabilities says
+    /// whether a provider supports transactions. See \link ProviderCapabilities Provider Capabilities \endlink.
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgTransaction BeginTransaction();
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgTransaction BeginTransaction();
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgTransaction BeginTransaction();
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \return
+    /// Returns an MgTransaction instance (or NULL).
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgTransaction* BeginTransaction();
+
+    //////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Executes the MgDeleteFeatures, MgInsertFeatures,
+    /// MgUpdateFeatures, MgLockFeatures or MgUnlockFeatures commands
+    /// contained in the given MgFeatureCommandCollection object.
+    ///
+    /// \remarks
+    /// The XML returned by MgFeatureService::GetCapabilities says
+    /// whether a provider supports SQL commands. See \link ProviderCapabilities Provider Capabilities \endlink.
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgPropertyCollection UpdateFeatures(MgFeatureCommandCollection commands);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgPropertyCollection UpdateFeatures(MgFeatureCommandCollection commands);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgPropertyCollection UpdateFeatures(MgFeatureCommandCollection commands);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param commands (MgFeatureCommandCollection)
+    /// A collection of feature commands to be
+    /// executed.
+    /// \param transaction (MgTransaction)
+    /// An optional transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns an MgPropertyCollection object. Each property in the
+    /// collection corresponds to a command in the
+    /// MgFeatureCommandCollection argument. The property name is the
+    /// index of the command in the feature command collection.
+    /// <ul>
+    ///   <li>If the command is of type MgDeleteFeatures, the property
+    ///     type is an MgPropertyType::Int32, and its value is the number
+    ///     of features deleted.</li>
+    ///   <li>If the command is of type MgInsertFeatures, the property
+    ///     type is an MgPropertyType::Feature, and its value is a
+    ///     MgFeatureReader object. The feature reader object contains
+    ///     the set of properties inserted into the datastore by the
+    ///     insert command.</li>
+    ///   <li>If the command is of type MgUpdateFeatures, the property
+    ///     type is MgPropertyType::Int32, and its value is the number of
+    ///     features updated.</li>
+    ///   <li>If the command is of type MgLockFeatures, the property
+    ///     type is MgPropertyType::Feature, and its value is the number
+    ///     of features locked.</li>
+    ///   <li>If the command is of type MgUnLockFeatures, the property
+    ///     type is MgPropertyType::Int32, and its value is the number of
+    ///     features unlocked.</li>
+    /// </ul>
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgPropertyCollection* UpdateFeatures(MgFeatureCommandCollection* commands, MgTransaction* transaction);
+
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
     /// Inserts a new feature into the specified feature class of the specified Feature Source
@@ -295,7 +386,7 @@
     /// \exception MgFdoException
     ///
     /// \since 3.0
-    virtual MgFeatureReader* InsertFeatures(MgPropertyCollection* properties);
+    virtual MgFeatureReader* InsertFeatures(MgPropertyCollection* properties, MgTransaction* transaction);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
@@ -331,7 +422,7 @@
     /// \exception MgFdoException
     ///
     /// \since 3.0
-    virtual MgFeatureReader* InsertFeatures(MgBatchPropertyCollection* properties);
+    virtual MgFeatureReader* InsertFeatures(MgBatchPropertyCollection* properties, MgTransaction* transaction);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
@@ -365,7 +456,7 @@
     /// \exception MgFdoException
     ///
     /// \since 3.0
-    virtual INT32 UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING filter);
+    virtual INT32 UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING filter, MgTransaction* transaction);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
@@ -397,7 +488,7 @@
     /// \exception MgFdoException
     ///
     /// \since 3.0
-    virtual INT32 DeleteFeatures(CREFSTRING filter);
+    virtual INT32 DeleteFeatures(CREFSTRING filter, MgTransaction* transaction);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
@@ -669,6 +760,40 @@
     /// \since 3.0
     MgByteReader* GenerateLegendImage(double scale, INT32 width, INT32 height, CREFSTRING format, INT32 geomType, INT32 themeCategory);
 
+    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Gets all of the spatial contexts available in the layer or just the active one
+    ///
+    /// \remarks
+    /// The \link FdoSpatialContextList_schema FdoSpatialContextList \endlink XML schema contains
+    /// a specification of the content of the spatial context
+    /// information returned in the MgSpatialContextReader object.
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgSpatialContextReader GetSpatialContexts(bool bActiveOnly);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgSpatialContextReader GetSpatialContexts(boolean bActiveOnly);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgSpatialContextReader GetSpatialContexts(bool bActiveOnly);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param bActiveOnly (boolean/bool)
+    /// This flag is obsolete and no longer used.
+    ///
+    /// \return
+    /// Returns an MgSpatialContextReader object.
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgSpatialContextReader* GetSpatialContexts(bool bActiveOnly);
+
 INTERNAL_API:
 
     //////////////////////////////////////////////////////////////////

Modified: sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.cpp
===================================================================
--- sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.cpp	2014-07-04 08:45:30 UTC (rev 8279)
+++ sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.cpp	2014-07-04 10:14:44 UTC (rev 8280)
@@ -814,26 +814,44 @@
         __LINE__, __WFILE__, NULL, L"", NULL);
 }
 
-MgFeatureReader* MgLayerBase::InsertFeatures(MgPropertyCollection* properties)
+MgPropertyCollection* MgLayerBase::UpdateFeatures(MgFeatureCommandCollection* commands, MgTransaction* transaction)
 {
+    throw new MgNotImplementedException(L"MgLayerBase.UpdateFeatures",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+MgTransaction* MgLayerBase::BeginTransaction()
+{
+    throw new MgNotImplementedException(L"MgLayerBase.BeginTransaction",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+MgFeatureReader* MgLayerBase::InsertFeatures(MgPropertyCollection* properties, MgTransaction* transaction)
+{
     throw new MgNotImplementedException(L"MgLayerBase.InsertFeatures",
         __LINE__, __WFILE__, NULL, L"", NULL);
 }
 
-MgFeatureReader* MgLayerBase::InsertFeatures(MgBatchPropertyCollection* properties)
+MgFeatureReader* MgLayerBase::InsertFeatures(MgBatchPropertyCollection* properties, MgTransaction* transaction)
 {
     throw new MgNotImplementedException(L"MgLayerBase.InsertFeatures",
         __LINE__, __WFILE__, NULL, L"", NULL);
 }
 
-INT32 MgLayerBase::UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING filter)
+INT32 MgLayerBase::UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING filter, MgTransaction* transaction)
 {
     throw new MgNotImplementedException(L"MgLayerBase.UpdateMatchingFeatures",
         __LINE__, __WFILE__, NULL, L"", NULL);
 }
 
-INT32 MgLayerBase::DeleteFeatures(CREFSTRING filter)
+INT32 MgLayerBase::DeleteFeatures(CREFSTRING filter, MgTransaction* transaction)
 {
     throw new MgNotImplementedException(L"MgLayerBase.DeleteFeatures",
         __LINE__, __WFILE__, NULL, L"", NULL);
 }
+
+MgSpatialContextReader* MgLayerBase::GetSpatialContexts(bool bActiveOnly)
+{
+    throw new MgNotImplementedException(L"MgLayerBase.GetSpatialContexts",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
\ No newline at end of file

Modified: sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.h
===================================================================
--- sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.h	2014-07-04 08:45:30 UTC (rev 8279)
+++ sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.h	2014-07-04 10:14:44 UTC (rev 8280)
@@ -908,6 +908,97 @@
     /// \since 1.2
     virtual MgPropertyCollection* UpdateFeatures(MgFeatureCommandCollection* commands);
 
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Starts a transaction on the this layer. The FDO provider indicated by the layer's 
+    /// Feature Source must support transactions.
+    ///
+    /// \remarks
+    /// The XML returned by MgFeatureService::GetCapabilities says
+    /// whether a provider supports transactions. See \link ProviderCapabilities Provider Capabilities \endlink.
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgTransaction BeginTransaction();
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgTransaction BeginTransaction();
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgTransaction BeginTransaction();
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \return
+    /// Returns an MgTransaction instance (or NULL).
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgTransaction* BeginTransaction();
+
+    //////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Executes the MgDeleteFeatures, MgInsertFeatures,
+    /// MgUpdateFeatures, MgLockFeatures or MgUnlockFeatures commands
+    /// contained in the given MgFeatureCommandCollection object.
+    ///
+    /// \remarks
+    /// The XML returned by MgFeatureService::GetCapabilities says
+    /// whether a provider supports SQL commands. See \link ProviderCapabilities Provider Capabilities \endlink.
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgPropertyCollection UpdateFeatures(MgFeatureCommandCollection commands);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgPropertyCollection UpdateFeatures(MgFeatureCommandCollection commands);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgPropertyCollection UpdateFeatures(MgFeatureCommandCollection commands);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param commands (MgFeatureCommandCollection)
+    /// A collection of feature commands to be
+    /// executed.
+    /// \param transaction (MgTransaction)
+    /// An optional transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns an MgPropertyCollection object. Each property in the
+    /// collection corresponds to a command in the
+    /// MgFeatureCommandCollection argument. The property name is the
+    /// index of the command in the feature command collection.
+    /// <ul>
+    ///   <li>If the command is of type MgDeleteFeatures, the property
+    ///     type is an MgPropertyType::Int32, and its value is the number
+    ///     of features deleted.</li>
+    ///   <li>If the command is of type MgInsertFeatures, the property
+    ///     type is an MgPropertyType::Feature, and its value is a
+    ///     MgFeatureReader object. The feature reader object contains
+    ///     the set of properties inserted into the datastore by the
+    ///     insert command.</li>
+    ///   <li>If the command is of type MgUpdateFeatures, the property
+    ///     type is MgPropertyType::Int32, and its value is the number of
+    ///     features updated.</li>
+    ///   <li>If the command is of type MgLockFeatures, the property
+    ///     type is MgPropertyType::Feature, and its value is the number
+    ///     of features locked.</li>
+    ///   <li>If the command is of type MgUnLockFeatures, the property
+    ///     type is MgPropertyType::Int32, and its value is the number of
+    ///     features unlocked.</li>
+    /// </ul>
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgPropertyCollection* UpdateFeatures(MgFeatureCommandCollection* commands, MgTransaction* transaction);
+
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
     /// Inserts a new feature into the specified feature class of the specified Feature Source
@@ -925,6 +1016,8 @@
     ///
     /// \param properties (MgPropertyCollection)
     /// The collection of property values to insert
+    /// \param transaction (MgTransaction)
+    /// An optional transaction to execute this operation under
     ///
     /// \return
     /// Returns a feature reader object that contains the set of properties 
@@ -941,7 +1034,7 @@
     /// \exception MgFdoException
     ///
     /// \since 3.0
-    virtual MgFeatureReader* InsertFeatures(MgPropertyCollection* properties);
+    virtual MgFeatureReader* InsertFeatures(MgPropertyCollection* properties, MgTransaction* transaction);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
@@ -961,6 +1054,8 @@
     /// \param properties (MgBatchPropertyCollection)
     /// The collection of property values to insert. Each MgPropertyCollection within 
     /// this collection represents property values for a single feature to insert
+    /// \param transaction (MgTransaction)
+    /// An optional transaction to execute this operation under
     ///
     /// \return
     /// Returns a feature reader object that contains the set of properties 
@@ -977,7 +1072,7 @@
     /// \exception MgFdoException
     ///
     /// \since 3.0
-    virtual MgFeatureReader* InsertFeatures(MgBatchPropertyCollection* properties);
+    virtual MgFeatureReader* InsertFeatures(MgBatchPropertyCollection* properties, MgTransaction* transaction);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
@@ -1001,6 +1096,8 @@
     /// The property values to update matching features with
     /// \param filter (String/string)
     /// The FDO filter string that detemines what features will be updated
+    /// \param transaction (MgTransaction)
+    /// An optional transaction to execute this operation under
     ///
     /// \return
     /// Returns the number of features updated by this operation
@@ -1011,7 +1108,7 @@
     /// \exception MgFdoException
     ///
     /// \since 3.0
-    virtual INT32 UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING filter);
+    virtual INT32 UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING filter, MgTransaction* transaction);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     /// \brief
@@ -1033,6 +1130,8 @@
     ///
     /// \param filter (String/string)
     /// The FDO filter string that detemines what features will be deleted
+    /// \param transaction (MgTransaction)
+    /// An optional transaction to execute this operation under
     ///
     /// \return
     /// Returns the number of features deleted by this operation
@@ -1043,8 +1142,42 @@
     /// \exception MgFdoException
     ///
     /// \since 3.0
-    virtual INT32 DeleteFeatures(CREFSTRING filter);
+    virtual INT32 DeleteFeatures(CREFSTRING filter, MgTransaction* transaction);
 
+    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Gets all of the spatial contexts available in the layer or just the active one
+    ///
+    /// \remarks
+    /// The \link FdoSpatialContextList_schema FdoSpatialContextList \endlink XML schema contains
+    /// a specification of the content of the spatial context
+    /// information returned in the MgSpatialContextReader object.
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgSpatialContextReader GetSpatialContexts(bool bActiveOnly);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgSpatialContextReader GetSpatialContexts(boolean bActiveOnly);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgSpatialContextReader GetSpatialContexts(bool bActiveOnly);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param bActiveOnly (boolean/bool)
+    /// This flag is obsolete and no longer used.
+    ///
+    /// \return
+    /// Returns an MgSpatialContextReader object.
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgSpatialContextReader* GetSpatialContexts(bool bActiveOnly);
+
 INTERNAL_API:
 
     static MdfModel::LayerDefinition* GetLayerDefinition(MgResourceService* svcResource, MgResourceIdentifier* resId);

Modified: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/ConvenienceTests.cs
===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/ConvenienceTests.cs	2014-07-04 08:45:30 UTC (rev 8279)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/ConvenienceTests.cs	2014-07-04 10:14:44 UTC (rev 8280)
@@ -57,161 +57,421 @@
     {
         public void Execute(IPlatformFactory factory, ITestLogger logger)
         {
-            MgFeatureService featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
-            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/InsertFeatures.FeatureSource");
-            string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
-            var agfRw = new MgAgfReaderWriter();
-            var wktRw = new MgWktReaderWriter();
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/FeatureServiceInsertFeatures.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var props = new MgPropertyCollection();
-            var nameP = new MgStringProperty("Name", "Test");
-            var geom = wktRw.Read("POINT (1 1)");
-            var agf = agfRw.Write(geom);
-            var geomP = new MgGeometryProperty("Geometry", agf);
-            props.Add(nameP);
-            props.Add(geomP);
+                var props = new MgPropertyCollection();
+                var nameP = new MgStringProperty("Name", "Test");
+                var geom = wktRw.Read("POINT (1 1)");
+                var agf = agfRw.Write(geom);
+                var geomP = new MgGeometryProperty("Geometry", agf);
+                props.Add(nameP);
+                props.Add(geomP);
 
-            var fr = featSvc.InsertFeatures(fsId, className, props);
-            int count = 0;
-            while (fr.ReadNext())
+                var fr = featSvc.InsertFeatures(fsId, className, props);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(1, count);
+            }
+            finally
             {
-                count++;
+                resSvc.DeleteResource(fsId);
             }
-            fr.Close();
-            Assert.AreEqual(1, count);
         }
     }
 
-    public class FeatureServiceInsertFeaturesBatched : IExternalTest
+    public class FeatureServiceInsertFeaturesWithTransaction : IExternalTest
     {
         public void Execute(IPlatformFactory factory, ITestLogger logger)
         {
-            MgFeatureService featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
-            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/InsertFeaturesBatched.FeatureSource");
-            string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
-            var agfRw = new MgAgfReaderWriter();
-            var wktRw = new MgWktReaderWriter();
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/FeatureServiceInsertFeaturesWithTransaction.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SQLite", featSvc);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var batchProps = new MgBatchPropertyCollection();
-            for (int i = 0; i < 5; i++)
-            {
                 var props = new MgPropertyCollection();
-                var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                var nameP = new MgStringProperty("Name", "Test");
                 var geom = wktRw.Read("POINT (1 1)");
                 var agf = agfRw.Write(geom);
                 var geomP = new MgGeometryProperty("Geometry", agf);
                 props.Add(nameP);
                 props.Add(geomP);
-                batchProps.Add(props);
+                var trans = featSvc.BeginTransaction(fsId);
+                var fr = featSvc.InsertFeatures(fsId, className, props, trans);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(1, count);
+                trans.Rollback();
+
+                fr = featSvc.SelectFeatures(fsId, className, null);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(0, count);
             }
-
-            var fr = featSvc.InsertFeatures(fsId, className, batchProps);
-            int count = 0;
-            while (fr.ReadNext())
+            finally
             {
-                count++;
+                resSvc.DeleteResource(fsId);
             }
-            fr.Close();
-            Assert.AreEqual(5, count);
         }
     }
 
-    public class FeatureServiceUpdateFeatures : IExternalTest
+    public class FeatureServiceInsertFeaturesBatched : IExternalTest
     {
         public void Execute(IPlatformFactory factory, ITestLogger logger)
         {
-            MgFeatureService featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/FeatureServiceInsertFeaturesBatched.FeatureSource");
+            try 
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/UpdateFeatures.FeatureSource");
-            string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
-            var agfRw = new MgAgfReaderWriter();
-            var wktRw = new MgWktReaderWriter();
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
 
-            var batchProps = new MgBatchPropertyCollection();
-            for (int i = 0; i < 5; i++)
+                var fr = featSvc.InsertFeatures(fsId, className, batchProps);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+            }
+            finally
             {
-                var props = new MgPropertyCollection();
-                var nameP = new MgStringProperty("Name", "Test" + (i + 1));
-                var geom = wktRw.Read("POINT (1 1)");
-                var agf = agfRw.Write(geom);
-                var geomP = new MgGeometryProperty("Geometry", agf);
-                props.Add(nameP);
-                props.Add(geomP);
-                batchProps.Add(props);
+                resSvc.DeleteResource(fsId);
             }
+        }
+    }
 
-            var fr = featSvc.InsertFeatures(fsId, className, batchProps);
-            int count = 0;
-            while (fr.ReadNext())
+    public class FeatureServiceInsertFeaturesBatchedWithTransaction : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/FeatureServiceInsertFeaturesBatchedWithTransaction.FeatureSource");
+            try
             {
-                count++;
-            }
-            fr.Close();
-            Assert.AreEqual(5, count);
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SQLite", featSvc);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var updateProps = new MgPropertyCollection();
-            var newName = new MgStringProperty("Name", "Test3Updated");
-            updateProps.Add(newName);
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
 
-            int updated = featSvc.UpdateMatchingFeatures(fsId, className, updateProps, "Name = 'Test3'");
-            Assert.AreEqual(1, updated);
+                var trans = featSvc.BeginTransaction(fsId);
+                var fr = featSvc.InsertFeatures(fsId, className, batchProps, trans);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+                trans.Rollback();
+
+                fr = featSvc.SelectFeatures(fsId, className, null);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(0, count);
+            }
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
         }
     }
 
-    public class FeatureServiceDeleteFeatures : IExternalTest
+    public class FeatureServiceUpdateFeatures : IExternalTest
     {
         public void Execute(IPlatformFactory factory, ITestLogger logger)
         {
-            MgFeatureService featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/FeatureServiceUpdateFeatures.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/DeleteFeatures.FeatureSource");
-            string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
-            var agfRw = new MgAgfReaderWriter();
-            var wktRw = new MgWktReaderWriter();
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
 
-            var batchProps = new MgBatchPropertyCollection();
-            for (int i = 0; i < 5; i++)
+                var fr = featSvc.InsertFeatures(fsId, className, batchProps);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                var updateProps = new MgPropertyCollection();
+                var newName = new MgStringProperty("Name", "Test3Updated");
+                updateProps.Add(newName);
+
+                int updated = featSvc.UpdateMatchingFeatures(fsId, className, updateProps, "Name = 'Test3'");
+                Assert.AreEqual(1, updated);
+            }
+            finally
             {
-                var props = new MgPropertyCollection();
-                var nameP = new MgStringProperty("Name", "Test" + (i + 1));
-                var geom = wktRw.Read("POINT (1 1)");
-                var agf = agfRw.Write(geom);
-                var geomP = new MgGeometryProperty("Geometry", agf);
-                props.Add(nameP);
-                props.Add(geomP);
-                batchProps.Add(props);
+                resSvc.DeleteResource(fsId);
             }
+        }
+    }
 
-            var fr = featSvc.InsertFeatures(fsId, className, batchProps);
-            int count = 0;
-            while (fr.ReadNext())
+    public class FeatureServiceUpdateFeaturesWithTransaction : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/FeatureServiceUpdateFeaturesWithTransaction.FeatureSource");
+            try
             {
-                count++;
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SQLite", featSvc);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
+
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
+
+                var fr = featSvc.InsertFeatures(fsId, className, batchProps);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                var updateProps = new MgPropertyCollection();
+                var newName = new MgStringProperty("Name", "Test3Updated");
+                updateProps.Add(newName);
+
+                var trans = featSvc.BeginTransaction(fsId);
+                int updated = featSvc.UpdateMatchingFeatures(fsId, className, updateProps, "Name = 'Test3'", trans);
+                Assert.AreEqual(1, updated);
+                trans.Rollback();
+
+                var query = new MgFeatureQueryOptions();
+                query.SetFilter("Name = 'Test3Updated'");
+                fr = featSvc.SelectFeatures(fsId, className, query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(0, count);
             }
-            fr.Close();
-            Assert.AreEqual(5, count);
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
+        }
+    }
 
-            int deleted = featSvc.DeleteFeatures(fsId, className, "Name = 'Test3'");
-            Assert.AreEqual(1, deleted);
+    public class FeatureServiceDeleteFeatures : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/FeatureServiceDeleteFeatures.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var query = new MgFeatureQueryOptions();
-            fr = featSvc.SelectFeatures(fsId, className, query);
-            count = 0;
-            while (fr.ReadNext())
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
+
+                var fr = featSvc.InsertFeatures(fsId, className, batchProps);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                int deleted = featSvc.DeleteFeatures(fsId, className, "Name = 'Test3'");
+                Assert.AreEqual(1, deleted);
+
+                var query = new MgFeatureQueryOptions();
+                fr = featSvc.SelectFeatures(fsId, className, query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(4, count);
+
+                query.SetFilter("Name = 'Test3'");
+                fr = featSvc.SelectFeatures(fsId, className, query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(0, count);
+            }
+            finally
             {
-                count++;
+                resSvc.DeleteResource(fsId);
             }
-            Assert.AreEqual(4, count);
+        }
+    }
 
-            query.SetFilter("Name = 'Test3'");
-            fr = featSvc.SelectFeatures(fsId, className, query);
-            count = 0;
-            while (fr.ReadNext())
+    public class FeatureServiceDeleteFeaturesWithTransaction : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/FeatureServiceDeleteFeaturesWithTransaction.FeatureSource");
+            try
             {
-                count++;
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SQLite", featSvc);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
+
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
+
+                var fr = featSvc.InsertFeatures(fsId, className, batchProps);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                var trans = featSvc.BeginTransaction(fsId);
+                int deleted = featSvc.DeleteFeatures(fsId, className, "Name = 'Test3'", trans);
+                Assert.AreEqual(1, deleted);
+
+                var query = new MgFeatureQueryOptions();
+                fr = featSvc.SelectFeatures(fsId, className, query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(4, count);
+                trans.Rollback();
+
+                query.SetFilter("Name = 'Test3'");
+                fr = featSvc.SelectFeatures(fsId, className, query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(1, count);
             }
-            fr.Close();
-            Assert.AreEqual(0, count);
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
         }
     }
 
@@ -221,116 +481,263 @@
         {
             var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
             var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/LayerInsertFeatures.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
 
-            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/UpdateFeatures.FeatureSource");
-            string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
 
-            MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
-            MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180,-90,180,90), "TestMap");
-            MgLayerCollection layers = map.GetLayers();
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
 
-            string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
-            byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
-            MgByteSource bs = new MgByteSource(bytes, bytes.Length);
-            MgByteReader br = bs.GetReader();
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
 
-            var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
-            resSvc.SetResource(ldfId, br, null);
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
 
-            MgLayerBase layer = factory.CreateLayer(ldfId);
-            layers.Insert(0, layer);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var agfRw = new MgAgfReaderWriter();
-            var wktRw = new MgWktReaderWriter();
+                var props = new MgPropertyCollection();
+                var nameP = new MgStringProperty("Name", "Test");
+                var geom = wktRw.Read("POINT (1 1)");
+                var agf = agfRw.Write(geom);
+                var geomP = new MgGeometryProperty("Geometry", agf);
+                props.Add(nameP);
+                props.Add(geomP);
 
-            var props = new MgPropertyCollection();
-            var nameP = new MgStringProperty("Name", "Test");
-            var geom = wktRw.Read("POINT (1 1)");
-            var agf = agfRw.Write(geom);
-            var geomP = new MgGeometryProperty("Geometry", agf);
-            props.Add(nameP);
-            props.Add(geomP);
+                var fr = layer.InsertFeatures(props, null);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(1, count);
 
-            var fr = layer.InsertFeatures(props);
-            int count = 0;
-            while (fr.ReadNext())
-            {
-                count++;
+                var query = new MgFeatureQueryOptions();
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(1, count);
             }
-            fr.Close();
-            Assert.AreEqual(1, count);
-
-            var query = new MgFeatureQueryOptions();
-            fr = layer.SelectFeatures(query);
-            count = 0;
-            while (fr.ReadNext())
+            finally
             {
-                count++;
+                resSvc.DeleteResource(fsId);
             }
-            fr.Close();
-            Assert.AreEqual(1, count);
         }
     }
 
-    public class LayerInsertFeaturesBatched : IExternalTest
+    public class LayerInsertFeaturesWithTransaction : IExternalTest
     {
         public void Execute(IPlatformFactory factory, ITestLogger logger)
         {
             var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
             var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/LayerInsertFeaturesWithTransaction.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SQLite", featSvc);
 
-            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/UpdateFeatures.FeatureSource");
-            string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
 
-            MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
-            MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
-            MgLayerCollection layers = map.GetLayers();
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
 
-            string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
-            byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
-            MgByteSource bs = new MgByteSource(bytes, bytes.Length);
-            MgByteReader br = bs.GetReader();
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
 
-            var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
-            resSvc.SetResource(ldfId, br, null);
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
 
-            MgLayerBase layer = factory.CreateLayer(ldfId);
-            layers.Insert(0, layer);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var agfRw = new MgAgfReaderWriter();
-            var wktRw = new MgWktReaderWriter();
-
-            var batchProps = new MgBatchPropertyCollection();
-            for (int i = 0; i < 5; i++)
-            {
                 var props = new MgPropertyCollection();
-                var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                var nameP = new MgStringProperty("Name", "Test");
                 var geom = wktRw.Read("POINT (1 1)");
                 var agf = agfRw.Write(geom);
                 var geomP = new MgGeometryProperty("Geometry", agf);
                 props.Add(nameP);
                 props.Add(geomP);
-                batchProps.Add(props);
+
+                var trans = layer.BeginTransaction();
+                var fr = layer.InsertFeatures(props, trans);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(1, count);
+                trans.Rollback();
+
+                var query = new MgFeatureQueryOptions();
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(0, count);
             }
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
+        }
+    }
 
-            var fr = layer.InsertFeatures(batchProps);
-            int count = 0;
-            while (fr.ReadNext())
+    public class LayerInsertFeaturesBatched : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/LayerInsertFeaturesBatched.FeatureSource");
+            try
             {
-                count++;
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
+
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
+
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
+
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
+
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
+
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
+
+                var fr = layer.InsertFeatures(batchProps, null);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                var query = new MgFeatureQueryOptions();
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
             }
-            fr.Close();
-            Assert.AreEqual(5, count);
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
+        }
+    }
 
-            var query = new MgFeatureQueryOptions();
-            fr = layer.SelectFeatures(query);
-            count = 0;
-            while (fr.ReadNext())
+    public class LayerInsertFeaturesBatchedWithTransaction : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/LayerInsertFeaturesBatchedWithTransaction.FeatureSource");
+            try
             {
-                count++;
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SQLite", featSvc);
+
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
+
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
+
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
+
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
+
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
+
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
+
+                var trans = layer.BeginTransaction();
+                var fr = layer.InsertFeatures(batchProps, trans);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+                trans.Rollback();
+
+                var query = new MgFeatureQueryOptions();
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(0, count);
             }
-            fr.Close();
-            Assert.AreEqual(5, count);
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
         }
     }
 
@@ -340,56 +747,140 @@
         {
             var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
             var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/LayerUpdateFeatures.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
 
-            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/UpdateFeatures.FeatureSource");
-            string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
 
-            MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
-            MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
-            MgLayerCollection layers = map.GetLayers();
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
 
-            string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
-            byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
-            MgByteSource bs = new MgByteSource(bytes, bytes.Length);
-            MgByteReader br = bs.GetReader();
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
 
-            var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
-            resSvc.SetResource(ldfId, br, null);
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
 
-            MgLayerBase layer = factory.CreateLayer(ldfId);
-            layers.Insert(0, layer);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var agfRw = new MgAgfReaderWriter();
-            var wktRw = new MgWktReaderWriter();
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
 
-            var batchProps = new MgBatchPropertyCollection();
-            for (int i = 0; i < 5; i++)
+                var fr = layer.InsertFeatures(batchProps, null);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                var updateProps = new MgPropertyCollection();
+                var newName = new MgStringProperty("Name", "Test3Updated");
+                updateProps.Add(newName);
+
+                int updated = layer.UpdateMatchingFeatures(updateProps, "Name = 'Test3'", null);
+                Assert.AreEqual(1, updated);
+            }
+            finally
             {
-                var props = new MgPropertyCollection();
-                var nameP = new MgStringProperty("Name", "Test" + (i + 1));
-                var geom = wktRw.Read("POINT (1 1)");
-                var agf = agfRw.Write(geom);
-                var geomP = new MgGeometryProperty("Geometry", agf);
-                props.Add(nameP);
-                props.Add(geomP);
-                batchProps.Add(props);
+                resSvc.DeleteResource(fsId);
             }
+        }
+    }
 
-            var fr = layer.InsertFeatures(batchProps);
-            int count = 0;
-            while (fr.ReadNext())
+    public class LayerUpdateFeaturesWithTransaction : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/LayerUpdateFeaturesWithTransaction.FeatureSource");
+            try
             {
-                count++;
-            }
-            fr.Close();
-            Assert.AreEqual(5, count);
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SQLite", featSvc);
 
-            var updateProps = new MgPropertyCollection();
-            var newName = new MgStringProperty("Name", "Test3Updated");
-            updateProps.Add(newName);
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
 
-            int updated = layer.UpdateMatchingFeatures(updateProps, "Name = 'Test3'");
-            Assert.AreEqual(1, updated);
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
+
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
+
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
+
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
+
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
+
+                var fr = layer.InsertFeatures(batchProps, null);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                var updateProps = new MgPropertyCollection();
+                var newName = new MgStringProperty("Name", "Test3Updated");
+                updateProps.Add(newName);
+
+                var trans = layer.BeginTransaction();
+                int updated = layer.UpdateMatchingFeatures(updateProps, "Name = 'Test3'", trans);
+                Assert.AreEqual(1, updated);
+
+                trans.Rollback();
+                var query = new MgFeatureQueryOptions();
+                query.SetFilter("Name = 'Test3Updated'");
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(0, count);
+            }
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
         }
     }
 
@@ -399,71 +890,161 @@
         {
             var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
             var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/LayerDeleteFeatures.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
 
-            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/UpdateFeatures.FeatureSource");
-            string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
 
-            MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
-            MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
-            MgLayerCollection layers = map.GetLayers();
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
 
-            string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
-            byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
-            MgByteSource bs = new MgByteSource(bytes, bytes.Length);
-            MgByteReader br = bs.GetReader();
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
 
-            var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
-            resSvc.SetResource(ldfId, br, null);
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
 
-            MgLayerBase layer = factory.CreateLayer(ldfId);
-            layers.Insert(0, layer);
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
 
-            var agfRw = new MgAgfReaderWriter();
-            var wktRw = new MgWktReaderWriter();
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
 
-            var batchProps = new MgBatchPropertyCollection();
-            for (int i = 0; i < 5; i++)
+                var fr = layer.InsertFeatures(batchProps, null);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                int deleted = layer.DeleteFeatures("Name = 'Test3'", null);
+                Assert.AreEqual(1, deleted);
+
+                var query = new MgFeatureQueryOptions();
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(4, count);
+
+                query.SetFilter("Name = 'Test3'");
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(0, count);
+            }
+            finally
             {
-                var props = new MgPropertyCollection();
-                var nameP = new MgStringProperty("Name", "Test" + (i + 1));
-                var geom = wktRw.Read("POINT (1 1)");
-                var agf = agfRw.Write(geom);
-                var geomP = new MgGeometryProperty("Geometry", agf);
-                props.Add(nameP);
-                props.Add(geomP);
-                batchProps.Add(props);
+                resSvc.DeleteResource(fsId);
             }
+        }
+    }
 
-            var fr = layer.InsertFeatures(batchProps);
-            int count = 0;
-            while (fr.ReadNext())
+    public class LayerDeleteFeaturesWithTransaction : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/LayerDeleteFeaturesWithTransaction.FeatureSource");
+            try
             {
-                count++;
-            }
-            fr.Close();
-            Assert.AreEqual(5, count);
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SQLite", featSvc);
 
-            int deleted = layer.DeleteFeatures("Name = 'Test3'");
-            Assert.AreEqual(1, deleted);
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
 
-            var query = new MgFeatureQueryOptions();
-            fr = layer.SelectFeatures(query);
-            count = 0;
-            while (fr.ReadNext())
-            {
-                count++;
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
+
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
+
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
+
+                var agfRw = new MgAgfReaderWriter();
+                var wktRw = new MgWktReaderWriter();
+
+                var batchProps = new MgBatchPropertyCollection();
+                for (int i = 0; i < 5; i++)
+                {
+                    var props = new MgPropertyCollection();
+                    var nameP = new MgStringProperty("Name", "Test" + (i + 1));
+                    var geom = wktRw.Read("POINT (1 1)");
+                    var agf = agfRw.Write(geom);
+                    var geomP = new MgGeometryProperty("Geometry", agf);
+                    props.Add(nameP);
+                    props.Add(geomP);
+                    batchProps.Add(props);
+                }
+
+                var fr = layer.InsertFeatures(batchProps, null);
+                int count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                var trans = layer.BeginTransaction();
+                int deleted = layer.DeleteFeatures("Name = 'Test3'", trans);
+                Assert.AreEqual(1, deleted);
+                trans.Rollback();
+
+                var query = new MgFeatureQueryOptions();
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(5, count);
+
+                query.SetFilter("Name = 'Test3'");
+                fr = layer.SelectFeatures(query);
+                count = 0;
+                while (fr.ReadNext())
+                {
+                    count++;
+                }
+                fr.Close();
+                Assert.AreEqual(1, count);
             }
-            Assert.AreEqual(4, count);
-
-            query.SetFilter("Name = 'Test3'");
-            fr = layer.SelectFeatures(query);
-            count = 0;
-            while (fr.ReadNext())
+            finally
             {
-                count++;
+                resSvc.DeleteResource(fsId);
             }
-            fr.Close();
-            Assert.AreEqual(0, count);
         }
     }
 
@@ -471,97 +1052,104 @@
     {
         public void Execute(IPlatformFactory factory, ITestLogger logger)
         {
-            MgFeatureService featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/TransformTest.FeatureSource");
+            try
+            {
+                //Create our test data store
+                MgFeatureSchema fs = new MgFeatureSchema("Default", "");
+                MgClassDefinition cls = new MgClassDefinition();
+                cls.SetName("Test");
 
-            //Create our test data store
-            MgFeatureSchema fs = new MgFeatureSchema("Default", "");
-            MgClassDefinition cls = new MgClassDefinition();
-            cls.SetName("Test");
-        
-            MgDataPropertyDefinition id = new MgDataPropertyDefinition("ID");
-            id.SetAutoGeneration(true);
-            id.SetDataType(MgPropertyType.Int32);
-        
-            MgGeometricPropertyDefinition geom = new MgGeometricPropertyDefinition("Geometry");
-            geom.SetGeometryTypes(MgFeatureGeometricType.Point);
-            geom.SetSpatialContextAssociation("Default");
+                MgDataPropertyDefinition id = new MgDataPropertyDefinition("ID");
+                id.SetAutoGeneration(true);
+                id.SetDataType(MgPropertyType.Int32);
 
-            MgPropertyDefinitionCollection props = cls.GetProperties();
-            MgPropertyDefinitionCollection idProps = cls.GetIdentityProperties();
+                MgGeometricPropertyDefinition geom = new MgGeometricPropertyDefinition("Geometry");
+                geom.SetGeometryTypes(MgFeatureGeometricType.Point);
+                geom.SetSpatialContextAssociation("Default");
 
-            props.Add(id);
-            props.Add(geom);
-            idProps.Add(id);
+                MgPropertyDefinitionCollection props = cls.GetProperties();
+                MgPropertyDefinitionCollection idProps = cls.GetIdentityProperties();
 
-            cls.SetDefaultGeometryPropertyName("Geometry");
-            MgClassDefinitionCollection classes = fs.GetClasses();
-            classes.Add(cls);
+                props.Add(id);
+                props.Add(geom);
+                idProps.Add(id);
 
-            //We'll use a transform guaranteed to work. ArbitraryXY (unitA to unitB)
-            //We just check that the transformed values are not the original, that way
-            //we know that CS-Map did its job
-            MgCoordinateSystemFactory csFact = new MgCoordinateSystemFactory();
-            string srcWkt = csFact.ConvertCoordinateSystemCodeToWkt("XY-M");
-            string dstWkt = csFact.ConvertCoordinateSystemCodeToWkt("XY-IN");
+                cls.SetDefaultGeometryPropertyName("Geometry");
+                MgClassDefinitionCollection classes = fs.GetClasses();
+                classes.Add(cls);
 
-            MgGeometryFactory geomFact = new MgGeometryFactory();
-            MgAgfReaderWriter agfRw = new MgAgfReaderWriter();
-            MgFileFeatureSourceParams create = new MgFileFeatureSourceParams("OSGeo.SDF", "Default", srcWkt, fs);
-            MgResourceIdentifier fsId = new MgResourceIdentifier("Library://UnitTests/Data/TransformTest.FeatureSource");
-            featSvc.CreateFeatureSource(fsId, create);
+                //We'll use a transform guaranteed to work. ArbitraryXY (unitA to unitB)
+                //We just check that the transformed values are not the original, that way
+                //we know that CS-Map did its job
+                MgCoordinateSystemFactory csFact = new MgCoordinateSystemFactory();
+                string srcWkt = csFact.ConvertCoordinateSystemCodeToWkt("XY-M");
+                string dstWkt = csFact.ConvertCoordinateSystemCodeToWkt("XY-IN");
 
-            //Populate data store with test points
+                MgGeometryFactory geomFact = new MgGeometryFactory();
+                MgAgfReaderWriter agfRw = new MgAgfReaderWriter();
+                MgFileFeatureSourceParams create = new MgFileFeatureSourceParams("OSGeo.SDF", "Default", srcWkt, fs);
+                featSvc.CreateFeatureSource(fsId, create);
 
-            MgCoordinate coord1 = geomFact.CreateCoordinateXY(-37.1020, 144.0020);
-            MgPoint pt1 = geomFact.CreatePoint(coord1);
-            MgByteReader agf1 = agfRw.Write(pt1);
+                //Populate data store with test points
 
-            MgPropertyCollection propVals = new MgPropertyCollection();
-            MgGeometryProperty pGeom = new MgGeometryProperty("Geometry", agf1);
-            propVals.Add(pGeom);
+                MgCoordinate coord1 = geomFact.CreateCoordinateXY(-37.1020, 144.0020);
+                MgPoint pt1 = geomFact.CreatePoint(coord1);
+                MgByteReader agf1 = agfRw.Write(pt1);
 
-            MgFeatureReader fr = featSvc.InsertFeatures(fsId, "Default:Test", propVals);
-            fr.Close();
+                MgPropertyCollection propVals = new MgPropertyCollection();
+                MgGeometryProperty pGeom = new MgGeometryProperty("Geometry", agf1);
+                propVals.Add(pGeom);
 
-            MgCoordinate coord2 = geomFact.CreateCoordinateXY(-37.2020, 144.2020);
-            MgPoint pt2 = geomFact.CreatePoint(coord2);
-            MgByteReader agf2 = agfRw.Write(pt2);
+                MgFeatureReader fr = featSvc.InsertFeatures(fsId, "Default:Test", propVals);
+                fr.Close();
 
-            pGeom.SetValue(agf2);
-            fr = featSvc.InsertFeatures(fsId, "Default:Test", propVals);
-            fr.Close();
+                MgCoordinate coord2 = geomFact.CreateCoordinateXY(-37.2020, 144.2020);
+                MgPoint pt2 = geomFact.CreatePoint(coord2);
+                MgByteReader agf2 = agfRw.Write(pt2);
 
-            //Now select from this data store
-            MgFeatureQueryOptions query = new MgFeatureQueryOptions();
-            MgReader reader = featSvc.SelectFeatures(fsId, "Default:Test", query, dstWkt);
-        
-            Assert.IsTrue(reader.ReadNext());
-            Assert.IsTrue(!reader.IsNull("Geometry"));
+                pGeom.SetValue(agf2);
+                fr = featSvc.InsertFeatures(fsId, "Default:Test", propVals);
+                fr.Close();
 
-            MgByteReader txAgf1 = reader.GetGeometry("Geometry");
-            MgGeometry txGeom1 = agfRw.Read(txAgf1);
-            MgPoint txPt1 = (MgPoint)txGeom1;
-            Assert.IsTrue(txPt1 != null);
-            MgCoordinate txCoord1 = txPt1.GetCoordinate();
+                //Now select from this data store
+                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
+                MgReader reader = featSvc.SelectFeatures(fsId, "Default:Test", query, dstWkt);
 
-            //TODO: Maybe we should really check that it matches the expected transformed result
-            Assert.IsTrue(txCoord1.GetX() != -37.1020);
-            Assert.IsTrue(txCoord1.GetY() != 144.0020);
+                Assert.IsTrue(reader.ReadNext());
+                Assert.IsTrue(!reader.IsNull("Geometry"));
 
-            Assert.IsTrue(reader.ReadNext());
-            Assert.IsTrue(!reader.IsNull("Geometry"));
+                MgByteReader txAgf1 = reader.GetGeometry("Geometry");
+                MgGeometry txGeom1 = agfRw.Read(txAgf1);
+                MgPoint txPt1 = (MgPoint)txGeom1;
+                Assert.IsTrue(txPt1 != null);
+                MgCoordinate txCoord1 = txPt1.GetCoordinate();
 
-            MgByteReader txAgf2 = reader.GetGeometry("Geometry");
-            MgGeometry txGeom2 = agfRw.Read(txAgf2);
-            MgPoint txPt2 = (MgPoint)txGeom2;
-            Assert.IsTrue(txPt2 != null);
-            MgCoordinate txCoord2 = txPt2.GetCoordinate();
+                //TODO: Maybe we should really check that it matches the expected transformed result
+                Assert.IsTrue(txCoord1.GetX() != -37.1020);
+                Assert.IsTrue(txCoord1.GetY() != 144.0020);
 
-            //TODO: Maybe we should really check that it matches the expected transformed result
-            Assert.IsTrue(txCoord2.GetX() != -37.2020);
-            Assert.IsTrue(txCoord2.GetY() != 144.2020);
+                Assert.IsTrue(reader.ReadNext());
+                Assert.IsTrue(!reader.IsNull("Geometry"));
 
-            reader.Close();
+                MgByteReader txAgf2 = reader.GetGeometry("Geometry");
+                MgGeometry txGeom2 = agfRw.Read(txAgf2);
+                MgPoint txPt2 = (MgPoint)txGeom2;
+                Assert.IsTrue(txPt2 != null);
+                MgCoordinate txCoord2 = txPt2.GetCoordinate();
+
+                //TODO: Maybe we should really check that it matches the expected transformed result
+                Assert.IsTrue(txCoord2.GetX() != -37.2020);
+                Assert.IsTrue(txCoord2.GetY() != 144.2020);
+
+                reader.Close();
+            }
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
         }
     }
 
@@ -571,110 +1159,167 @@
         {
             var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
             var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/TransformTest.FeatureSource");
+            try
+            {
+                //Create our test data store
+                MgFeatureSchema fs = new MgFeatureSchema("Default", "");
+                MgClassDefinition cls = new MgClassDefinition();
+                cls.SetName("Test");
 
-            //Create our test data store
-            MgFeatureSchema fs = new MgFeatureSchema("Default", "");
-            MgClassDefinition cls = new MgClassDefinition();
-            cls.SetName("Test");
+                MgDataPropertyDefinition id = new MgDataPropertyDefinition("ID");
+                id.SetAutoGeneration(true);
+                id.SetDataType(MgPropertyType.Int32);
 
-            MgDataPropertyDefinition id = new MgDataPropertyDefinition("ID");
-            id.SetAutoGeneration(true);
-            id.SetDataType(MgPropertyType.Int32);
+                MgGeometricPropertyDefinition geom = new MgGeometricPropertyDefinition("Geometry");
+                geom.SetGeometryTypes(MgFeatureGeometricType.Point);
+                geom.SetSpatialContextAssociation("Default");
 
-            MgGeometricPropertyDefinition geom = new MgGeometricPropertyDefinition("Geometry");
-            geom.SetGeometryTypes(MgFeatureGeometricType.Point);
-            geom.SetSpatialContextAssociation("Default");
+                MgPropertyDefinitionCollection props = cls.GetProperties();
+                MgPropertyDefinitionCollection idProps = cls.GetIdentityProperties();
 
-            MgPropertyDefinitionCollection props = cls.GetProperties();
-            MgPropertyDefinitionCollection idProps = cls.GetIdentityProperties();
+                props.Add(id);
+                props.Add(geom);
+                idProps.Add(id);
 
-            props.Add(id);
-            props.Add(geom);
-            idProps.Add(id);
+                cls.SetDefaultGeometryPropertyName("Geometry");
+                MgClassDefinitionCollection classes = fs.GetClasses();
+                classes.Add(cls);
 
-            cls.SetDefaultGeometryPropertyName("Geometry");
-            MgClassDefinitionCollection classes = fs.GetClasses();
-            classes.Add(cls);
+                //We'll use a transform guaranteed to work. ArbitraryXY (unitA to unitB)
+                //We just check that the transformed values are not the original, that way
+                //we know that CS-Map did its job
+                MgCoordinateSystemFactory csFact = new MgCoordinateSystemFactory();
+                string srcWkt = csFact.ConvertCoordinateSystemCodeToWkt("XY-M");
+                string dstWkt = csFact.ConvertCoordinateSystemCodeToWkt("XY-IN");
 
-            //We'll use a transform guaranteed to work. ArbitraryXY (unitA to unitB)
-            //We just check that the transformed values are not the original, that way
-            //we know that CS-Map did its job
-            MgCoordinateSystemFactory csFact = new MgCoordinateSystemFactory();
-            string srcWkt = csFact.ConvertCoordinateSystemCodeToWkt("XY-M");
-            string dstWkt = csFact.ConvertCoordinateSystemCodeToWkt("XY-IN");
+                MgGeometryFactory geomFact = new MgGeometryFactory();
+                MgAgfReaderWriter agfRw = new MgAgfReaderWriter();
+                MgFileFeatureSourceParams create = new MgFileFeatureSourceParams("OSGeo.SDF", "Default", srcWkt, fs);
 
-            MgGeometryFactory geomFact = new MgGeometryFactory();
-            MgAgfReaderWriter agfRw = new MgAgfReaderWriter();
-            MgFileFeatureSourceParams create = new MgFileFeatureSourceParams("OSGeo.SDF", "Default", srcWkt, fs);
-            MgResourceIdentifier fsId = new MgResourceIdentifier("Library://UnitTests/Data/TransformTest.FeatureSource");
-            featSvc.CreateFeatureSource(fsId, create);
+                featSvc.CreateFeatureSource(fsId, create);
 
-            MgMapBase map = factory.CreateMap(srcWkt, new MgEnvelope(-180, -90, 180, 90), "TestMap");
-            MgLayerCollection layers = map.GetLayers();
+                MgMapBase map = factory.CreateMap(srcWkt, new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
 
-            string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), "Default:Test", "Geometry");
-            byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
-            MgByteSource bs = new MgByteSource(bytes, bytes.Length);
-            MgByteReader br = bs.GetReader();
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), "Default:Test", "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
 
-            var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
-            resSvc.SetResource(ldfId, br, null);
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
 
-            MgLayerBase layer = factory.CreateLayer(ldfId);
-            layers.Insert(0, layer);
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
 
-            //Populate data store with test points
+                //Populate data store with test points
 
-            MgCoordinate coord1 = geomFact.CreateCoordinateXY(-37.1020, 144.0020);
-            MgPoint pt1 = geomFact.CreatePoint(coord1);
-            MgByteReader agf1 = agfRw.Write(pt1);
+                MgCoordinate coord1 = geomFact.CreateCoordinateXY(-37.1020, 144.0020);
+                MgPoint pt1 = geomFact.CreatePoint(coord1);
+                MgByteReader agf1 = agfRw.Write(pt1);
 
-            MgPropertyCollection propVals = new MgPropertyCollection();
-            MgGeometryProperty pGeom = new MgGeometryProperty("Geometry", agf1);
-            propVals.Add(pGeom);
+                MgPropertyCollection propVals = new MgPropertyCollection();
+                MgGeometryProperty pGeom = new MgGeometryProperty("Geometry", agf1);
+                propVals.Add(pGeom);
 
-            MgFeatureReader fr = layer.InsertFeatures(propVals);
-            fr.Close();
+                MgFeatureReader fr = layer.InsertFeatures(propVals, null);
+                fr.Close();
 
-            MgCoordinate coord2 = geomFact.CreateCoordinateXY(-37.2020, 144.2020);
-            MgPoint pt2 = geomFact.CreatePoint(coord2);
-            MgByteReader agf2 = agfRw.Write(pt2);
+                MgCoordinate coord2 = geomFact.CreateCoordinateXY(-37.2020, 144.2020);
+                MgPoint pt2 = geomFact.CreatePoint(coord2);
+                MgByteReader agf2 = agfRw.Write(pt2);
 
-            pGeom.SetValue(agf2);
-            fr = layer.InsertFeatures(propVals);
-            fr.Close();
+                pGeom.SetValue(agf2);
+                fr = layer.InsertFeatures(propVals, null);
+                fr.Close();
 
-            //Now select from this data store
-            MgFeatureQueryOptions query = new MgFeatureQueryOptions();
-            MgReader reader = layer.SelectFeatures(query, dstWkt);
+                //Now select from this data store
+                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
+                MgReader reader = layer.SelectFeatures(query, dstWkt);
 
-            Assert.IsTrue(reader.ReadNext());
-            Assert.IsTrue(!reader.IsNull("Geometry"));
+                Assert.IsTrue(reader.ReadNext());
+                Assert.IsTrue(!reader.IsNull("Geometry"));
 
-            MgByteReader txAgf1 = reader.GetGeometry("Geometry");
-            MgGeometry txGeom1 = agfRw.Read(txAgf1);
-            MgPoint txPt1 = (MgPoint)txGeom1;
-            Assert.IsTrue(txPt1 != null);
-            MgCoordinate txCoord1 = txPt1.GetCoordinate();
+                MgByteReader txAgf1 = reader.GetGeometry("Geometry");
+                MgGeometry txGeom1 = agfRw.Read(txAgf1);
+                MgPoint txPt1 = (MgPoint)txGeom1;
+                Assert.IsTrue(txPt1 != null);
+                MgCoordinate txCoord1 = txPt1.GetCoordinate();
 
-            //TODO: Maybe we should really check that it matches the expected transformed result
-            Assert.IsTrue(txCoord1.GetX() != -37.1020);
-            Assert.IsTrue(txCoord1.GetY() != 144.0020);
+                //TODO: Maybe we should really check that it matches the expected transformed result
+                Assert.IsTrue(txCoord1.GetX() != -37.1020);
+                Assert.IsTrue(txCoord1.GetY() != 144.0020);
 
-            Assert.IsTrue(reader.ReadNext());
-            Assert.IsTrue(!reader.IsNull("Geometry"));
+                Assert.IsTrue(reader.ReadNext());
+                Assert.IsTrue(!reader.IsNull("Geometry"));
 
-            MgByteReader txAgf2 = reader.GetGeometry("Geometry");
-            MgGeometry txGeom2 = agfRw.Read(txAgf2);
-            MgPoint txPt2 = (MgPoint)txGeom2;
-            Assert.IsTrue(txPt2 != null);
-            MgCoordinate txCoord2 = txPt2.GetCoordinate();
+                MgByteReader txAgf2 = reader.GetGeometry("Geometry");
+                MgGeometry txGeom2 = agfRw.Read(txAgf2);
+                MgPoint txPt2 = (MgPoint)txGeom2;
+                Assert.IsTrue(txPt2 != null);
+                MgCoordinate txCoord2 = txPt2.GetCoordinate();
 
-            //TODO: Maybe we should really check that it matches the expected transformed result
-            Assert.IsTrue(txCoord2.GetX() != -37.2020);
-            Assert.IsTrue(txCoord2.GetY() != 144.2020);
+                //TODO: Maybe we should really check that it matches the expected transformed result
+                Assert.IsTrue(txCoord2.GetX() != -37.2020);
+                Assert.IsTrue(txCoord2.GetY() != 144.2020);
 
-            reader.Close();
+                reader.Close();
+            }
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
         }
     }
+
+    public class LayerGetSpatialContexts : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            var resSvc = (MgResourceService)factory.CreateService(MgServiceType.ResourceService);
+            var featSvc = (MgFeatureService)factory.CreateService(MgServiceType.FeatureService);
+            var fsId = new MgResourceIdentifier("Library://UnitTests/Data/GetSpatialContexts.FeatureSource");
+            try
+            {
+                string className = FeatureServiceTestUtil.CreateTestDataStore(fsId, "OSGeo.SDF", featSvc);
+
+                MgCoordinateSystemFactory csFactory = new MgCoordinateSystemFactory();
+                MgMapBase map = factory.CreateMap(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), new MgEnvelope(-180, -90, 180, 90), "TestMap");
+                MgLayerCollection layers = map.GetLayers();
+
+                string layerXml = string.Format(Properties.Resources.TestLayer, fsId.ToString(), className, "Geometry");
+                byte[] bytes = Encoding.UTF8.GetBytes(layerXml);
+                MgByteSource bs = new MgByteSource(bytes, bytes.Length);
+                MgByteReader br = bs.GetReader();
+
+                var ldfId = new MgResourceIdentifier("Library://UnitTests/Layers/TestLayer.LayerDefinition");
+                resSvc.SetResource(ldfId, br, null);
+
+                MgLayerBase layer = factory.CreateLayer(ldfId);
+                layers.Insert(0, layer);
+
+                MgSpatialContextReader scReader = layer.GetSpatialContexts(false);
+                int count = 0;
+                try
+                {
+                    while (scReader.ReadNext())
+                    {
+                        Assert.AreEqual("Default", scReader.GetName());
+                        Assert.AreEqual(csFactory.ConvertCoordinateSystemCodeToWkt("LL84"), scReader.GetCoordinateSystemWkt());
+                        count++;
+                    }
+                }
+                finally
+                {
+                    scReader.Close();
+                }
+                Assert.AreEqual(1, count);
+            }
+            finally
+            {
+                resSvc.DeleteResource(fsId);
+            }
+        }
+    }
 }



More information about the mapguide-commits mailing list