[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mapguide-commits
Subject:    [mapguide-commits] r8264 - in sandbox/jng/convenience_apis: Common/MapGuideCommon/MapLayer Common/Ma
From:       svn_mapguide () osgeo ! org
Date:       2014-06-26 11:37:30
Message-ID: 20140626113730.7AE01390253 () trac ! osgeo ! org
[Download RAW message or body]

Author: jng
Date: 2014-06-26 04:37:30 -0700 (Thu, 26 Jun 2014)
New Revision: 8264

Added:
   sandbox/jng/convenience_apis/Server/src/Services/Feature/OpDeleteFeatures.cpp
   sandbox/jng/convenience_apis/Server/src/Services/Feature/OpDeleteFeatures.h
   sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeatures.cpp
   sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeatures.h
   sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeaturesBatched.cpp
  sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeaturesBatched.h
   sandbox/jng/convenience_apis/Server/src/Services/Feature/OpUpdateMatchingFeatures.cpp
  sandbox/jng/convenience_apis/Server/src/Services/Feature/OpUpdateMatchingFeatures.h
   sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/ConvenienceTests.cs
  sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Properties/Resources.Designer.cs
  sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Properties/Resources.resx
  sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/
   sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/TestLayer.txt
  sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/TestMapDef.txt
 Modified:
   sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.cpp
   sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.h
   sandbox/jng/convenience_apis/Common/MapGuideCommon/Services/ProxyFeatureService.cpp
  sandbox/jng/convenience_apis/Common/MapGuideCommon/Services/ProxyFeatureService.h
   sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.cpp
   sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.h
   sandbox/jng/convenience_apis/Common/PlatformBase/Services/FeatureDefs.h
   sandbox/jng/convenience_apis/Common/PlatformBase/Services/FeatureService.h
   sandbox/jng/convenience_apis/Server/src/Services/Feature/FeatureOperationFactory.cpp
  sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.cpp
   sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.h
   sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.vcxproj
  sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.vcxproj.filters
  sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureServiceBuild.cpp
  sandbox/jng/convenience_apis/Server/src/UnitTesting/TestFeatureService.cpp
   sandbox/jng/convenience_apis/Server/src/UnitTesting/TestFeatureService.h
   sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/MgTestRunner/Program.cs
   sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/CommonTests.cs
   sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/CollectionTests.cs
  sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/PropertiesTest.cs
  sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/TestCommon.csproj
   sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestMapGuideApi/ExternalTests/CollectionTests.cs
 Log:
Add new convenience APIs to MgFeatureService and MgLayerBase:

 * InsertFeatures - Inserts one or more features to the specified feature source
 * UpdateMatchingFeatures - Updates one or more features in the specified feature \
                source
 * DeleteFeatures - Deletes one or more features in the specified feature source

These APIs are much simpler to use than UpdateFeatures and require less boilerplate \
and have simpler exception handling logic (all of the above APIs *will* throw \
exceptions on any error, transactional or not).

Use the external test mechanism introduced in the previous submission to add new .net \
tests to exercise these new convenience APIs

Modified: sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.cpp
===================================================================
--- sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.cpp	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -307,6 +307,23 @@
 
     MG_TRY()
 
+    Ptr<MgResourceIdentifier> resourceId = new \
MgResourceIdentifier(m_featureSourceId); +    STRING providerName = \
GetProviderName(); +    // Determine if the provider supports transactions.
+    Ptr<MgFeatureService> featureService = dynamic_cast<MgFeatureService*>(
+        GetMap()->GetService(MgServiceType::FeatureService));
+
+    bool useTransaction = UseTransaction(featureService, providerName);
+
+    propCol = featureService->UpdateFeatures(resourceId, commands, useTransaction);
+
+    MG_CATCH_AND_THROW(L"MgLayer.UpdateFeatures")
+
+    return propCol.Detach();
+}
+
+STRING MgLayer::GetProviderName()
+{
     // Get the content of the feature source.
     Ptr<MgResourceService> resourceService = dynamic_cast<MgResourceService*>(
         GetMap()->GetService(MgServiceType::ResourceService));
@@ -332,15 +349,14 @@
     featureSource.reset(parser.DetachFeatureSource());
 
     // Get the provider name.
-    STRING providerName = (STRING)featureSource->GetProvider();
+    return (STRING)featureSource->GetProvider();
+}
 
-    // Determine if the provider supports transactions.
+bool MgLayer::UseTransaction(MgFeatureService* featureService, CREFSTRING \
providerName) +{
     bool useTransaction = false;
-    Ptr<MgFeatureService> featureService = dynamic_cast<MgFeatureService*>(
-        GetMap()->GetService(MgServiceType::FeatureService));
-
-    byteReader = featureService->GetCapabilities(providerName);
-    xmlContent.clear();
+    Ptr<MgByteReader> byteReader = featureService->GetCapabilities(providerName);
+    std::string xmlContent;
     byteReader->ToStringUtf8(xmlContent);
 
     const string openTag = "<SupportsTransactions>"; //NOXLATE
@@ -363,12 +379,7 @@
             useTransaction = MgUtil::StringToBoolean(tagValue);
         }
     }
-
-    propCol = featureService->UpdateFeatures(resourceId, commands, useTransaction);
-
-    MG_CATCH_AND_THROW(L"MgLayer.UpdateFeatures")
-
-    return propCol.Detach();
+    return useTransaction;
 }
 
 void MgLayer::ParseFeatureName(MgFeatureService* featureService, REFSTRING \
className, REFSTRING schemaName) @@ -423,3 +434,111 @@
         m_idProps.push_back(idProp);
     }
 }
+
+MgFeatureReader* MgLayer::InsertFeatures(MgPropertyCollection* properties)
+{
+    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);
+    if (NULL != trans.p)
+        trans->Commit();
+
+    MG_CATCH(L"MgLayer.InsertFeatures")
+
+    if (NULL != trans.p)
+        trans->Rollback();
+
+    MG_THROW()
+
+    return ret.Detach();
+}
+
+MgFeatureReader* MgLayer::InsertFeatures(MgBatchPropertyCollection* properties)
+{
+    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);
+    if (NULL != trans.p)
+        trans->Commit();
+
+    MG_CATCH(L"MgLayer.InsertFeatures")
+
+    if (NULL != trans.p)
+        trans->Rollback();
+
+    MG_THROW()
+
+    return ret.Detach();
+}
+
+INT32 MgLayer::UpdateMatchingFeatures(MgPropertyCollection* properties, CREFSTRING \
filter) +{
+    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); +    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)
+{
+    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);
+    if (NULL != trans.p)
+        trans->Commit();
+
+    MG_CATCH(L"MgLayer.DeleteFeatures")
+
+    if (NULL != trans.p)
+        trans->Rollback();
+
+    MG_THROW()
+
+    return deleted;
+}

Modified: sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.h
===================================================================
--- sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.h	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Common/MapGuideCommon/MapLayer/Layer.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -224,6 +224,143 @@
     ///
     virtual MgPropertyCollection* UpdateFeatures(MgFeatureCommandCollection* \
commands);  
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a new feature into the specified feature class of the specified \
Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgPropertyCollection properties);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgPropertyCollection properties);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgPropertyCollection properties);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param properties (MgPropertyCollection)
+    /// The collection of property values to insert
+    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Transactions will be used internally if the provider supports them.
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgPropertyCollection* properties);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a set of new features into the specified feature class of the \
specified Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgBatchPropertyCollection \
properties); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgBatchPropertyCollection \
properties); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgBatchPropertyCollection \
properties); +    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param properties (MgBatchPropertyCollection)
+    /// The collection of property values to insert. Each MgPropertyCollection \
within  +    /// this collection represents property values for a single feature to \
insert +    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Transactions will be used internally if the provider supports them.
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgBatchPropertyCollection* properties);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Updates all features that match the given filter with the specified property \
values +    ///
+    /// \remarks
+    /// Transactions will be used internally if the provider supports them
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgPropertyCollection properties, string \
filter); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgPropertyCollection properties, String \
filter); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgPropertyCollection properties, String \
filter); +    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param properties (MgBatchPropertyCollection)
+    /// The property values to update matching features with
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be updated
+    ///
+    /// \return
+    /// Returns the number of features updated by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 UpdateMatchingFeatures(MgPropertyCollection* properties, \
CREFSTRING filter); +
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Deletes all features that match the given filter
+    ///
+    /// \remarks
+    /// Transactions will be used internally if the provider supports them
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int DeleteFeatures(string filter);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int DeleteFeatures(String filter);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int DeleteFeatures(String filter);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be deleted
+    ///
+    /// \return
+    /// Returns the number of features deleted by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 DeleteFeatures(CREFSTRING filter);
+
 INTERNAL_API:
 
     //////////////////////////////////////////////////////////////////
@@ -308,6 +445,8 @@
     }
 
 private:
+    STRING GetProviderName();
+    bool UseTransaction(MgFeatureService* svcFeature, CREFSTRING providerName);
 
     MgMapBase* GetMap();
 

Modified: sandbox/jng/convenience_apis/Common/MapGuideCommon/Services/ProxyFeatureService.cpp
 ===================================================================
--- sandbox/jng/convenience_apis/Common/MapGuideCommon/Services/ProxyFeatureService.cpp	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Common/MapGuideCommon/Services/ProxyFeatureService.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -1897,3 +1897,228 @@
     SetWarning(cmd.GetWarningObject());
     return cmd.GetReturnValue().val.m_i8;
 }
+
+MgFeatureReader* MgProxyFeatureService::InsertFeatures(MgResourceIdentifier* \
resource, +                                                       CREFSTRING \
className, +                                                       \
MgPropertyCollection* propertyValues) +
+{
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                  // Connection
+                       MgCommand::knObject,                         // Return type \
expected +                       MgFeatureServiceOpId::InsertFeatures,        // \
Command Code +                       3,                                           // \
No of arguments +                       Feature_Service,                             \
// Service Id +                       BUILD_VERSION(3,0,0),                        // \
Operation version +                       MgCommand::knObject, resource,              \
// Argument#1 +                       MgCommand::knString, &className,             // \
Argument#2 +                       MgCommand::knObject, propertyValues,         // \
Argument#3 +                       MgCommand::knNone);                          // \
End of argument +
+    SetWarning(cmd.GetWarningObject());
+
+    Ptr<MgProxyFeatureReader> featReader = \
(MgProxyFeatureReader*)cmd.GetReturnValue().val.m_obj; +
+    if (featReader != NULL)
+        featReader->SetService(this); // Feature reader on proxy side would store \
proxy service to call GetFeatures() +
+    return SAFE_ADDREF((MgProxyFeatureReader*)featReader);
+}
+
+MgFeatureReader* MgProxyFeatureService::InsertFeatures(MgResourceIdentifier* \
resource, +                                                       CREFSTRING \
className, +                                                       \
MgPropertyCollection* propertyValues, +                                               \
MgTransaction* transaction) +{
+    STRING transactionId = L"";
+    MgProxyFeatureTransaction* proxyTransaction = \
dynamic_cast<MgProxyFeatureTransaction*>(transaction); +    if (NULL != \
proxyTransaction) +    {
+        transactionId = proxyTransaction->GetTransactionId();
+    }
+
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                  // Connection
+                       MgCommand::knObject,                         // Return type \
expected +                       MgFeatureServiceOpId::InsertFeatures,        // \
Command Code +                       4,                                           // \
No of arguments +                       Feature_Service,                             \
// Service Id +                       BUILD_VERSION(3,0,0),                        // \
Operation version +                       MgCommand::knObject, resource,              \
// Argument#1 +                       MgCommand::knString, &className,             // \
Argument#2 +                       MgCommand::knObject, propertyValues,         // \
Argument#3 +                       MgCommand::knString, &transactionId,         // \
Argument#4 +                       MgCommand::knNone);                          // \
End of argument +
+    SetWarning(cmd.GetWarningObject());
+
+    Ptr<MgProxyFeatureReader> featReader = \
(MgProxyFeatureReader*)cmd.GetReturnValue().val.m_obj; +
+    if (featReader != NULL)
+        featReader->SetService(this); // Feature reader on proxy side would store \
proxy service to call GetFeatures() +
+    return SAFE_ADDREF((MgProxyFeatureReader*)featReader);
+}
+
+MgFeatureReader* MgProxyFeatureService::InsertFeatures(MgResourceIdentifier* \
resource, +                                                       CREFSTRING \
className, +                                                       \
MgBatchPropertyCollection* batchPropertyValues) +{
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                  // Connection
+                       MgCommand::knObject,                         // Return type \
expected +                       MgFeatureServiceOpId::InsertFeatures2,       // \
Command Code +                       3,                                           // \
No of arguments +                       Feature_Service,                             \
// Service Id +                       BUILD_VERSION(3,0,0),                        // \
Operation version +                       MgCommand::knObject, resource,              \
// Argument#1 +                       MgCommand::knString, &className,             // \
Argument#2 +                       MgCommand::knObject, batchPropertyValues,    // \
Argument#3 +                       MgCommand::knNone);                          // \
End of argument +
+    SetWarning(cmd.GetWarningObject());
+
+    Ptr<MgProxyFeatureReader> featReader = \
(MgProxyFeatureReader*)cmd.GetReturnValue().val.m_obj; +
+    if (featReader != NULL)
+        featReader->SetService(this); // Feature reader on proxy side would store \
proxy service to call GetFeatures() +
+    return SAFE_ADDREF((MgProxyFeatureReader*)featReader);
+}
+
+MgFeatureReader* MgProxyFeatureService::InsertFeatures(MgResourceIdentifier* \
resource, +                                                       CREFSTRING \
className, +                                                       \
MgBatchPropertyCollection* batchPropertyValues, +                                     \
MgTransaction* transaction) +{
+    STRING transactionId = L"";
+    MgProxyFeatureTransaction* proxyTransaction = \
dynamic_cast<MgProxyFeatureTransaction*>(transaction); +    if (NULL != \
proxyTransaction) +    {
+        transactionId = proxyTransaction->GetTransactionId();
+    }
+
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                  // Connection
+                       MgCommand::knObject,                         // Return type \
expected +                       MgFeatureServiceOpId::InsertFeatures2,       // \
Command Code +                       4,                                           // \
No of arguments +                       Feature_Service,                             \
// Service Id +                       BUILD_VERSION(3,0,0),                        // \
Operation version +                       MgCommand::knObject, resource,              \
// Argument#1 +                       MgCommand::knString, &className,             // \
Argument#2 +                       MgCommand::knObject, batchPropertyValues,    // \
Argument#3 +                       MgCommand::knString, &transactionId,         // \
Argument#4 +                       MgCommand::knNone);                          // \
End of argument +
+    SetWarning(cmd.GetWarningObject());
+
+    Ptr<MgProxyFeatureReader> featReader = \
(MgProxyFeatureReader*)cmd.GetReturnValue().val.m_obj; +
+    if (featReader != NULL)
+        featReader->SetService(this); // Feature reader on proxy side would store \
proxy service to call GetFeatures() +
+    return SAFE_ADDREF((MgProxyFeatureReader*)featReader);
+}
+
+INT32 MgProxyFeatureService::UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                                    CREFSTRING className,
+                                                    MgPropertyCollection* \
propertyValues, +                                                    CREFSTRING \
filter) +{
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                  // Connection
+                       MgCommand::knInt32,                          // Return type \
expected +                       MgFeatureServiceOpId::UpdateMatchingFeatures,// \
Command Code +                       4,                                           // \
No of arguments +                       Feature_Service,                             \
// Service Id +                       BUILD_VERSION(3,0,0),                        // \
Operation version +                       MgCommand::knObject, resource,              \
// Argument#1 +                       MgCommand::knString, &className,             // \
Argument#2 +                       MgCommand::knObject, propertyValues,         // \
Argument#3 +                       MgCommand::knString, &filter,                // \
Argument#4 +                       MgCommand::knNone);                          // \
End of argument +
+    SetWarning(cmd.GetWarningObject());
+    return cmd.GetReturnValue().val.m_i32;
+}
+
+INT32 MgProxyFeatureService::UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                                    CREFSTRING className,
+                                                    MgPropertyCollection* \
propertyValues, +                                                    CREFSTRING \
filter, +                                                    MgTransaction* \
transaction) +{
+    STRING transactionId = L"";
+    MgProxyFeatureTransaction* proxyTransaction = \
dynamic_cast<MgProxyFeatureTransaction*>(transaction); +    if (NULL != \
proxyTransaction) +    {
+        transactionId = proxyTransaction->GetTransactionId();
+    }
+
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                  // Connection
+                       MgCommand::knInt32,                          // Return type \
expected +                       MgFeatureServiceOpId::UpdateMatchingFeatures,// \
Command Code +                       5,                                           // \
No of arguments +                       Feature_Service,                             \
// Service Id +                       BUILD_VERSION(3,0,0),                        // \
Operation version +                       MgCommand::knObject, resource,              \
// Argument#1 +                       MgCommand::knString, &className,             // \
Argument#2 +                       MgCommand::knObject, propertyValues,         // \
Argument#3 +                       MgCommand::knString, &filter,                // \
Argument#4 +                       MgCommand::knString, &transactionId,         // \
Argument#5 +                       MgCommand::knNone);                          // \
End of argument +
+    SetWarning(cmd.GetWarningObject());
+    return cmd.GetReturnValue().val.m_i32;
+}
+
+INT32 MgProxyFeatureService::DeleteFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            CREFSTRING filter)
+{
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                  // Connection
+                       MgCommand::knInt32,                          // Return type \
expected +                       MgFeatureServiceOpId::DeleteFeatures,        // \
Command Code +                       3,                                           // \
No of arguments +                       Feature_Service,                             \
// Service Id +                       BUILD_VERSION(3,0,0),                        // \
Operation version +                       MgCommand::knObject, resource,              \
// Argument#1 +                       MgCommand::knString, &className,             // \
Argument#2 +                       MgCommand::knString, &filter,                // \
Argument#3 +                       MgCommand::knNone);                          // \
End of argument +
+    SetWarning(cmd.GetWarningObject());
+    return cmd.GetReturnValue().val.m_i32;
+}
+
+INT32 MgProxyFeatureService::DeleteFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            CREFSTRING filter,
+                                            MgTransaction* transaction)
+{
+    STRING transactionId = L"";
+    MgProxyFeatureTransaction* proxyTransaction = \
dynamic_cast<MgProxyFeatureTransaction*>(transaction); +    if (NULL != \
proxyTransaction) +    {
+        transactionId = proxyTransaction->GetTransactionId();
+    }
+
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                  // Connection
+                       MgCommand::knInt32,                          // Return type \
expected +                       MgFeatureServiceOpId::DeleteFeatures,        // \
Command Code +                       4,                                           // \
No of arguments +                       Feature_Service,                             \
// Service Id +                       BUILD_VERSION(3,0,0),                        // \
Operation version +                       MgCommand::knObject, resource,              \
// Argument#1 +                       MgCommand::knString, &className,             // \
Argument#2 +                       MgCommand::knString, &filter,                // \
Argument#3 +                       MgCommand::knString, &transactionId,         // \
Argument#4 +                       MgCommand::knNone);                          // \
End of argument +
+    SetWarning(cmd.GetWarningObject());
+    return cmd.GetReturnValue().val.m_i32;
+}
\ No newline at end of file

Modified: sandbox/jng/convenience_apis/Common/MapGuideCommon/Services/ProxyFeatureService.h
 ===================================================================
--- sandbox/jng/convenience_apis/Common/MapGuideCommon/Services/ProxyFeatureService.h	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Common/MapGuideCommon/Services/ProxyFeatureService.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -659,6 +659,342 @@
                                          MgFeatureCommandCollection* commands,
                                          MgTransaction* transaction);
 
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a new feature into the specified feature class of the specified \
Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, string \
className, MgPropertyCollection propertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection propertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection propertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the insert operation is performed.
+    /// \param propertyValues (MgPropertyCollection)
+    /// The collection of property values to insert
+    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgPropertyCollection* propertyValues);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a new feature into the specified feature class of the specified \
Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, string \
className, MgPropertyCollection propertyValues, MgTransaction trans); +    /// \
\htmlinclude SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection propertyValues, MgTransaction trans); +    /// \
\htmlinclude SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection propertyValues, MgTransaction trans); +    /// \
\htmlinclude SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the insert operation is performed.
+    /// \param propertyValues (MgPropertyCollection)
+    /// The collection of property values to insert
+    /// \param trans (MgTransaction)
+    /// The transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgPropertyCollection* propertyValues,
+                                            MgTransaction* trans);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a set of new features into the specified feature class of the \
specified Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, string \
className, MgBatchPropertyCollection batchPropertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgBatchPropertyCollection batchPropertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgBatchPropertyCollection batchPropertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the insert operation is performed.
+    /// \param batchPropertyValues (MgBatchPropertyCollection)
+    /// The collection of property values to insert. Each MgPropertyCollection \
within  +    /// this collection represents property values for a single feature to \
insert +    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgBatchPropertyCollection* \
batchPropertyValues); +
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a set of new features into the specified feature class of the \
specified Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, string \
className, MgBatchPropertyCollection batchPropertyValues, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgBatchPropertyCollection batchPropertyValues, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgBatchPropertyCollection batchPropertyValues, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the insert operation is performed.
+    /// \param batchPropertyValues (MgBatchPropertyCollection)
+    /// The collection of property values to insert. Each MgPropertyCollection \
within  +    /// this collection represents property values for a single feature to \
insert +    /// \param trans (MgTransaction)
+    /// The transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgBatchPropertyCollection* \
batchPropertyValues, +                                            MgTransaction* \
trans); +
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Updates all features that match the given filter with the specified property \
values +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, string \
className, MgPropertyCollection properties, string filter); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection properties, String filter); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection properties, String filter); +    /// \htmlinclude \
SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the update operation is performed.
+    /// \param properties (MgBatchPropertyCollection)
+    /// The property values to update matching features with
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be updated
+    ///
+    /// \return
+    /// Returns the number of features updated by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                         CREFSTRING className,
+                                         MgPropertyCollection* properties,
+                                         CREFSTRING filter);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Updates all features that match the given filter with the specified property \
values +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, string \
className, MgPropertyCollection properties, string filter, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection properties, String filter, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection properties, String filter, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the update operation is performed.
+    /// \param properties (MgBatchPropertyCollection)
+    /// The property values to update matching features with
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be updated
+    /// \param trans (MgTransaction)
+    /// The transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns the number of features updated by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                         CREFSTRING className,
+                                         MgPropertyCollection* properties,
+                                         CREFSTRING filter,
+                                         MgTransaction* trans);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Deletes all features that match the given filter
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, string className, \
string filter); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, String className, \
String filter); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, String className, \
String filter); +    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the delete operation is performed.
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be deleted
+    ///
+    /// \return
+    /// Returns the number of features deleted by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 DeleteFeatures(MgResourceIdentifier* resource,
+                                 CREFSTRING className,
+                                 CREFSTRING filter);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Deletes all features that match the given filter
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, string className, \
string filter, MgTransaction trans); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, String className, \
String filter, MgTransaction trans); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, String className, \
String filter, MgTransaction trans); +    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the delete operation is performed.
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be deleted
+    /// \param trans (MgTransaction)
+    /// The transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns the number of features deleted by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 DeleteFeatures(MgResourceIdentifier* resource,
+                                 CREFSTRING className,
+                                 CREFSTRING filter,
+                                 MgTransaction* trans);
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief
     /// Gets the locked features

Modified: sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.cpp
===================================================================
--- sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.cpp	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -799,3 +799,27 @@
     throw new MgNotImplementedException(L"MgLayerBase.UpdateFeatures",
         __LINE__, __WFILE__, NULL, L"", NULL);
 }
+
+MgFeatureReader* MgLayerBase::InsertFeatures(MgPropertyCollection* properties)
+{
+    throw new MgNotImplementedException(L"MgLayerBase.InsertFeatures",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+MgFeatureReader* MgLayerBase::InsertFeatures(MgBatchPropertyCollection* properties)
+{
+    throw new MgNotImplementedException(L"MgLayerBase.InsertFeatures",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+INT32 MgLayerBase::UpdateMatchingFeatures(MgPropertyCollection* properties, \
CREFSTRING filter) +{
+    throw new MgNotImplementedException(L"MgLayerBase.UpdateMatchingFeatures",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+INT32 MgLayerBase::DeleteFeatures(CREFSTRING filter)
+{
+    throw new MgNotImplementedException(L"MgLayerBase.DeleteFeatures",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}

Modified: sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.h
===================================================================
--- sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.h	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Common/PlatformBase/MapLayer/LayerBase.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -870,6 +870,143 @@
     /// \since 1.2
     virtual MgPropertyCollection* UpdateFeatures(MgFeatureCommandCollection* \
commands);  
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a new feature into the specified feature class of the specified \
Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgPropertyCollection properties);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgPropertyCollection properties);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgPropertyCollection properties);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param properties (MgPropertyCollection)
+    /// The collection of property values to insert
+    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Transactions will be used internally if the provider supports them.
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgPropertyCollection* properties);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a set of new features into the specified feature class of the \
specified Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgBatchPropertyCollection \
properties); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgBatchPropertyCollection \
properties); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgBatchPropertyCollection \
properties); +    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param properties (MgBatchPropertyCollection)
+    /// The collection of property values to insert. Each MgPropertyCollection \
within  +    /// this collection represents property values for a single feature to \
insert +    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Transactions will be used internally if the provider supports them.
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgBatchPropertyCollection* properties);
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Updates all features that match the given filter with the specified property \
values +    ///
+    /// \remarks
+    /// Transactions will be used internally if the provider supports them
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgPropertyCollection properties, string \
filter); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgPropertyCollection properties, String \
filter); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgPropertyCollection properties, String \
filter); +    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param properties (MgBatchPropertyCollection)
+    /// The property values to update matching features with
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be updated
+    ///
+    /// \return
+    /// Returns the number of features updated by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 UpdateMatchingFeatures(MgPropertyCollection* properties, \
CREFSTRING filter); +
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Deletes all features that match the given filter
+    ///
+    /// \remarks
+    /// Transactions will be used internally if the provider supports them
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int DeleteFeatures(string filter);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int DeleteFeatures(String filter);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int DeleteFeatures(String filter);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be deleted
+    ///
+    /// \return
+    /// Returns the number of features deleted by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 DeleteFeatures(CREFSTRING filter);
+
 INTERNAL_API:
 
     static MdfModel::LayerDefinition* GetLayerDefinition(MgResourceService* \
svcResource, MgResourceIdentifier* resId);

Modified: sandbox/jng/convenience_apis/Common/PlatformBase/Services/FeatureDefs.h
===================================================================
--- sandbox/jng/convenience_apis/Common/PlatformBase/Services/FeatureDefs.h	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Common/PlatformBase/Services/FeatureDefs.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -77,6 +77,11 @@
     static const int AddSavePoint_Id                      = 0x1111ED2E;
     static const int RollbackSavePoint_Id                 = 0x1111ED2F;
     static const int ReleaseSavePoint_Id                  = 0x1111ED30;
+
+    static const int InsertFeatures         = 0x1111ED31;
+    static const int InsertFeatures2        = 0x1111ED32;
+    static const int UpdateMatchingFeatures = 0x1111ED33;
+    static const int DeleteFeatures         = 0x1111ED34;
 };
 /// \endcond
 

Modified: sandbox/jng/convenience_apis/Common/PlatformBase/Services/FeatureService.h
===================================================================
--- sandbox/jng/convenience_apis/Common/PlatformBase/Services/FeatureService.h	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Common/PlatformBase/Services/FeatureService.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -982,6 +982,342 @@
                                                  MgFeatureCommandCollection* \
                commands,
                                                  MgTransaction* transaction) = 0;
 
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a new feature into the specified feature class of the specified \
Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, string \
className, MgPropertyCollection propertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection propertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection propertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the insert operation is performed.
+    /// \param propertyValues (MgPropertyCollection)
+    /// The collection of property values to insert
+    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgPropertyCollection* propertyValues) = \
0; +
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a new feature into the specified feature class of the specified \
Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, string \
className, MgPropertyCollection propertyValues, MgTransaction trans); +    /// \
\htmlinclude SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection propertyValues, MgTransaction trans); +    /// \
\htmlinclude SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection propertyValues, MgTransaction trans); +    /// \
\htmlinclude SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the insert operation is performed.
+    /// \param propertyValues (MgPropertyCollection)
+    /// The collection of property values to insert
+    /// \param trans (MgTransaction)
+    /// The transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgPropertyCollection* propertyValues,
+                                            MgTransaction* trans) = 0;
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a set of new features into the specified feature class of the \
specified Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, string \
className, MgBatchPropertyCollection batchPropertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgBatchPropertyCollection batchPropertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgBatchPropertyCollection batchPropertyValues); +    /// \htmlinclude \
SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the insert operation is performed.
+    /// \param batchPropertyValues (MgBatchPropertyCollection)
+    /// The collection of property values to insert. Each MgPropertyCollection \
within  +    /// this collection represents property values for a single feature to \
insert +    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgBatchPropertyCollection* \
batchPropertyValues) = 0; +
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Inserts a set of new features into the specified feature class of the \
specified Feature Source +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, string \
className, MgBatchPropertyCollection batchPropertyValues, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgBatchPropertyCollection batchPropertyValues, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual MgFeatureReader InsertFeatures(MgResourceIdentifier resource, String \
className, MgBatchPropertyCollection batchPropertyValues, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the insert operation is performed.
+    /// \param batchPropertyValues (MgBatchPropertyCollection)
+    /// The collection of property values to insert. Each MgPropertyCollection \
within  +    /// this collection represents property values for a single feature to \
insert +    /// \param trans (MgTransaction)
+    /// The transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns a feature reader object that contains the set of properties 
+    /// inserted into the datastore by the insert command.
+    ///
+    /// \remarks
+    /// Remember to close any feature readers returned by this method, even if you \
don't intend +    /// to do anything with them
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgBatchPropertyCollection* \
batchPropertyValues, +                                            MgTransaction* \
trans) = 0; +
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Updates all features that match the given filter with the specified property \
values +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, string \
className, MgPropertyCollection properties, string filter); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection properties, String filter); +    /// \htmlinclude \
SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection properties, String filter); +    /// \htmlinclude \
SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the update operation is performed.
+    /// \param properties (MgBatchPropertyCollection)
+    /// The property values to update matching features with
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be updated
+    ///
+    /// \return
+    /// Returns the number of features updated by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                         CREFSTRING className,
+                                         MgPropertyCollection* properties,
+                                         CREFSTRING filter) = 0;
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Updates all features that match the given filter with the specified property \
values +    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, string \
className, MgPropertyCollection properties, string filter, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection properties, String filter, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int UpdateMatchingFeatures(MgResourceIdentifier resource, String \
className, MgPropertyCollection properties, String filter, MgTransaction trans); +    \
/// \htmlinclude SyntaxBottom.html +    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the update operation is performed.
+    /// \param properties (MgBatchPropertyCollection)
+    /// The property values to update matching features with
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be updated
+    /// \param trans (MgTransaction)
+    /// The transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns the number of features updated by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                         CREFSTRING className,
+                                         MgPropertyCollection* properties,
+                                         CREFSTRING filter,
+                                         MgTransaction* trans) = 0;
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Deletes all features that match the given filter
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, string className, \
string filter); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, String className, \
String filter); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, String className, \
String filter); +    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the delete operation is performed.
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be deleted
+    ///
+    /// \return
+    /// Returns the number of features deleted by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 DeleteFeatures(MgResourceIdentifier* resource,
+                                 CREFSTRING className,
+                                 CREFSTRING filter) = 0;
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +    /// \brief
+    /// Deletes all features that match the given filter
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, string className, \
string filter, MgTransaction trans); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, String className, \
String filter, MgTransaction trans); +    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual int DeleteFeatures(MgResourceIdentifier resource, String className, \
String filter, MgTransaction trans); +    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param resource (MgResourceIdentifier)
+    /// A resource identifier for the feature
+    /// source.
+    /// \param className (String/string)
+    /// The name of the feature class on which
+    /// the delete operation is performed.
+    /// \param filter (String/string)
+    /// The FDO filter string that detemines what features will be deleted
+    /// \param trans (MgTransaction)
+    /// The transaction to execute this operation under
+    ///
+    /// \return
+    /// Returns the number of features deleted by this operation
+    ///
+    /// \exception MgFeatureServiceException
+    /// \exception MgInvalidArgumentException
+    /// \exception MgInvalidOperationException
+    /// \exception MgFdoException
+    ///
+    /// \since 3.0
+    virtual INT32 DeleteFeatures(MgResourceIdentifier* resource,
+                                 CREFSTRING className,
+                                 CREFSTRING filter,
+                                 MgTransaction* trans) = 0;
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief
     /// Gets the locked features

Modified: sandbox/jng/convenience_apis/Server/src/Services/Feature/FeatureOperationFactory.cpp
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/FeatureOperationFactory.cpp	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/FeatureOperationFactory.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -36,6 +36,10 @@
 #include "OpTestConnection.h"
 #include "OpTestFeatureSourceConnection.h"
 #include "OpUpdateFeatures.h"
+#include "OpInsertFeatures.h"
+#include "OpInsertFeaturesBatched.h"
+#include "OpUpdateMatchingFeatures.h"
+#include "OpDeleteFeatures.h"
 #include "OpGetFeatures.h"
 #include "OpCloseFeatureReader.h"
 #include "OpGetLongTransactions.h"
@@ -332,6 +336,54 @@
         }
         break;
 
+    case MgFeatureServiceOpId::InsertFeatures:
+        switch (VERSION_NO_PHASE(operationVersion))
+        {
+        case VERSION_SUPPORTED(3,0):
+            handler.reset(new MgOpInsertFeatures());
+            break;
+        default:
+            throw new MgInvalidOperationVersionException(
+                L"MgFeatureOperationFactory.GetOperation", __LINE__, __WFILE__, \
NULL, L"", NULL); +        }
+        break;
+
+    case MgFeatureServiceOpId::InsertFeatures2:
+        switch (VERSION_NO_PHASE(operationVersion))
+        {
+        case VERSION_SUPPORTED(3,0):
+            handler.reset(new MgOpInsertFeaturesBatched());
+            break;
+        default:
+            throw new MgInvalidOperationVersionException(
+                L"MgFeatureOperationFactory.GetOperation", __LINE__, __WFILE__, \
NULL, L"", NULL); +        }
+        break;
+
+    case MgFeatureServiceOpId::UpdateMatchingFeatures:
+        switch (VERSION_NO_PHASE(operationVersion))
+        {
+        case VERSION_SUPPORTED(3,0):
+            handler.reset(new MgOpUpdateMatchingFeatures());
+            break;
+        default:
+            throw new MgInvalidOperationVersionException(
+                L"MgFeatureOperationFactory.GetOperation", __LINE__, __WFILE__, \
NULL, L"", NULL); +        }
+        break;
+
+    case MgFeatureServiceOpId::DeleteFeatures:
+        switch (VERSION_NO_PHASE(operationVersion))
+        {
+        case VERSION_SUPPORTED(3,0):
+            handler.reset(new MgOpDeleteFeatures());
+            break;
+        default:
+            throw new MgInvalidOperationVersionException(
+                L"MgFeatureOperationFactory.GetOperation", __LINE__, __WFILE__, \
NULL, L"", NULL); +        }
+        break;
+
     case MgFeatureServiceOpId::GetFeatures_Id:
         switch (VERSION_NO_PHASE(operationVersion))
         {

Added: sandbox/jng/convenience_apis/Server/src/Services/Feature/OpDeleteFeatures.cpp
===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/OpDeleteFeatures.cpp	    \
                (rev 0)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/OpDeleteFeatures.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,150 @@
+//
+//  Copyright (C) 2004-2014 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#include "OpDeleteFeatures.h"
+#include "ServerFeatureTransactionPool.h"
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Constructs the object.
+/// </summary>
+///----------------------------------------------------------------------------
+MgOpDeleteFeatures::MgOpDeleteFeatures()
+{
+}
+
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Destructs the object.
+/// </summary>
+///----------------------------------------------------------------------------
+MgOpDeleteFeatures::~MgOpDeleteFeatures()
+{
+}
+
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Executes the operation.
+/// </summary>
+///
+/// <exceptions>
+/// MgException
+/// </exceptions>
+///----------------------------------------------------------------------------
+void MgOpDeleteFeatures::Execute()
+{
+    ACE_DEBUG((LM_DEBUG, ACE_TEXT("  (%t) MgOpDeleteFeatures::Execute()\n")));
+
+    MG_LOG_OPERATION_MESSAGE(L"DeleteFeatures");
+
+    MG_FEATURE_SERVICE_TRY()
+
+    MG_LOG_OPERATION_MESSAGE_INIT(m_packet.m_OperationVersion, \
m_packet.m_NumArguments); +
+    ACE_ASSERT(m_stream != NULL);
+
+    if (3 == m_packet.m_NumArguments)
+    {
+        Ptr<MgResourceIdentifier> resource = \
(MgResourceIdentifier*)m_stream->GetObject(); +        STRING className;
+        m_stream->GetString(className);
+        STRING filter;
+        m_stream->GetString(filter);
+        
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? \
L"MgResourceIdentifier" : resource->ToString().c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(className.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(filter.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_PARAMETERS_END(); +
+        Validate();
+
+        // Execute the operation
+        INT32 result = m_service->DeleteFeatures(resource, className, filter);
+
+        // Write the response
+        EndExecution(result);
+    }
+    if (4 == m_packet.m_NumArguments)
+    {
+        Ptr<MgResourceIdentifier> resource = \
(MgResourceIdentifier*)m_stream->GetObject(); +        STRING className;
+        m_stream->GetString(className);
+        STRING filter;
+        m_stream->GetString(filter);
+        STRING transactionId;
+        m_stream->GetString(transactionId);
+        
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? \
L"MgResourceIdentifier" : resource->ToString().c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(className.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(filter.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_PARAMETERS_END(); +
+        Validate();
+
+        MgServerFeatureTransactionPool* transactionPool = \
MgServerFeatureTransactionPool::GetInstance(); +        CHECKNULL(transactionPool, \
L"MgOpDeleteFeatures.Execute") +
+        transactionPool->ValidateTimeout(transactionId);
+
+        // Get the MgTransaction instance from the pool if one has been started for \
this resource. +        Ptr<MgServerFeatureTransaction> transaction = \
transactionPool->GetTransaction(transactionId); +
+        // Execute the operation
+        INT32 result = m_service->DeleteFeatures(resource, className, filter, \
(MgTransaction*)transaction.p); +
+        // Write the response
+        EndExecution(result);
+    }
+    else
+    {
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
+    }
+
+    if (!m_argsRead)
+    {
+        throw new MgOperationProcessingException(L"MgOpDeleteFeatures.Execute",
+            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    // Successful operation
+    MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Success.c_str());
+
+    MG_FEATURE_SERVICE_CATCH(L"MgOpDeleteFeatures.Execute")
+
+    if (mgException != NULL)
+    {
+        // Failed operation
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Failure.c_str());
+    }
+
+    // Add access log entry for operation
+    MG_LOG_OPERATION_MESSAGE_ACCESS_ENTRY();
+
+    MG_FEATURE_SERVICE_THROW()
+}

Added: sandbox/jng/convenience_apis/Server/src/Services/Feature/OpDeleteFeatures.h
===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/OpDeleteFeatures.h	      \
                (rev 0)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/OpDeleteFeatures.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,33 @@
+//
+//  Copyright (C) 2004-2014 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef MG_OP_DELETE_FEATURES_H
+#define MG_OP_DELETE_FEATURES_H
+
+#include "FeatureOperation.h"
+
+class MgOpDeleteFeatures : public MgFeatureOperation
+{
+    public:
+        MgOpDeleteFeatures();
+        virtual ~MgOpDeleteFeatures();
+
+    public:
+        virtual void Execute();
+};
+
+#endif

Added: sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeatures.cpp
===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeatures.cpp	    \
                (rev 0)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeatures.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,150 @@
+//
+//  Copyright (C) 2004-2014 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#include "OpInsertFeatures.h"
+#include "ServerFeatureTransactionPool.h"
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Constructs the object.
+/// </summary>
+///----------------------------------------------------------------------------
+MgOpInsertFeatures::MgOpInsertFeatures()
+{
+}
+
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Destructs the object.
+/// </summary>
+///----------------------------------------------------------------------------
+MgOpInsertFeatures::~MgOpInsertFeatures()
+{
+}
+
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Executes the operation.
+/// </summary>
+///
+/// <exceptions>
+/// MgException
+/// </exceptions>
+///----------------------------------------------------------------------------
+void MgOpInsertFeatures::Execute()
+{
+    ACE_DEBUG((LM_DEBUG, ACE_TEXT("  (%t) MgOpInsertFeatures::Execute()\n")));
+
+    MG_LOG_OPERATION_MESSAGE(L"InsertFeatures");
+
+    MG_FEATURE_SERVICE_TRY()
+
+    MG_LOG_OPERATION_MESSAGE_INIT(m_packet.m_OperationVersion, \
m_packet.m_NumArguments); +
+    ACE_ASSERT(m_stream != NULL);
+
+    if (3 == m_packet.m_NumArguments)
+    {
+        Ptr<MgResourceIdentifier> resource = \
(MgResourceIdentifier*)m_stream->GetObject(); +        STRING className;
+        m_stream->GetString(className);
+        Ptr<MgPropertyCollection> properties = \
(MgPropertyCollection*)m_stream->GetObject(); +        
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? \
L"MgResourceIdentifier" : resource->ToString().c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(className.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"MgPropertyCollection"); +        \
MG_LOG_OPERATION_MESSAGE_PARAMETERS_END(); +
+        Validate();
+
+        // Execute the operation
+        Ptr<MgFeatureReader> result = m_service->InsertFeatures(resource, className, \
properties); +
+        // Write the response
+        EndExecution(result);
+    }
+    if (4 == m_packet.m_NumArguments)
+    {
+        Ptr<MgResourceIdentifier> resource = \
(MgResourceIdentifier*)m_stream->GetObject(); +        STRING className;
+        m_stream->GetString(className);
+        Ptr<MgPropertyCollection> properties = \
(MgPropertyCollection*)m_stream->GetObject(); +        STRING transactionId;
+        m_stream->GetString(transactionId);
+        
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? \
L"MgResourceIdentifier" : resource->ToString().c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(className.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"MgPropertyCollection"); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(transactionId.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_PARAMETERS_END(); +
+        Validate();
+
+        MgServerFeatureTransactionPool* transactionPool = \
MgServerFeatureTransactionPool::GetInstance(); +        CHECKNULL(transactionPool, \
L"MgOpInsertFeatures.Execute") +
+        transactionPool->ValidateTimeout(transactionId);
+
+        // Get the MgTransaction instance from the pool if one has been started for \
this resource. +        Ptr<MgServerFeatureTransaction> transaction = \
transactionPool->GetTransaction(transactionId); +
+        // Execute the operation
+        Ptr<MgFeatureReader> result = m_service->InsertFeatures(resource, className, \
properties, (MgTransaction*)transaction.p); +
+        // Write the response
+        EndExecution(result);
+    }
+    else
+    {
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
+    }
+
+    if (!m_argsRead)
+    {
+        throw new MgOperationProcessingException(L"MgOpInsertFeatures.Execute",
+            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    // Successful operation
+    MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Success.c_str());
+
+    MG_FEATURE_SERVICE_CATCH(L"MgOpInsertFeatures.Execute")
+
+    if (mgException != NULL)
+    {
+        // Failed operation
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Failure.c_str());
+    }
+
+    // Add access log entry for operation
+    MG_LOG_OPERATION_MESSAGE_ACCESS_ENTRY();
+
+    MG_FEATURE_SERVICE_THROW()
+}

Added: sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeatures.h
===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeatures.h	      \
                (rev 0)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeatures.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,33 @@
+//
+//  Copyright (C) 2004-2014 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef MG_OP_INSERT_FEATURES_H
+#define MG_OP_INSERT_FEATURES_H
+
+#include "FeatureOperation.h"
+
+class MgOpInsertFeatures : public MgFeatureOperation
+{
+    public:
+        MgOpInsertFeatures();
+        virtual ~MgOpInsertFeatures();
+
+    public:
+        virtual void Execute();
+};
+
+#endif

Added: sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeaturesBatched.cpp
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeaturesBatched.cpp	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeaturesBatched.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,150 @@
+//
+//  Copyright (C) 2004-2014 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#include "OpInsertFeaturesBatched.h"
+#include "ServerFeatureTransactionPool.h"
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Constructs the object.
+/// </summary>
+///----------------------------------------------------------------------------
+MgOpInsertFeaturesBatched::MgOpInsertFeaturesBatched()
+{
+}
+
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Destructs the object.
+/// </summary>
+///----------------------------------------------------------------------------
+MgOpInsertFeaturesBatched::~MgOpInsertFeaturesBatched()
+{
+}
+
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Executes the operation.
+/// </summary>
+///
+/// <exceptions>
+/// MgException
+/// </exceptions>
+///----------------------------------------------------------------------------
+void MgOpInsertFeaturesBatched::Execute()
+{
+    ACE_DEBUG((LM_DEBUG, ACE_TEXT("  (%t) \
MgOpInsertFeaturesBatched::Execute()\n"))); +
+    MG_LOG_OPERATION_MESSAGE(L"InsertFeaturesBatched");
+
+    MG_FEATURE_SERVICE_TRY()
+
+    MG_LOG_OPERATION_MESSAGE_INIT(m_packet.m_OperationVersion, \
m_packet.m_NumArguments); +
+    ACE_ASSERT(m_stream != NULL);
+
+    if (3 == m_packet.m_NumArguments)
+    {
+        Ptr<MgResourceIdentifier> resource = \
(MgResourceIdentifier*)m_stream->GetObject(); +        STRING className;
+        m_stream->GetString(className);
+        Ptr<MgBatchPropertyCollection> properties = \
(MgBatchPropertyCollection*)m_stream->GetObject(); +        
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? \
L"MgResourceIdentifier" : resource->ToString().c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(className.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"MgPropertyCollection"); +        \
MG_LOG_OPERATION_MESSAGE_PARAMETERS_END(); +
+        Validate();
+
+        // Execute the operation
+        Ptr<MgFeatureReader> result = m_service->InsertFeatures(resource, className, \
properties); +
+        // Write the response
+        EndExecution(result);
+    }
+    if (4 == m_packet.m_NumArguments)
+    {
+        Ptr<MgResourceIdentifier> resource = \
(MgResourceIdentifier*)m_stream->GetObject(); +        STRING className;
+        m_stream->GetString(className);
+        Ptr<MgBatchPropertyCollection> properties = \
(MgBatchPropertyCollection*)m_stream->GetObject(); +        STRING transactionId;
+        m_stream->GetString(transactionId);
+        
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? \
L"MgResourceIdentifier" : resource->ToString().c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(className.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"MgPropertyCollection"); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(transactionId.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_PARAMETERS_END(); +
+        Validate();
+
+        MgServerFeatureTransactionPool* transactionPool = \
MgServerFeatureTransactionPool::GetInstance(); +        CHECKNULL(transactionPool, \
L"MgOpInsertFeaturesBatched.Execute") +
+        transactionPool->ValidateTimeout(transactionId);
+
+        // Get the MgTransaction instance from the pool if one has been started for \
this resource. +        Ptr<MgServerFeatureTransaction> transaction = \
transactionPool->GetTransaction(transactionId); +
+        // Execute the operation
+        Ptr<MgFeatureReader> result = m_service->InsertFeatures(resource, className, \
properties, (MgTransaction*)transaction.p); +
+        // Write the response
+        EndExecution(result);
+    }
+    else
+    {
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
+    }
+
+    if (!m_argsRead)
+    {
+        throw new MgOperationProcessingException(L"MgOpInsertFeaturesBatched.Execute",
 +            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    // Successful operation
+    MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Success.c_str());
+
+    MG_FEATURE_SERVICE_CATCH(L"MgOpInsertFeaturesBatched.Execute")
+
+    if (mgException != NULL)
+    {
+        // Failed operation
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Failure.c_str());
+    }
+
+    // Add access log entry for operation
+    MG_LOG_OPERATION_MESSAGE_ACCESS_ENTRY();
+
+    MG_FEATURE_SERVICE_THROW()
+}

Added: sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeaturesBatched.h
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeaturesBatched.h	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/OpInsertFeaturesBatched.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,33 @@
+//
+//  Copyright (C) 2004-2014 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef MG_OP_INSERT_FEATURES_BATCHED_H
+#define MG_OP_INSERT_FEATURES_BATCHED_H
+
+#include "FeatureOperation.h"
+
+class MgOpInsertFeaturesBatched : public MgFeatureOperation
+{
+    public:
+        MgOpInsertFeaturesBatched();
+        virtual ~MgOpInsertFeaturesBatched();
+
+    public:
+        virtual void Execute();
+};
+
+#endif

Added: sandbox/jng/convenience_apis/Server/src/Services/Feature/OpUpdateMatchingFeatures.cpp
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/OpUpdateMatchingFeatures.cpp	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/OpUpdateMatchingFeatures.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,158 @@
+//
+//  Copyright (C) 2004-2014 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#include "OpUpdateMatchingFeatures.h"
+#include "ServerFeatureTransactionPool.h"
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Constructs the object.
+/// </summary>
+///----------------------------------------------------------------------------
+MgOpUpdateMatchingFeatures::MgOpUpdateMatchingFeatures()
+{
+}
+
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Destructs the object.
+/// </summary>
+///----------------------------------------------------------------------------
+MgOpUpdateMatchingFeatures::~MgOpUpdateMatchingFeatures()
+{
+}
+
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Executes the operation.
+/// </summary>
+///
+/// <exceptions>
+/// MgException
+/// </exceptions>
+///----------------------------------------------------------------------------
+void MgOpUpdateMatchingFeatures::Execute()
+{
+    ACE_DEBUG((LM_DEBUG, ACE_TEXT("  (%t) \
MgOpUpdateMatchingFeatures::Execute()\n"))); +
+    MG_LOG_OPERATION_MESSAGE(L"UpdateMatchingFeatures");
+
+    MG_FEATURE_SERVICE_TRY()
+
+    MG_LOG_OPERATION_MESSAGE_INIT(m_packet.m_OperationVersion, \
m_packet.m_NumArguments); +
+    ACE_ASSERT(m_stream != NULL);
+
+    if (4 == m_packet.m_NumArguments)
+    {
+        Ptr<MgResourceIdentifier> resource = \
(MgResourceIdentifier*)m_stream->GetObject(); +        STRING className;
+        m_stream->GetString(className);
+        Ptr<MgPropertyCollection> properties = \
(MgPropertyCollection*)m_stream->GetObject(); +        STRING filter;
+        m_stream->GetString(filter);
+        
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? \
L"MgResourceIdentifier" : resource->ToString().c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(className.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"MgPropertyCollection"); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(filter.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_PARAMETERS_END(); +
+        Validate();
+
+        // Execute the operation
+        INT32 result = m_service->UpdateMatchingFeatures(resource, className, \
properties, filter); +
+        // Write the response
+        EndExecution(result);
+    }
+    if (5 == m_packet.m_NumArguments)
+    {
+        Ptr<MgResourceIdentifier> resource = \
(MgResourceIdentifier*)m_stream->GetObject(); +        STRING className;
+        m_stream->GetString(className);
+        Ptr<MgPropertyCollection> properties = \
(MgPropertyCollection*)m_stream->GetObject(); +        STRING filter;
+        m_stream->GetString(filter);
+        STRING transactionId;
+        m_stream->GetString(transactionId);
+        
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING((NULL == resource) ? \
L"MgResourceIdentifier" : resource->ToString().c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(className.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"MgPropertyCollection"); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(filter.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR(); +        \
MG_LOG_OPERATION_MESSAGE_ADD_STRING(transactionId.c_str()); +        \
MG_LOG_OPERATION_MESSAGE_PARAMETERS_END(); +
+        Validate();
+
+        MgServerFeatureTransactionPool* transactionPool = \
MgServerFeatureTransactionPool::GetInstance(); +        CHECKNULL(transactionPool, \
L"MgOpUpdateMatchingFeatures.Execute") +
+        transactionPool->ValidateTimeout(transactionId);
+
+        // Get the MgTransaction instance from the pool if one has been started for \
this resource. +        Ptr<MgServerFeatureTransaction> transaction = \
transactionPool->GetTransaction(transactionId); +
+        // Execute the operation
+        INT32 result = m_service->UpdateMatchingFeatures(resource, className, \
properties, filter, (MgTransaction*)transaction.p); +
+        // Write the response
+        EndExecution(result);
+    }
+    else
+    {
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
+    }
+
+    if (!m_argsRead)
+    {
+        throw new MgOperationProcessingException(L"MgOpUpdateMatchingFeatures.Execute",
 +            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    // Successful operation
+    MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Success.c_str());
+
+    MG_FEATURE_SERVICE_CATCH(L"MgOpUpdateMatchingFeatures.Execute")
+
+    if (mgException != NULL)
+    {
+        // Failed operation
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(MgResources::Failure.c_str());
+    }
+
+    // Add access log entry for operation
+    MG_LOG_OPERATION_MESSAGE_ACCESS_ENTRY();
+
+    MG_FEATURE_SERVICE_THROW()
+}

Added: sandbox/jng/convenience_apis/Server/src/Services/Feature/OpUpdateMatchingFeatures.h
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/OpUpdateMatchingFeatures.h	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/OpUpdateMatchingFeatures.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,33 @@
+//
+//  Copyright (C) 2004-2014 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef MG_OP_UPDATE_MATCHING_FEATURES_H
+#define MG_OP_UPDATE_MATCHING_FEATURES_H
+
+#include "FeatureOperation.h"
+
+class MgOpUpdateMatchingFeatures : public MgFeatureOperation
+{
+    public:
+        MgOpUpdateMatchingFeatures();
+        virtual ~MgOpUpdateMatchingFeatures();
+
+    public:
+        virtual void Execute();
+};
+
+#endif

Modified: sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.cpp
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.cpp	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -637,7 +637,308 @@
     return asuf.Execute(resource, commands, transaction);
 }
 
+MgFeatureReader* MgServerFeatureService::InsertFeatures(MgResourceIdentifier* \
resource, +                                                        CREFSTRING \
className, +                                                        \
MgPropertyCollection* propertyValues) +{
+    MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::InsertFeatures()");
 
+    Ptr<MgFeatureReader> ret;
+    MG_FEATURE_SERVICE_TRY()
+    
+    Ptr<MgInsertFeatures> insert = new MgInsertFeatures(className, propertyValues);
+    Ptr<MgFeatureCommandCollection> cmds = new MgFeatureCommandCollection();
+    cmds->Add(insert);
+    MgServerUpdateFeatures asuf;
+    Ptr<MgPropertyCollection> props = asuf.Execute(resource, cmds, false);
+
+    if (cmds->GetCount() == 1)
+    {
+        INT32 i = 0;
+        Ptr<MgProperty> prop = props->GetItem(i);
+        if (prop->GetPropertyType() == MgPropertyType::String) //FDO error in \
non-transactional mode +        {
+            MgStringProperty* sp = static_cast<MgStringProperty*>(prop.p);
+            MgStringCollection args;
+            args.Add(sp->GetValue());
+            throw new MgFdoException(L"MgServerFeatureService.InsertFeatures", \
__LINE__, __WFILE__, &args, L"MgFormatInnerExceptionMessage", NULL); +        }
+        else if (prop->GetPropertyType() == MgPropertyType::Feature) //Insert result
+        {
+            MgFeatureProperty* fp = static_cast<MgFeatureProperty*>(prop.p);
+            ret = fp->GetValue();
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW_WITH_FEATURE_SOURCE(L"MgServerFeatureService.InsertFeatures", \
resource) +    return ret.Detach();
+}
+
+MgFeatureReader* MgServerFeatureService::InsertFeatures(MgResourceIdentifier* \
resource, +                                                        CREFSTRING \
className, +                                                        \
MgPropertyCollection* propertyValues, +                                               \
MgTransaction* trans) +{
+    MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::InsertFeatures()");
+
+    Ptr<MgFeatureReader> ret;
+    MG_FEATURE_SERVICE_TRY()
+    
+    Ptr<MgInsertFeatures> insert = new MgInsertFeatures(className, propertyValues);
+    Ptr<MgFeatureCommandCollection> cmds = new MgFeatureCommandCollection();
+    cmds->Add(insert);
+    MgServerUpdateFeatures asuf;
+    Ptr<MgPropertyCollection> props = asuf.Execute(resource, cmds, trans);
+
+    if (cmds->GetCount() == 1)
+    {
+        INT32 i = 0;
+        Ptr<MgProperty> prop = props->GetItem(i);
+        if (prop->GetPropertyType() == MgPropertyType::String) //FDO error in \
non-transactional mode +        {
+            MgStringProperty* sp = static_cast<MgStringProperty*>(prop.p);
+            MgStringCollection args;
+            args.Add(sp->GetValue());
+            throw new MgFdoException(L"MgServerFeatureService.InsertFeatures", \
__LINE__, __WFILE__, &args, L"MgFormatInnerExceptionMessage", NULL); +        }
+        else if (prop->GetPropertyType() == MgPropertyType::Feature) //Insert result
+        {
+            MgFeatureProperty* fp = static_cast<MgFeatureProperty*>(prop.p);
+            ret = fp->GetValue();
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW_WITH_FEATURE_SOURCE(L"MgServerFeatureService.InsertFeatures", \
resource) +    return ret.Detach();
+}
+
+MgFeatureReader* MgServerFeatureService::InsertFeatures(MgResourceIdentifier* \
resource, +                                                        CREFSTRING \
className, +                                                        \
MgBatchPropertyCollection* batchPropertyValues) +{
+    MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::InsertFeatures()");
+
+    Ptr<MgFeatureReader> ret;
+    MG_FEATURE_SERVICE_TRY()
+    
+    Ptr<MgInsertFeatures> insert = new MgInsertFeatures(className, \
batchPropertyValues); +    Ptr<MgFeatureCommandCollection> cmds = new \
MgFeatureCommandCollection(); +    cmds->Add(insert);
+    MgServerUpdateFeatures asuf;
+    Ptr<MgPropertyCollection> props = asuf.Execute(resource, cmds, false);
+
+    if (cmds->GetCount() == 1)
+    {
+        INT32 i = 0;
+        Ptr<MgProperty> prop = props->GetItem(i);
+        if (prop->GetPropertyType() == MgPropertyType::String) //FDO error in \
non-transactional mode +        {
+            MgStringProperty* sp = static_cast<MgStringProperty*>(prop.p);
+            MgStringCollection args;
+            args.Add(sp->GetValue());
+            throw new MgFdoException(L"MgServerFeatureService.InsertFeatures", \
__LINE__, __WFILE__, &args, L"MgFormatInnerExceptionMessage", NULL); +        }
+        else if (prop->GetPropertyType() == MgPropertyType::Feature) //Insert result
+        {
+            MgFeatureProperty* fp = static_cast<MgFeatureProperty*>(prop.p);
+            ret = fp->GetValue();
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW_WITH_FEATURE_SOURCE(L"MgServerFeatureService.InsertFeatures", \
resource) +    return ret.Detach();
+}
+
+MgFeatureReader* MgServerFeatureService::InsertFeatures(MgResourceIdentifier* \
resource, +                                                        CREFSTRING \
className, +                                                        \
MgBatchPropertyCollection* batchPropertyValues, +                                     \
MgTransaction* trans) +{
+    MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::InsertFeatures()");
+
+    Ptr<MgFeatureReader> ret;
+    MG_FEATURE_SERVICE_TRY()
+    
+    Ptr<MgInsertFeatures> insert = new MgInsertFeatures(className, \
batchPropertyValues); +    Ptr<MgFeatureCommandCollection> cmds = new \
MgFeatureCommandCollection(); +    cmds->Add(insert);
+    MgServerUpdateFeatures asuf;
+    Ptr<MgPropertyCollection> props = asuf.Execute(resource, cmds, trans);
+
+    if (cmds->GetCount() == 1)
+    {
+        INT32 i = 0;
+        Ptr<MgProperty> prop = props->GetItem(i);
+        if (prop->GetPropertyType() == MgPropertyType::String) //FDO error in \
non-transactional mode +        {
+            MgStringProperty* sp = static_cast<MgStringProperty*>(prop.p);
+            MgStringCollection args;
+            args.Add(sp->GetValue());
+            throw new MgFdoException(L"MgServerFeatureService.InsertFeatures", \
__LINE__, __WFILE__, &args, L"MgFormatInnerExceptionMessage", NULL); +        }
+        else if (prop->GetPropertyType() == MgPropertyType::Feature) //Insert result
+        {
+            MgFeatureProperty* fp = static_cast<MgFeatureProperty*>(prop.p);
+            ret = fp->GetValue();
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW_WITH_FEATURE_SOURCE(L"MgServerFeatureService.InsertFeatures", \
resource) +    return ret.Detach();
+}
+
+INT32 MgServerFeatureService::UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                                     CREFSTRING className,
+                                                     MgPropertyCollection* \
properties, +                                                     CREFSTRING filter)
+{
+    MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::UpdateMatchingFeatures()");
+
+    INT32 ret = -1;
+    MG_FEATURE_SERVICE_TRY()
+    
+    Ptr<MgUpdateFeatures> update = new MgUpdateFeatures(className, properties, \
filter); +    Ptr<MgFeatureCommandCollection> cmds = new \
MgFeatureCommandCollection(); +    cmds->Add(update);
+    MgServerUpdateFeatures asuf;
+    Ptr<MgPropertyCollection> props = asuf.Execute(resource, cmds, false);
+
+    if (cmds->GetCount() == 1)
+    {
+        INT32 i = 0;
+        Ptr<MgProperty> prop = props->GetItem(i);
+        if (prop->GetPropertyType() == MgPropertyType::String) //FDO error in \
non-transactional mode +        {
+            MgStringProperty* sp = static_cast<MgStringProperty*>(prop.p);
+            MgStringCollection args;
+            args.Add(sp->GetValue());
+            throw new \
MgFdoException(L"MgServerFeatureService.UpdateMatchingFeatures", __LINE__, __WFILE__, \
&args, L"MgFormatInnerExceptionMessage", NULL); +        }
+        else if (prop->GetPropertyType() == MgPropertyType::Int32) //Update result
+        {
+            MgInt32Property* ip = static_cast<MgInt32Property*>(prop.p);
+            ret = ip->GetValue();
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW_WITH_FEATURE_SOURCE(L"MgServerFeatureService.UpdateMatchingFeatures", \
resource) +    return ret;
+}
+
+INT32 MgServerFeatureService::UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                                     CREFSTRING className,
+                                                     MgPropertyCollection* \
properties, +                                                     CREFSTRING filter,
+                                                     MgTransaction* trans)
+{
+    MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::UpdateMatchingFeatures()");
+
+    INT32 ret = -1;
+    MG_FEATURE_SERVICE_TRY()
+    
+    Ptr<MgUpdateFeatures> update = new MgUpdateFeatures(className, properties, \
filter); +    Ptr<MgFeatureCommandCollection> cmds = new \
MgFeatureCommandCollection(); +    cmds->Add(update);
+    MgServerUpdateFeatures asuf;
+    Ptr<MgPropertyCollection> props = asuf.Execute(resource, cmds, trans);
+
+    if (cmds->GetCount() == 1)
+    {
+        INT32 i = 0;
+        Ptr<MgProperty> prop = props->GetItem(i);
+        if (prop->GetPropertyType() == MgPropertyType::String) //FDO error in \
non-transactional mode +        {
+            MgStringProperty* sp = static_cast<MgStringProperty*>(prop.p);
+            MgStringCollection args;
+            args.Add(sp->GetValue());
+            throw new \
MgFdoException(L"MgServerFeatureService.UpdateMatchingFeatures", __LINE__, __WFILE__, \
&args, L"MgFormatInnerExceptionMessage", NULL); +        }
+        else if (prop->GetPropertyType() == MgPropertyType::Int32) //Update result
+        {
+            MgInt32Property* ip = static_cast<MgInt32Property*>(prop.p);
+            ret = ip->GetValue();
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW_WITH_FEATURE_SOURCE(L"MgServerFeatureService.UpdateMatchingFeatures", \
resource) +    return ret;
+}
+
+INT32 MgServerFeatureService::DeleteFeatures(MgResourceIdentifier* resource,
+                                             CREFSTRING className,
+                                             CREFSTRING filter)
+{
+    MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::DeleteFeatures()");
+
+    INT32 ret = -1;
+    MG_FEATURE_SERVICE_TRY()
+    
+    Ptr<MgDeleteFeatures> deleteCmd = new MgDeleteFeatures(className, filter);
+    Ptr<MgFeatureCommandCollection> cmds = new MgFeatureCommandCollection();
+    cmds->Add(deleteCmd);
+    MgServerUpdateFeatures asuf;
+    Ptr<MgPropertyCollection> props = asuf.Execute(resource, cmds, false);
+
+    if (cmds->GetCount() == 1)
+    {
+        INT32 i = 0;
+        Ptr<MgProperty> prop = props->GetItem(i);
+        if (prop->GetPropertyType() == MgPropertyType::String) //FDO error in \
non-transactional mode +        {
+            MgStringProperty* sp = static_cast<MgStringProperty*>(prop.p);
+            MgStringCollection args;
+            args.Add(sp->GetValue());
+            throw new MgFdoException(L"MgServerFeatureService.DeleteFeatures", \
__LINE__, __WFILE__, &args, L"MgFormatInnerExceptionMessage", NULL); +        }
+        else if (prop->GetPropertyType() == MgPropertyType::Int32) //Delete result
+        {
+            MgInt32Property* ip = static_cast<MgInt32Property*>(prop.p);
+            ret = ip->GetValue();
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW_WITH_FEATURE_SOURCE(L"MgServerFeatureService.UpdateMatchingFeatures", \
resource) +    return ret;
+}
+
+INT32 MgServerFeatureService::DeleteFeatures(MgResourceIdentifier* resource,
+                                             CREFSTRING className,
+                                             CREFSTRING filter,
+                                             MgTransaction* trans)
+{
+    MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::DeleteFeatures()");
+
+    INT32 ret = -1;
+    MG_FEATURE_SERVICE_TRY()
+    
+    Ptr<MgDeleteFeatures> deleteCmd = new MgDeleteFeatures(className, filter);
+    Ptr<MgFeatureCommandCollection> cmds = new MgFeatureCommandCollection();
+    cmds->Add(deleteCmd);
+    MgServerUpdateFeatures asuf;
+    Ptr<MgPropertyCollection> props = asuf.Execute(resource, cmds, trans);
+
+    if (cmds->GetCount() == 1)
+    {
+        INT32 i = 0;
+        Ptr<MgProperty> prop = props->GetItem(i);
+        if (prop->GetPropertyType() == MgPropertyType::String) //FDO error in \
non-transactional mode +        {
+            MgStringProperty* sp = static_cast<MgStringProperty*>(prop.p);
+            MgStringCollection args;
+            args.Add(sp->GetValue());
+            throw new MgFdoException(L"MgServerFeatureService.DeleteFeatures", \
__LINE__, __WFILE__, &args, L"MgFormatInnerExceptionMessage", NULL); +        }
+        else if (prop->GetPropertyType() == MgPropertyType::Int32) //Delete result
+        {
+            MgInt32Property* ip = static_cast<MgInt32Property*>(prop.p);
+            ret = ip->GetValue();
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW_WITH_FEATURE_SOURCE(L"MgServerFeatureService.UpdateMatchingFeatures", \
resource) +    return ret;
+}
+
 ////////////////////////////////////////////////////////////////////////////////////////
  /// <summary>
 /// Gets the locked features

Modified: sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.h
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.h	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -992,6 +992,44 @@
     ///
     void CreateFeatureSource(MgResourceIdentifier* resource, MgFeatureSourceParams* \
sourceParams);  
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgPropertyCollection* propertyValues);
+
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgPropertyCollection* propertyValues,
+                                            MgTransaction* trans);
+
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgBatchPropertyCollection* \
batchPropertyValues); +
+    virtual MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource,
+                                            CREFSTRING className,
+                                            MgBatchPropertyCollection* \
batchPropertyValues, +                                            MgTransaction* \
trans); +
+    virtual INT32 UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                         CREFSTRING className,
+                                         MgPropertyCollection* properties,
+                                         CREFSTRING filter);
+
+    virtual INT32 UpdateMatchingFeatures(MgResourceIdentifier* resource,
+                                         CREFSTRING className,
+                                         MgPropertyCollection* properties,
+                                         CREFSTRING filter,
+                                         MgTransaction* trans);
+
+    virtual INT32 DeleteFeatures(MgResourceIdentifier* resource,
+                                 CREFSTRING className,
+                                 CREFSTRING filter);
+
+    virtual INT32 DeleteFeatures(MgResourceIdentifier* resource,
+                                 CREFSTRING className,
+                                 CREFSTRING filter,
+                                 MgTransaction* trans);
+
     // Feature
     MgBatchPropertyCollection* GetFeatures(CREFSTRING featureReader);
     bool CloseFeatureReader(CREFSTRING featureReader);

Modified: sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.vcxproj
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.vcxproj	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.vcxproj	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -277,6 +277,12 @@
       <ExcludedFromBuild \
                Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
                
       <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>  \
</ClCompile> +    <ClCompile Include="OpDeleteFeatures.cpp">
+      <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> +  \
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
 +      <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> +    \
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
 +    </ClCompile>
     <ClCompile Include="OpDescribeSchema.cpp">
       <ExcludedFromBuild \
                Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
                
       <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> @@ \
                -409,6 +415,18 @@
       <ExcludedFromBuild \
                Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
                
       <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>  \
</ClCompile> +    <ClCompile Include="OpInsertFeatures.cpp">
+      <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> +  \
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
 +      <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> +    \
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
 +    </ClCompile>
+    <ClCompile Include="OpInsertFeaturesBatched.cpp">
+      <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> +  \
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
 +      <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> +    \
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
 +    </ClCompile>
     <ClCompile Include="OpReleaseSavePoint.cpp">
       <ExcludedFromBuild \
                Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
                
       <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> @@ \
                -483,6 +501,12 @@
       <ExcludedFromBuild \
                Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
                
       <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>  \
</ClCompile> +    <ClCompile Include="OpUpdateMatchingFeatures.cpp">
+      <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> +  \
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
 +      <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> +    \
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
 +    </ClCompile>
     <ClCompile Include="OpXmlToSchema.cpp">
       <ExcludedFromBuild \
                Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
                
       <ExcludedFromBuild \
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> @@ \
-799,6 +823,7 @@  <ClInclude Include="OpCloseSqlReader.h" />
     <ClInclude Include="OpCommitTransaction.h" />
     <ClInclude Include="OpCreateFeatureSource.h" />
+    <ClInclude Include="OpDeleteFeatures.h" />
     <ClInclude Include="OpDescribeSchema.h" />
     <ClInclude Include="OpDescribeSchemaAsXml.h" />
     <ClInclude Include="OpDescribeWfsFeatureType.h" />
@@ -821,6 +846,8 @@
     <ClInclude Include="OpGetSpatialContexts.h" />
     <ClInclude Include="OpGetSqlRows.h" />
     <ClInclude Include="OpGetWfsFeature.h" />
+    <ClInclude Include="OpInsertFeatures.h" />
+    <ClInclude Include="OpInsertFeaturesBatched.h" />
     <ClInclude Include="OpReleaseSavePoint.h" />
     <ClInclude Include="OpRollbackSavePoint.h" />
     <ClInclude Include="OpRollbackTransaction.h" />
@@ -832,6 +859,7 @@
     <ClInclude Include="OpTestFeatureSourceConnection.h" />
     <ClInclude Include="OpUpdateFeatures.h" />
     <ClInclude Include="OpUpdateFeaturesWithTransaction.h" />
+    <ClInclude Include="OpUpdateMatchingFeatures.h" />
     <ClInclude Include="OpXmlToSchema.h" />
     <ClInclude Include="BooleanDataReaderCreator.h" />
     <ClInclude Include="ByteDataReaderCreator.h" />

Modified: sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.vcxproj.filters
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.vcxproj.filters	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureService.vcxproj.filters	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -188,6 +188,18 @@
     <ClCompile Include="ServerUpdateFeatures.cpp" />
     <ClCompile Include="TransformCache.cpp" />
     <ClCompile Include="FdoForcedOneToOneFeatureReader.cpp" />
+    <ClCompile Include="OpInsertFeatures.cpp">
+      <Filter>Ops</Filter>
+    </ClCompile>
+    <ClCompile Include="OpUpdateMatchingFeatures.cpp">
+      <Filter>Ops</Filter>
+    </ClCompile>
+    <ClCompile Include="OpDeleteFeatures.cpp">
+      <Filter>Ops</Filter>
+    </ClCompile>
+    <ClCompile Include="OpInsertFeaturesBatched.cpp">
+      <Filter>Ops</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="FeatureOperation.h">
@@ -385,6 +397,18 @@
     <ClInclude Include="TransformCache.h" />
     <ClInclude Include="UniqueFunction.h" />
     <ClInclude Include="FdoForcedOneToOneFeatureReader.h" />
+    <ClInclude Include="OpInsertFeatures.h">
+      <Filter>Ops</Filter>
+    </ClInclude>
+    <ClInclude Include="OpUpdateMatchingFeatures.h">
+      <Filter>Ops</Filter>
+    </ClInclude>
+    <ClInclude Include="OpDeleteFeatures.h">
+      <Filter>Ops</Filter>
+    </ClInclude>
+    <ClInclude Include="OpInsertFeaturesBatched.h">
+      <Filter>Ops</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="ServerFeatureService.rc" />

Modified: sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureServiceBuild.cpp
 ===================================================================
--- sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureServiceBuild.cpp	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Server/src/Services/Feature/ServerFeatureServiceBuild.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -107,3 +107,7 @@
 #include "OpCommitTransaction.cpp"
 #include "OpRollbackTransaction.cpp"
 #include "OpUpdateFeaturesWithTransaction.cpp"
+#include "OpInsertFeatures.cpp"
+#include "OpInsertFeaturesBatched.cpp"
+#include "OpUpdateMatchingFeatures.cpp"
+#include "OpDeleteFeatures.cpp"

Modified: sandbox/jng/convenience_apis/Server/src/UnitTesting/TestFeatureService.cpp
===================================================================
--- sandbox/jng/convenience_apis/Server/src/UnitTesting/TestFeatureService.cpp	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Server/src/UnitTesting/TestFeatureService.cpp	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -2978,4 +2978,557 @@
     {
         throw;
     }
+}
+
+void TestFeatureService::TestCase_InsertFeatures()
+{
+    try
+    {
+        MgServiceManager* serviceManager = MgServiceManager::GetInstance();
+        if(serviceManager == 0)
+        {
+            throw new \
MgNullReferenceException(L"TestFeatureService.TestCase_InsertFeatures", __LINE__, \
__WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgFeatureService> featSvc = \
dynamic_cast<MgFeatureService*>(serviceManager->RequestService(MgServiceType::FeatureService));
 +        if (featSvc == 0)
+        {
+            throw new \
MgServiceNotAvailableException(L"TestFeatureService.TestCase_InsertFeatures", +       \
__LINE__, __WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgResourceIdentifier> fsId = new \
MgResourceIdentifier(L"Library://UnitTests/Data/TestCase_InsertFeatures.FeatureSource");
 +        STRING className = CreateTestDataStore(featSvc, L"OSGeo.SDF", fsId);
+
+        Ptr<MgPropertyCollection> props = new MgPropertyCollection();
+        Ptr<MgStringProperty> nameProp = new MgStringProperty(L"Name", L"");
+        Ptr<MgGeometryProperty> geomProp = new MgGeometryProperty(L"Geometry", \
NULL); +        props->Add(nameProp);
+        props->Add(geomProp);
+
+        MgAgfReaderWriter agfRw;
+        MgWktReaderWriter wktRw;
+
+        nameProp->SetValue(L"Test");
+        Ptr<MgGeometry> geom = wktRw.Read(L"POINT (1 1)");
+        Ptr<MgByteReader> agf = agfRw.Write(geom);
+        geomProp->SetValue(agf);
+
+        Ptr<MgReader> fr = featSvc->InsertFeatures(fsId, className, props);
+        INT32 count = 0;
+        while (fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(1 == count);
+
+        Ptr<MgFeatureQueryOptions> query = new MgFeatureQueryOptions();
+        fr = featSvc->SelectFeatures(fsId, className, query);
+        count = 0;
+        while(fr->ReadNext())
+        {
+            CPPUNIT_ASSERT(fr->GetString(L"Name") == L"Test");
+            agf = fr->GetGeometry(L"Geometry");
+            geom = agfRw.Read(agf);
+            CPPUNIT_ASSERT(wktRw.Write(geom) == L"POINT (1 1)");
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(1 == count);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(FdoException* e)
+    {
+        STRING message = L"FdoException occurred: ";
+        message += e->GetExceptionMessage();
+        FDO_SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+void TestFeatureService::TestCase_InsertFeaturesBatch()
+{
+    try
+    {
+        MgServiceManager* serviceManager = MgServiceManager::GetInstance();
+        if(serviceManager == 0)
+        {
+            throw new \
MgNullReferenceException(L"TestFeatureService.TestCase_InsertFeatures", __LINE__, \
__WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgFeatureService> featSvc = \
dynamic_cast<MgFeatureService*>(serviceManager->RequestService(MgServiceType::FeatureService));
 +        if (featSvc == 0)
+        {
+            throw new \
MgServiceNotAvailableException(L"TestFeatureService.TestCase_InsertFeatures", +       \
__LINE__, __WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgResourceIdentifier> fsId = new \
MgResourceIdentifier(L"Library://UnitTests/Data/TestCase_InsertFeatures.FeatureSource");
 +        STRING className = CreateTestDataStore(featSvc, L"OSGeo.SDF", fsId);
+
+        Ptr<MgBatchPropertyCollection> batchProps = new MgBatchPropertyCollection();
+
+        for (INT32 i = 0; i < 5; i++)
+        {
+            Ptr<MgPropertyCollection> props = new MgPropertyCollection();
+            Ptr<MgStringProperty> nameProp = new MgStringProperty(L"Name", L"");
+            Ptr<MgGeometryProperty> geomProp = new MgGeometryProperty(L"Geometry", \
NULL); +            props->Add(nameProp);
+            props->Add(geomProp);
+
+            MgAgfReaderWriter agfRw;
+            MgWktReaderWriter wktRw;
+
+            STRING str = L"Test";
+            STRING sNum;
+            MgUtil::Int32ToString((i+1), sNum);
+            str += sNum;
+
+            nameProp->SetValue(str);
+            Ptr<MgGeometry> geom = wktRw.Read(L"POINT (1 1)");
+            Ptr<MgByteReader> agf = agfRw.Write(geom);
+            geomProp->SetValue(agf);
+
+            batchProps->Add(props);
+        }
+        Ptr<MgReader> fr = featSvc->InsertFeatures(fsId, className, batchProps);
+        INT32 count = 0;
+        while (fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(5 == count);
+
+        Ptr<MgFeatureQueryOptions> query = new MgFeatureQueryOptions();
+        fr = featSvc->SelectFeatures(fsId, className, query);
+        count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(5 == count);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(FdoException* e)
+    {
+        STRING message = L"FdoException occurred: ";
+        message += e->GetExceptionMessage();
+        FDO_SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+void TestFeatureService::TestCase_UpdateMatchingFeatures()
+{
+    try
+    {
+        MgServiceManager* serviceManager = MgServiceManager::GetInstance();
+        if(serviceManager == 0)
+        {
+            throw new \
MgNullReferenceException(L"TestFeatureService.TestCase_UpdateMatchingFeatures", \
__LINE__, __WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgFeatureService> featSvc = \
dynamic_cast<MgFeatureService*>(serviceManager->RequestService(MgServiceType::FeatureService));
 +        if (featSvc == 0)
+        {
+            throw new \
MgServiceNotAvailableException(L"TestFeatureService.TestCase_UpdateMatchingFeatures", \
+                __LINE__, __WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgResourceIdentifier> fsId = new \
MgResourceIdentifier(L"Library://UnitTests/Data/TestCase_InsertFeatures.FeatureSource");
 +        STRING className = CreateTestDataStore(featSvc, L"OSGeo.SDF", fsId);
+
+        Ptr<MgPropertyCollection> props = new MgPropertyCollection();
+        Ptr<MgStringProperty> nameProp = new MgStringProperty(L"Name", L"");
+        Ptr<MgGeometryProperty> geomProp = new MgGeometryProperty(L"Geometry", \
NULL); +        props->Add(nameProp);
+        props->Add(geomProp);
+
+        MgAgfReaderWriter agfRw;
+        MgWktReaderWriter wktRw;
+
+        for (INT32 i = 0; i < 5; i++)
+        {
+            STRING str = L"Test";
+            STRING sNum;
+            MgUtil::Int32ToString((i+1), sNum);
+            str += sNum;
+            nameProp->SetValue(str);
+            Ptr<MgGeometry> geom = wktRw.Read(L"POINT (1 1)");
+            Ptr<MgByteReader> agf = agfRw.Write(geom);
+            geomProp->SetValue(agf);
+
+            Ptr<MgReader> fr = featSvc->InsertFeatures(fsId, className, props);
+            INT32 count = 0;
+            while (fr->ReadNext())
+            {
+                count++;
+            }
+            fr->Close();
+            CPPUNIT_ASSERT(1 == count);
+        }
+
+        Ptr<MgFeatureQueryOptions> query = new MgFeatureQueryOptions();
+        Ptr<MgReader> fr = featSvc->SelectFeatures(fsId, className, query);
+        INT32 count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(5 == count);
+
+        Ptr<MgPropertyCollection> updateProps = new MgPropertyCollection();
+        Ptr<MgStringProperty> newNameProp = new MgStringProperty(L"Name", \
L"Test3Updated"); +        updateProps->Add(newNameProp);
+        Ptr<MgGeometry> newGeom = wktRw.Read(L"POINT (2 2)");
+        Ptr<MgByteReader> newAgf = agfRw.Write(newGeom);
+        Ptr<MgGeometryProperty> newGeomProp = new MgGeometryProperty(L"Geometry", \
newAgf); +        updateProps->Add(newGeomProp);
+
+        INT32 updated = featSvc->UpdateMatchingFeatures(fsId, className, \
updateProps, L"Name = 'Test3'"); +        CPPUNIT_ASSERT(1 == updated);
+
+        query->SetFilter(L"Name = 'Test3'");
+        fr = featSvc->SelectFeatures(fsId, className, query);
+        count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(0 == count);
+
+        query->SetFilter(L"Name = 'Test3Updated'");
+        fr = featSvc->SelectFeatures(fsId, className, query);
+        count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(1 == count);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(FdoException* e)
+    {
+        STRING message = L"FdoException occurred: ";
+        message += e->GetExceptionMessage();
+        FDO_SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+void TestFeatureService::TestCase_DeleteFeatures()
+{
+    try
+    {
+        MgServiceManager* serviceManager = MgServiceManager::GetInstance();
+        if(serviceManager == 0)
+        {
+            throw new \
MgNullReferenceException(L"TestFeatureService.TestCase_DeleteFeatures", __LINE__, \
__WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgFeatureService> featSvc = \
dynamic_cast<MgFeatureService*>(serviceManager->RequestService(MgServiceType::FeatureService));
 +        if (featSvc == 0)
+        {
+            throw new \
MgServiceNotAvailableException(L"TestFeatureService.TestCase_DeleteFeatures", +       \
__LINE__, __WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgResourceIdentifier> fsId = new \
MgResourceIdentifier(L"Library://UnitTests/Data/TestCase_InsertFeatures.FeatureSource");
 +        STRING className = CreateTestDataStore(featSvc, L"OSGeo.SDF", fsId);
+
+        Ptr<MgPropertyCollection> props = new MgPropertyCollection();
+        Ptr<MgStringProperty> nameProp = new MgStringProperty(L"Name", L"");
+        Ptr<MgGeometryProperty> geomProp = new MgGeometryProperty(L"Geometry", \
NULL); +        props->Add(nameProp);
+        props->Add(geomProp);
+
+        MgAgfReaderWriter agfRw;
+        MgWktReaderWriter wktRw;
+
+        for (INT32 i = 0; i < 5; i++)
+        {
+            STRING str = L"Test";
+            STRING sNum;
+            MgUtil::Int32ToString((i+1), sNum);
+            str += sNum;
+            nameProp->SetValue(str);
+            Ptr<MgGeometry> geom = wktRw.Read(L"POINT (1 1)");
+            Ptr<MgByteReader> agf = agfRw.Write(geom);
+            geomProp->SetValue(agf);
+
+            Ptr<MgReader> fr = featSvc->InsertFeatures(fsId, className, props);
+            INT32 count = 0;
+            while (fr->ReadNext())
+            {
+                count++;
+            }
+            fr->Close();
+            CPPUNIT_ASSERT(1 == count);
+        }
+
+        Ptr<MgFeatureQueryOptions> query = new MgFeatureQueryOptions();
+        Ptr<MgReader> fr = featSvc->SelectFeatures(fsId, className, query);
+        INT32 count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(5 == count);
+
+        INT32 deleted = featSvc->DeleteFeatures(fsId, className, L"Name = 'Test3'");
+        CPPUNIT_ASSERT(1 == deleted);
+
+        query->SetFilter(L"Name = 'Test3'");
+        fr = featSvc->SelectFeatures(fsId, className, query);
+        count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(0 == count);
+
+        query = new MgFeatureQueryOptions();
+        fr = featSvc->SelectFeatures(fsId, className, query);
+        count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(4 == count);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(FdoException* e)
+    {
+        STRING message = L"FdoException occurred: ";
+        message += e->GetExceptionMessage();
+        FDO_SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+void TestFeatureService::TestCase_TransactedCrud()
+{
+    try
+    {
+        MgServiceManager* serviceManager = MgServiceManager::GetInstance();
+        if(serviceManager == 0)
+        {
+            throw new \
MgNullReferenceException(L"TestFeatureService.TestCase_TransactedCrud", __LINE__, \
__WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgFeatureService> featSvc = \
dynamic_cast<MgFeatureService*>(serviceManager->RequestService(MgServiceType::FeatureService));
 +        if (featSvc == 0)
+        {
+            throw new \
MgServiceNotAvailableException(L"TestFeatureService.TestCase_TransactedCrud", +       \
__LINE__, __WFILE__, NULL, L"", NULL); +        }
+
+        Ptr<MgResourceIdentifier> fsId = new \
MgResourceIdentifier(L"Library://UnitTests/Data/TestCase_InsertFeatures.FeatureSource");
 +        STRING className = CreateTestDataStore(featSvc, L"OSGeo.SQLite", fsId);
+
+        Ptr<MgPropertyCollection> props = new MgPropertyCollection();
+        Ptr<MgStringProperty> nameProp = new MgStringProperty(L"Name", L"");
+        Ptr<MgGeometryProperty> geomProp = new MgGeometryProperty(L"Geometry", \
NULL); +        props->Add(nameProp);
+        props->Add(geomProp);
+
+        MgAgfReaderWriter agfRw;
+        MgWktReaderWriter wktRw;
+
+        for (INT32 i = 0; i < 5; i++)
+        {
+            STRING str = L"Test";
+            STRING sNum;
+            MgUtil::Int32ToString((i+1), sNum);
+            str += sNum;
+            nameProp->SetValue(str);
+            Ptr<MgGeometry> geom = wktRw.Read(L"POINT (1 1)");
+            Ptr<MgByteReader> agf = agfRw.Write(geom);
+            geomProp->SetValue(agf);
+
+            Ptr<MgReader> fr = featSvc->InsertFeatures(fsId, className, props);
+            INT32 count = 0;
+            while (fr->ReadNext())
+            {
+                count++;
+            }
+            fr->Close();
+            CPPUNIT_ASSERT(1 == count);
+        }
+
+        Ptr<MgFeatureQueryOptions> query = new MgFeatureQueryOptions();
+        Ptr<MgReader> fr = featSvc->SelectFeatures(fsId, className, query);
+        INT32 count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(5 == count);
+
+        //Do a transacted update
+        Ptr<MgTransaction> trans = featSvc->BeginTransaction(fsId);
+        
+        Ptr<MgPropertyCollection> updateProps = new MgPropertyCollection();
+        Ptr<MgStringProperty> newNameProp = new MgStringProperty(L"Name", \
L"Test3Updated"); +        updateProps->Add(newNameProp);
+        Ptr<MgGeometry> newGeom = wktRw.Read(L"POINT (2 2)");
+        Ptr<MgByteReader> newAgf = agfRw.Write(newGeom);
+        Ptr<MgGeometryProperty> newGeomProp = new MgGeometryProperty(L"Geometry", \
newAgf); +        updateProps->Add(newGeomProp);
+
+        INT32 updated = featSvc->UpdateMatchingFeatures(fsId, className, \
updateProps, L"Name = 'Test3'", trans); +        CPPUNIT_ASSERT(1 == updated);
+
+        //This hasn't been commited yet. So roll it back and verify our update never \
made it +        trans->Rollback();
+        query->SetFilter(L"Name = 'Test3Updated'");
+        fr = featSvc->SelectFeatures(fsId, className, query);
+        count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(0 == count);
+
+        //Do a transacted update. This time, commit it.
+        trans = featSvc->BeginTransaction(fsId);
+        
+        updateProps = new MgPropertyCollection();
+        newNameProp = new MgStringProperty(L"Name", L"Test3Updated");
+        updateProps->Add(newNameProp);
+        newGeom = wktRw.Read(L"POINT (2 2)");
+        newAgf = agfRw.Write(newGeom);
+        newGeomProp = new MgGeometryProperty(L"Geometry", newAgf);
+        updateProps->Add(newGeomProp);
+
+        updated = featSvc->UpdateMatchingFeatures(fsId, className, updateProps, \
L"Name = 'Test3'", trans); +        CPPUNIT_ASSERT(1 == updated);
+        trans->Commit();
+
+        //Verify the update came through
+        query->SetFilter(L"Name = 'Test3Updated'");
+        fr = featSvc->SelectFeatures(fsId, className, query);
+        count = 0;
+        while(fr->ReadNext())
+        {
+            count++;
+        }
+        fr->Close();
+        CPPUNIT_ASSERT(1 == count);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(FdoException* e)
+    {
+        STRING message = L"FdoException occurred: ";
+        message += e->GetExceptionMessage();
+        FDO_SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+STRING TestFeatureService::CreateTestDataStore(MgFeatureService* svcFeature, \
CREFSTRING provider, MgResourceIdentifier* fsId) +{
+    Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory();
+    STRING scName = L"Default";
+    STRING csWkt = csFactory->ConvertCoordinateSystemCodeToWkt(L"LL84");
+
+    Ptr<MgFeatureSchema> schema = new MgFeatureSchema(L"Default", L"Default Feature \
Schema"); +    Ptr<MgClassDefinition> klass = new MgClassDefinition();
+    klass->SetName(L"Test");
+
+    Ptr<MgPropertyDefinitionCollection> clsProps = klass->GetProperties();
+    Ptr<MgPropertyDefinitionCollection> clsIdProps = klass->GetIdentityProperties();
+
+    Ptr<MgDataPropertyDefinition> id = new MgDataPropertyDefinition(L"ID");
+    id->SetDataType(MgPropertyType::Int32);
+    id->SetAutoGeneration(true);
+    
+    Ptr<MgDataPropertyDefinition> name = new MgDataPropertyDefinition(L"Name");
+    name->SetDataType(MgPropertyType::String);
+    name->SetLength(255);
+    name->SetNullable(true);
+
+    Ptr<MgGeometricPropertyDefinition> geom = new \
MgGeometricPropertyDefinition(L"Geometry"); +    \
geom->SetGeometryTypes(MgFeatureGeometricType::Point); +    \
geom->SetSpatialContextAssociation(scName); +
+    clsProps->Add(id);
+    clsProps->Add(name);
+    clsProps->Add(geom);
+
+    clsIdProps->Add(id);
+
+    klass->SetDefaultGeometryPropertyName(L"Geometry");
+
+    Ptr<MgClassDefinitionCollection> classes = schema->GetClasses();
+    classes->Add(klass);
+
+    Ptr<MgFileFeatureSourceParams> fsParams = new \
MgFileFeatureSourceParams(provider, scName, csWkt, schema); +    \
svcFeature->CreateFeatureSource(fsId, fsParams); +
+    Ptr<MgFeatureSchemaCollection> schemas = svcFeature->DescribeSchema(fsId, L"");
+    Ptr<MgFeatureSchema> theSchema = schemas->GetItem(0);
+    Ptr<MgClassDefinitionCollection> theClasses = theSchema->GetClasses();
+    Ptr<MgClassDefinition> theClass = theClasses->GetItem(0);
+
+    STRING qClassName = theSchema->GetName();
+    qClassName += L":";
+    qClassName += theClass->GetName();
+    return qClassName;
 }
\ No newline at end of file

Modified: sandbox/jng/convenience_apis/Server/src/UnitTesting/TestFeatureService.h
===================================================================
--- sandbox/jng/convenience_apis/Server/src/UnitTesting/TestFeatureService.h	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/Server/src/UnitTesting/TestFeatureService.h	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -41,6 +41,11 @@
     CPPUNIT_TEST(TestCase_SelectAggregate);
     CPPUNIT_TEST(TestCase_UpdateFeaturesInsert);
     CPPUNIT_TEST(TestCase_UpdateFeaturesPartialFailure);
+    CPPUNIT_TEST(TestCase_InsertFeatures);
+    CPPUNIT_TEST(TestCase_InsertFeaturesBatch);
+    CPPUNIT_TEST(TestCase_UpdateMatchingFeatures);
+    CPPUNIT_TEST(TestCase_DeleteFeatures);
+    CPPUNIT_TEST(TestCase_TransactedCrud);
     CPPUNIT_TEST(TestCase_ExecuteSqlQuery);
     CPPUNIT_TEST(TestCase_ExecuteSqlNonQuery);
     CPPUNIT_TEST(TestCase_GetSpatialContexts);
@@ -89,6 +94,11 @@
     void TestCase_SelectAggregate();
     void TestCase_UpdateFeaturesInsert();
     void TestCase_UpdateFeaturesPartialFailure();
+    void TestCase_InsertFeatures();
+    void TestCase_InsertFeaturesBatch();
+    void TestCase_UpdateMatchingFeatures();
+    void TestCase_DeleteFeatures();
+    void TestCase_TransactedCrud();
     void TestCase_ExecuteSqlQuery();
     void TestCase_ExecuteSqlNonQuery();
     void TestCase_GetSpatialContexts();
@@ -110,6 +120,9 @@
     void TestCase_JoinFdoFeatures();
     void TestCase_BenchmarkSqliteJoin();
     void TestCase_BenchmarkSqliteAggregateJoin();
+
+private:
+    STRING CreateTestDataStore(MgFeatureService* svcFeature, CREFSTRING provider, \
MgResourceIdentifier* fsId);  };
 
 #endif // _TESTFEATURESERVICE_H

Modified: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/MgTestRunner/Program.cs
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/MgTestRunner/Program.cs	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/MgTestRunner/Program.cs	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -30,11 +30,20 @@
                 return _siteConn.CreateService(serviceType);
             }
 
-            public MgMapBase CreateMap()
+            public MgMapBase CreateMap(MgResourceIdentifier mapDefinition)
             {
-                return new MgMap(_siteConn);
+                var map = new MgMap(_siteConn);
+                map.Create(mapDefinition, mapDefinition.Name);
+                return map;
             }
 
+            public MgMapBase CreateMap(string coordSys, MgEnvelope env, string name)
+            {
+                var map = new MgMap(_siteConn);
+                map.Create(coordSys, env, name);
+                return map;
+            }
+
             public MgLayerBase CreateLayer(MgResourceIdentifier resId)
             {
                 MgResourceService resSvc = \
(MgResourceService)_siteConn.CreateService(MgServiceType.ResourceService);

Modified: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/CommonTests.cs
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/CommonTests.cs	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/CommonTests.cs	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -18,7 +18,8 @@
     public interface IPlatformFactory
     {
         MgService CreateService(int serviceType);
-        MgMapBase CreateMap();
+        MgMapBase CreateMap(MgResourceIdentifier mapDefinition);
+        MgMapBase CreateMap(string coordSys, MgEnvelope env, string name);
         MgLayerBase CreateLayer(MgResourceIdentifier resId);
     }
 

Modified: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/CollectionTests.cs
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/CollectionTests.cs	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/CollectionTests.cs	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -807,15 +807,14 @@
         {
             string coordsys = "GEOGCS[\"LL84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS \
84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHOR \
ITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"de \
gree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]";
  MgEnvelope env = new MgEnvelope(10, 10, 20, 20);
-            MgMapBase map1 = factory.CreateMap();
-            map1.Create(coordsys, env, "map1");
-            MgMapBase map2 = factory.CreateMap();
-            map2.Create(coordsys, env, "map2");
-            MgMapBase map3 = factory.CreateMap();
-            map3.Create(coordsys, env, "map3");
-            MgMapBase map4 = factory.CreateMap();
-            map4.Create(coordsys, env, "map4");
 
+
+
+            MgMapBase map1 = factory.CreateMap(coordsys, env, "map1");
+            MgMapBase map2 = factory.CreateMap(coordsys, env, "map2");
+            MgMapBase map3 = factory.CreateMap(coordsys, env, "map3");
+            MgMapBase map4 = factory.CreateMap(coordsys, env, "map4");
+
             MgMapCollection coll = new MgMapCollection();
             coll.Add(map1);
             coll.Insert(1, map2);

Added: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/ConvenienceTests.cs
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/ConvenienceTests.cs	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/ConvenienceTests.cs	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,470 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OSGeo.MapGuide;
+
+namespace OSGeo.MapGuide.Test.Common.ExternalTests
+{
+    internal class FeatureServiceTestUtil
+    {
+        public static string CreateTestDataStore(MgResourceIdentifier fsId, string \
provider, MgFeatureService featSvc) +        {
+            string scName = "Default";
+            var csFactory = new MgCoordinateSystemFactory();
+            string wkt = csFactory.ConvertCoordinateSystemCodeToWkt("LL84");
+            var schema = new MgFeatureSchema("Default", "Default Schema");
+            var cls = new MgClassDefinition();
+            cls.SetName("Test");
+            var classes = schema.GetClasses();
+            classes.Add(cls);
+
+            var clsProps = cls.GetProperties();
+            var idProps = cls.GetIdentityProperties();
+
+            var id = new MgDataPropertyDefinition("ID");
+            id.SetAutoGeneration(true);
+            id.SetDataType(MgPropertyType.Int32);
+
+            var name = new MgDataPropertyDefinition("Name");
+            name.SetDataType(MgPropertyType.String);
+            name.SetLength(255);
+            name.SetNullable(false);
+
+            var geom = new MgGeometricPropertyDefinition("Geometry");
+            geom.SetGeometryTypes(MgFeatureGeometricType.Point);
+            geom.SetSpatialContextAssociation(scName);
+
+            clsProps.Add(id);
+            clsProps.Add(name);
+            clsProps.Add(geom);
+
+            idProps.Add(id);
+
+            cls.SetDefaultGeometryPropertyName("Geometry");
+
+            var fsp = new MgFileFeatureSourceParams(provider, scName, wkt, schema);
+            featSvc.CreateFeatureSource(fsId, fsp);
+
+            var schemas = featSvc.DescribeSchema(fsId, "");
+            classes = schemas[0].GetClasses();
+            return schemas[0].Name + ":" + classes[0].Name;
+        }
+    }
+
+    public class FeatureServiceInsertFeatures : IExternalTest
+    {
+        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 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())
+            {
+                count++;
+            }
+            fr.Close();
+            Assert.AreEqual(1, count);
+        }
+    }
+
+    public class FeatureServiceInsertFeaturesBatched : 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 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);
+        }
+    }
+
+    public class FeatureServiceUpdateFeatures : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            MgFeatureService featSvc = \
(MgFeatureService)factory.CreateService(MgServiceType.FeatureService); +
+            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 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);
+        }
+    }
+
+    public class FeatureServiceDeleteFeatures : IExternalTest
+    {
+        public void Execute(IPlatformFactory factory, ITestLogger logger)
+        {
+            MgFeatureService featSvc = \
(MgFeatureService)factory.CreateService(MgServiceType.FeatureService); +
+            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 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++;
+            }
+            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);
+        }
+    }
+
+    public class LayerInsertFeatures : 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/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(); +
+            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 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);
+            int count = 0;
+            while (fr.ReadNext())
+            {
+                count++;
+            }
+            fr.Close();
+            Assert.AreEqual(1, count);
+
+            var query = new MgFeatureQueryOptions();
+            fr = layer.SelectFeatures(query);
+            count = 0;
+            while (fr.ReadNext())
+            {
+                count++;
+            }
+            fr.Close();
+            Assert.AreEqual(1, count);
+        }
+    }
+
+    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/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(); +
+            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);
+            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);
+        }
+    }
+
+    public class LayerUpdateFeatures : 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/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(); +
+            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);
+            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'"); +            Assert.AreEqual(1, updated);
+        }
+    }
+
+    public class LayerDeleteFeatures : 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/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(); +
+            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);
+            int count = 0;
+            while (fr.ReadNext())
+            {
+                count++;
+            }
+            fr.Close();
+            Assert.AreEqual(5, count);
+
+            int deleted = layer.DeleteFeatures("Name = 'Test3'");
+            Assert.AreEqual(1, deleted);
+
+            var query = new MgFeatureQueryOptions();
+            fr = layer.SelectFeatures(query);
+            count = 0;
+            while (fr.ReadNext())
+            {
+                count++;
+            }
+            Assert.AreEqual(4, count);
+
+            query.SetFilter("Name = 'Test3'");
+            fr = layer.SelectFeatures(query);
+            count = 0;
+            while (fr.ReadNext())
+            {
+                count++;
+            }
+            fr.Close();
+            Assert.AreEqual(0, count);
+        }
+    }
+
+}

Modified: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/PropertiesTest.cs
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/PropertiesTest.cs	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/ExternalTests/PropertiesTest.cs	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -369,7 +369,7 @@
     {
         public void Execute(IPlatformFactory factory, ITestLogger logger)
         {
-            MgMapBase mb = factory.CreateMap();
+            MgMapBase mb = new MgMapBase();
             Assert.AreEqual("", mb.Name);
             Assert.AreEqual("", mb.SessionId);
             Assert.IsNull(mb.MapDefinition);

Added: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Properties/Resources.Designer.cs
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Properties/Resources.Designer.cs	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Properties/Resources.Designer.cs	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,92 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.18444
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace OSGeo.MapGuide.Test.Common.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", \
"4.0.0.0")] +    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", \
"CA1811:AvoidUncalledPrivateCode")] +        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
 +        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new \
global::System.Resources.ResourceManager("OSGeo.MapGuide.Test.Common.Properties.Resources", \
typeof(Resources).Assembly); +                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
 +        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to .
+        /// </summary>
+        internal static string TestLayer {
+            get {
+                return ResourceManager.GetString("TestLayer", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to &lt;?xml \
version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt; +        ///&lt;MapDefinition \
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; \
xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot; version=&quot;2.4.0&quot; \
xsi:noNamespaceSchemaLocation=&quot;MapDefinition-2.4.0.xsd&quot;&gt; +        ///  \
&lt;Name&gt;Test Map&lt;/Name&gt; +        ///  \
&lt;CoordinateSystem&gt;{0}&lt;/CoordinateSystem&gt; +        ///  &lt;Extents&gt;
+        ///    &lt;MinX&gt;{1}&lt;/MinX&gt;
+        ///    &lt;MaxX&gt;{2}&lt;/MaxX&gt;
+        ///    &lt;MinY&gt;{3}&lt;/MinY&gt;
+        ///    &lt;MaxY&gt;{4}&lt;/MaxY&gt;
+        ///  &lt;/Extents&gt;
+        ///  &lt;BackgroundColor&gt;ffffffff&lt;/BackgroundColor&gt;
+        ///&lt;/MapDefinition&gt;.
+        /// </summary>
+        internal static string TestMapDef {
+            get {
+                return ResourceManager.GetString("TestMapDef", resourceCulture);
+            }
+        }
+    }
+}

Added: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Properties/Resources.resx
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Properties/Resources.resx	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Properties/Resources.resx	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, \
System.Windows.Forms, ...</resheader> +    <resheader \
name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, \
...</resheader> +    <data name="Name1"><value>this is my long \
string</value><comment>this is a comment</comment></data> +    <data name="Color1" \
type="System.Drawing.Color, System.Drawing">Blue</data> +    <data name="Bitmap1" \
mimetype="application/x-microsoft.net.object.binary.base64"> +        <value>[base64 \
mime encoded serialized .NET Framework object]</value> +    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" \
mimetype="application/x-microsoft.net.object.bytearray.base64"> +        \
<value>[base64 mime encoded string representing a byte array form of the .NET \
Framework object]</value> +        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" \
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> +    <xsd:import \
namespace="http://www.w3.org/XML/1998/namespace" /> +    <xsd:element name="root" \
msdata:IsDataSet="true"> +      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" \
msdata:Ordinal="1" /> +                <xsd:element name="comment" type="xsd:string" \
minOccurs="0" msdata:Ordinal="2" /> +              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" \
msdata:Ordinal="1" /> +              <xsd:attribute name="type" type="xsd:string" \
msdata:Ordinal="3" /> +              <xsd:attribute name="mimetype" type="xsd:string" \
msdata:Ordinal="4" /> +              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" \
msdata:Ordinal="1" /> +              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, \
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> +  \
</resheader> +  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, \
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> +  \
</resheader> +  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, \
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> +  <data \
name="TestLayer" type="System.Resources.ResXFileRef, System.Windows.Forms"> +    \
<value>..\Resources\TestLayer.txt;System.String, mscorlib, Version=4.0.0.0, \
Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value> +  </data>
+  <data name="TestMapDef" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\TestMapDef.txt;System.String, mscorlib, Version=4.0.0.0, \
Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value> +  </data>
+</root>
\ No newline at end of file

Added: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/TestLayer.txt
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/TestLayer.txt	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/TestLayer.txt	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LayerDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1.0.0" \
xsi:noNamespaceSchemaLocation="LayerDefinition-1.0.0.xsd"> +  <VectorLayerDefinition>
+    <ResourceId>{0}</ResourceId>
+    <FeatureName>{1}</FeatureName>
+    <FeatureNameType>FeatureClass</FeatureNameType>
+    <Geometry>{2}</Geometry>
+    <VectorScaleRange>
+      <PointTypeStyle>
+        <DisplayAsText>false</DisplayAsText>
+        <AllowOverpost>false</AllowOverpost>
+        <PointRule>
+          <LegendLabel />
+          <PointSymbolization2D>
+            <Mark>
+              <Unit>Points</Unit>
+              <SizeContext>DeviceUnits</SizeContext>
+              <SizeX>10</SizeX>
+              <SizeY>10</SizeY>
+              <Rotation>0</Rotation>
+              <Shape>Square</Shape>
+              <Fill>
+                <FillPattern>Solid</FillPattern>
+                <ForegroundColor>ffffffff</ForegroundColor>
+                <BackgroundColor>ffffffff</BackgroundColor>
+              </Fill>
+              <Edge>
+                <LineStyle>Solid</LineStyle>
+                <Thickness>1</Thickness>
+                <Color>ff000000</Color>
+                <Unit>Points</Unit>
+              </Edge>
+            </Mark>
+          </PointSymbolization2D>
+        </PointRule>
+      </PointTypeStyle>
+      <LineTypeStyle>
+        <LineRule>
+          <LegendLabel />
+          <LineSymbolization2D>
+            <LineStyle>Solid</LineStyle>
+            <Thickness>1</Thickness>
+            <Color>ff000000</Color>
+            <Unit>Points</Unit>
+          </LineSymbolization2D>
+        </LineRule>
+      </LineTypeStyle>
+      <AreaTypeStyle>
+        <AreaRule>
+          <LegendLabel />
+          <AreaSymbolization2D>
+            <Fill>
+              <FillPattern>Solid</FillPattern>
+              <ForegroundColor>ffffffff</ForegroundColor>
+              <BackgroundColor>ffffffff</BackgroundColor>
+            </Fill>
+            <Stroke>
+              <LineStyle>Solid</LineStyle>
+              <Thickness>1</Thickness>
+              <Color>ff000000</Color>
+              <Unit>Points</Unit>
+            </Stroke>
+          </AreaSymbolization2D>
+        </AreaRule>
+      </AreaTypeStyle>
+    </VectorScaleRange>
+  </VectorLayerDefinition>
+</LayerDefinition>
\ No newline at end of file

Added: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/TestMapDef.txt
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/TestMapDef.txt	 \
                (rev 0)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/Resources/TestMapDef.txt	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<MapDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="2.4.0" \
xsi:noNamespaceSchemaLocation="MapDefinition-2.4.0.xsd"> +  <Name>Test Map</Name>
+  <CoordinateSystem>{0}</CoordinateSystem>
+  <Extents>
+    <MinX>{1}</MinX>
+    <MaxX>{2}</MaxX>
+    <MinY>{3}</MinY>
+    <MaxY>{4}</MaxY>
+  </Extents>
+  <BackgroundColor>ffffffff</BackgroundColor>
+</MapDefinition>
\ No newline at end of file

Modified: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/TestCommon.csproj
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/TestCommon.csproj	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestCommon/TestCommon.csproj	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -76,6 +76,7 @@
     <Compile Include="CommonTests.cs" />
     <Compile Include="ExternalTests\ByteReaderTest.cs" />
     <Compile Include="ExternalTests\CollectionTests.cs" />
+    <Compile Include="ExternalTests\ConvenienceTests.cs" />
     <Compile Include="ExternalTests\PropertiesTest.cs" />
     <Compile Include="FeatureService\Operations.cs" />
     <Compile Include="ITestExecutor.cs" />
@@ -86,6 +87,11 @@
     <Compile Include="PlatformApiTestExecutor.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="FeatureService\FeatureServiceOperationExecutor.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
     <Compile Include="ResourceService\ResourceServiceOperationExecutor.cs" />
     <Compile Include="ResourceService\Operations.cs" />
     <Compile Include="SqliteException.cs" />
@@ -95,7 +101,18 @@
     <Compile Include="UnitTestException.cs" />
     <Compile Include="CommonUtility.cs" />
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\TestLayer.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\TestMapDef.txt" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
     <PreBuildEvent>call "$(SolutionDir)prebuild.bat" "$(ConfigurationName)" \
"$(PlatformName)"</PreBuildEvent>

Modified: sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestMapGuideApi/ExternalTests/CollectionTests.cs
 ===================================================================
--- sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestMapGuideApi/ExternalTests/CollectionTests.cs	2014-06-25 \
                15:30:06 UTC (rev 8263)
+++ sandbox/jng/convenience_apis/UnitTest/WebTier/DotNet/TestMapGuideApi/ExternalTests/CollectionTests.cs	2014-06-26 \
11:37:30 UTC (rev 8264) @@ -13,15 +13,10 @@
         {
             string coordsys = "GEOGCS[\"LL84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS \
84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHOR \
ITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"de \
gree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]";
  MgEnvelope env = new MgEnvelope(10, 10, 20, 20);
-            MgMap map1 = (MgMap)factory.CreateMap();
-            map1.Create(coordsys, env, "map1");
+            MgMap map1 = (MgMap)factory.CreateMap(coordsys, env, "map1");
+            MgMap map2 = (MgMap)factory.CreateMap(coordsys, env, "map2");
+            MgMap map3 = (MgMap)factory.CreateMap(coordsys, env, "map3");
 
-            MgMap map2 = (MgMap)factory.CreateMap();
-            map2.Create(coordsys, env, "map2");
-
-            MgMap map3 = (MgMap)factory.CreateMap();
-            map3.Create(coordsys, env, "map3");
-
             MgPlotSpecification spec = new MgPlotSpecification((float)8.0, \
                (float)11.0, "in", (float)0.0, (float)0.0, (float)5.0, (float)5.0);
             MgResourceIdentifier resId = new \
MgResourceIdentifier("Library://test.WebLayout");  MgLayout layout1 = new \
MgLayout(resId, "Title1", "in");

_______________________________________________
mapguide-commits mailing list
mapguide-commits@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/mapguide-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic