Feature services


Local (DCOM) connections are only supported for ArcGIS Server versions prior to 10.1.

About feature services

Feature services allow you to serve features over the Internet and provide the symbology to use when displaying the features. Features are organized into layers on which clients can execute queries and perform edits. Feature services provide templates that can be used for an enhanced editing experience on the client. Data from relationships and non-spatial tables can also be queried and edited using feature services.
The service offers the following capabilities:
  • List of layers and tables available from the service.
  • Query data from multiple layers and tables at once based on a geographic area and/or attribute values.
  • Query data from a single layer or table based on a geographic area, attribute values, a list of object IDs, and/or time.
  • Run queries that return results from related layers and tables.
  • Query, add, delete, and update multiple attachments on individual features.
  • Supports time aware layers that allow you to visualize temporal data within the specified window or time period.
  • Add new features or objects to a layer or table.
  • Delete features or objects from a layer or table.
  • Update features or objects in a layer or table.
  • Apply adds, deletes, and updates to multiple layers or tables at once.

Getting information about service contents  

A feature service can provide spatial and non-spatial data. The GetLayers method can be used to get information about the spatial data on the service. The method returns an array of GraphicFeatureLayers where each GraphicFeatureLayer (also referred to as a layer) describes a distinct set of features. The GetTables method can be called to get information about the non-spatial data only or called to get information about all data (both spatial and non-spatial). This method returns an array of DataObjectTables. A GraphicFeatureLayer is a DataObjectTable (also referred to as a table) and because of this, the method can return spatial and non-spatial data in the same array.
Information provided by a DataObjectTable includes types, templates, and properties (fields in the database). Types describe the symbology and are used by an application to render the features returned from queries. A template contains a prototypical instance of an object and is used to define the default values for a new object.
A DataObjectTable will also return information describing relationships, time, and attachments for data that has been published with these properties. This can be used when making queries on the service. For example, with relationships, you can query a table and have the result return corresponding objects from a related table. With time, you can execute queries that return objects that existed during a specific period of time.
GraphicFeatureLayer objects inherit all of these properties and also include properties describing spatial information, such as the spatial reference and spatial extent.

Querying

To get data from the service, queries can be executed on the layers and tables. Some methods are provided to query many layers or tables at once while others are provided to query individual layers or tables.
The QueryFromService and GetServiceObjectCount methods allow you to query many layers or tables at once. These methods take an array of GFSTableDescription, as well as a geometry that defines the area in which to apply the query. Each of these objects in the array includes a layer or table and optionally a definition expression. The GetServiceObjectCount method can be used to get the number of objects returned from the query while QueryFromService returns the actual objects. These methods are useful for operations, such as pan and zoom where when the extent changes, features need to be fetched from the service for the new extent.
The Query, QueryIDs and GetCount methods allow you to query individual layers and tables. These methods take a QueryFilter that allows you to define the query using attribute expressions, time and/or spatial filters. QueryFilter also accepts a FIDSet that allows you to query using an array of ObjectIDs. An ObjectID is a system attribute available in all layers and tables that uniquely identifies a row within a table or layer.
The GetCount method is used to get the number of rows that will be returned by the query. If the number of rows is relatively small, for example, you can use the Query method that returns the results of the query. If the number of rows is large, you might want to use paging to return the results in a series of smaller queries. To implement paging, use the QueryIDs method to get an array of the ObjectIDs that satisfy the query condition. The ObjectIDs can then be used with the QueryFilter’s FIDSet property to execute a series of queries each returning a subset of the result.
The QueryRelatedObjects method allows you to execute queries that return related rows. This method takes a list of ObjectIDs from the source layer or table, and returns objects from the related layer or table. When implementing an identify tool, for example, you might want to use this method to allow results to be expanded to include related rows.
The QueryAttachmentInfos and QueryAttachmentData methods allow you to query information and the actual attachments that are related to features that have been published with these properties. The QueryAttachmentInfos method takes a list of ObjectIDs from the source layer (IDsOfObjectstoQuery) and returns an array of AttachmentInfo objects containing all of the related attachments, as well as the properties of the attachment including AttachmentID, ContentType (for example, .pdf, .jpg and so on), Name, ParentID (the layer or table ID) and the Size of the attachment. Once you have the AttachmentIDs, you can use the QueryAttachmentData to access the attachments.

Query results

Results from queries are returned as ServiceData objects. When executing a query, use the ServiceDataOptions object to define the format of the results. Supported formats are, Native, Action Message Format (AMF), and JavaScript Object Notation (JSON). The ServiceData object returned from the result includes the ServiceDataOptions object that was passed in with the query.
The output spatial reference can also be specified when running a query. This is useful in cases where the client requires features in a spatial reference other than the default returned from the service.
Results can also be returned as grouped or ungrouped. Ungrouped means that all results are returned in one array while grouped means that results are returned in a set of arrays. The Query method always returns results ungrouped. The QueryFromService method always returns results grouped where arrays are provided with the results for each layer or table. You can choose either grouped or ungrouped results for the QueryRelatedObjects method. In this case, when grouped is selected, the method returns results with an array for each ID from the source.
For grouped results, the ServiceData.Object method returns a DataObjectGroups object that allows you to step through the results one group at a time. For ungrouped results, the ServiceData.Object method returns DataObjects that allows you to step through all results.

Definition expression

The Query and QueryRelatedObjects methods and the GFSTableDescription object takes a DefinitionExpression. Definition expressions are strings and are separate from and can be applied in addition to QueryFilters. Definition expressions can be used to apply queries to a specific type within a layer or table. You can also use a definition expression to easily apply the same query to all layers in the service.

Editing

Methods are provided that allow the application to apply edits to the underlying geodatabase through the service. The ApplyEdits method allows you to apply many edits to many layers and tables at once. The Add, Update, Delete, and DeleteByID methods allow you to apply edits to a single layer or table. Each call to any of these methods results in a transaction in the underlying geodatabase used by the service.
To apply updates, get the data to update from the feature service by executing a query. Data is returned from the query as an array of DataObjects and GraphicFeatures. GraphicFeature inherits from a DataObject and therefore, includes attributes, as well as geometry. To update an attribute, use DataObject.Properties, a PropertySet, to set the new values for the properties. To apply a change to a shape, set the GraphicFeature.Geometry property. Once all changes are made, use the Update or ApplyEdits methods to apply the changes on the service.
Some attributes, such as the ObjectID or GlobalID, are not editable and changes to these attributes are ignored when updates are applied.
Deletes can be applied by providing an array of ObjectIDs or by providing a query expression. You can get the ObjectIDs by querying the service and getting the ObjectID attribute values from the DataObjects. When deleting using a query expression, the query can involve attribute expressions, time, and/or spatial filters. The DeleteByID and ApplyEdits methods use an ObjectID array for deletes while the Delete method uses a QueryFilter.
To add new rows or features, create a DataObject or GraphicFeature object. Next, set the properties of the new object equal to the properties from the template you want to use (TemplateInfo object). This sets the default values that you can then change as needed. When you are ready to apply the new rows or features, use the Add or ApplyEdits methods to apply them on the service.
There are also edit methods provided that allow you to add, delete, and update attachments through the feature service to features that have been published with this property. To add new attachments, create an array of AttachmentData objects with the attachments you want to add, then use the AddAttachments method to add the attachments to a specified layer. To update attachments, use an array AttachmentData objects with the attachments and the changes you would like to apply with the layer ID to the UpdateAttachments method. Attachments can also be deleted by providing an array of AttachmentIDs and the layer ID to the DeleteAttachments method.
When edits are applied to the service, an array of EditResult objects is returned. You can step through the results to see if individual edits were applied successfully and in the case of adds, you will get the new ObjectID and GlobalID values assigned on the service.
The Adds, Updates, and Deletes properties for ITableEdit must be set to objects of a specific type. Adds and Updates must be set to a type that implements ESRI.ArcGIS.Carto.IDataObjects and Deletes must to be set to a type that implements ESRI.ArcGIS.esriSystem.ILongArray. The objects can remain empty (no property are set) as long as they are available. If objects of these types are not set to their respective properties on the ITableEdit instance, IGraphicFeatureServer.ApplyEdits() does not update the database and no error is returned.
See the following AppyEdits code examples.

Code examples

The following are some code examples that demonstrate the usage of some of the methods exposed by FeatureServer within servercontext using ArcObjects:
[C#]
/// QUERY.
public static void FeatureServer_Query()
{
    IServerContext serverContext = null;
    try
    {
        GISServerConnection serverConnection = new GISServerConnection();
        serverConnection.Connect("Localhost");
        IServerObjectManager serverManager = serverConnection.ServerObjectManager;
        serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer");
        // Get the FeatureServer object extension.
        IServerObjectExtensionManager pSOEM = serverContext.ServerObject as
            IServerObjectExtensionManager;
        IGraphicFeatureServer featureServer = pSOEM.FindExtensionByTypeName(
            "FeatureServer")as IGraphicFeatureServer;
        IServiceDataOptions serviceDataOptions = serverContext.CreateObject(
            "esriCarto.ServiceDataOptions")as IServiceDataOptions;
        serviceDataOptions.Format = "Native";
        IQueryFilter pQFilter = serverContext.CreateObject(
            "esriGeodatabase.QueryFilter")as IQueryFilter;
        pQFilter.WhereClause = "Service_Type = 'Repair'";
        IServiceData serviceData = featureServer.Query(4, "", pQFilter,
            serviceDataOptions);
        System.Object obj = serviceData.Object;
        if (obj is IDataObjects)
        {
            IDataObjects dataObjects = obj as DataObjects;
            IDataObjectArray dataObjectArray = dataObjects.DataObjectArray;
            IDataObjectEx dataobject;
            IPropertySet pPropSet = serverContext.CreateObject(
                "esriSystem.PropertySet")as IPropertySet;
            System.Object names;
            System.Object values;
            for (int i = 0; i < dataObjectArray.Count; i++)
            {
                dataobject = dataObjectArray.get_Element(i);
                pPropSet = dataobject.Properties;
                pPropSet.GetAllProperties(out names, out values);
                // Do something with Names and Values populated which are nothing but field names and their values.
            }
        }
        else if (obj is IDataObjectGroups)
        {
            //If object is of type DataObjetGroups do something.
        }
    }
    catch (Exception ex)
    {
        if (serverContext != null)
            serverContext.ReleaseContext();
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    finally
    {
        serverContext.ReleaseContext();
    }
}

/// QUERY RELATED OBJECTS.
public static void FeatureServer_QueryRelatedObjects()
{
    IServerContext serverContext = null;
    try
    {
        GISServerConnection serverConnection = new GISServerConnection();
        serverConnection.Connect("localhost");
        IServerObjectManager serverManager = serverConnection.ServerObjectManager;
        serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer");
        // Get the FeatureServer object extension.
        IServerObjectExtensionManager pSOEM = serverContext.ServerObject as
            IServerObjectExtensionManager;
        IGraphicFeatureServer featureServer = pSOEM.FindExtensionByTypeName(
            "FeatureServer")as IGraphicFeatureServer;
        IDataObjectTables dataObjectTables = featureServer.GetTables(false);
        //Add some OIDs for which related records will be fetched.
        ILongArray longOIDArray = serverContext.CreateObject("esriSystem.LongArray")
            as ILongArray;
        int elem = 0;
        for (elem = 0; elem < 25; elem++)
        {
            longOIDArray.Add(elem);
        }

        int relCount, relationshipID;
        if (dataObjectTables.Count > 0)
        {
            for (int i = 0; i < dataObjectTables.Count; i++)
            {
                int srcTableID = dataObjectTables.get_Element(i).ID;
                IRelateInfos relateInfos = dataObjectTables.get_Element(i).Relations;
                if (relateInfos != null)
                {
                    String tableName = dataObjectTables.get_Element(i).Name;
                    relCount = relateInfos.Count;
                    IServiceDataOptions serviceDataOptions =
                        serverContext.CreateObject("esriCarto.ServiceDataOptions")as
                        IServiceDataOptions;
                    serviceDataOptions.Format = "Native";
                    for (int j = 0; j < relCount; j++)
                    {
                        relationshipID = relateInfos.get_Element(j).RelationshipID;
                        //Get the service data for the queried related objetcs.
                        IServiceData serviceData = featureServer.QueryRelatedObjects
                            (srcTableID, longOIDArray, relationshipID, "", "*", true,
                            null, null, serviceDataOptions);
                        System.Object obj = serviceData.Object;
                        if (obj is DataObjects)
                        
                            // if paramater groupBySourceIds is false, dataObjects is returned
                        {
                            Console.WriteLine("Service data is Object");
                            //Do something with DataObjects.
                        }
                        else if (obj is DataObjectGroups)
                        
                            //If paramater groupBySourceIds is true, dataObjectGroups is returned.
                        {
                            Console.WriteLine("Service data is Object Group");
                            IDataObjectGroups dataObjectGroups = (IDataObjectGroups)
                                obj;
                            IDataObjectGroupArray dataObjectGroupArray =
                                dataObjectGroups.DataObjectGroupArray;
                            IDataObjectGroup dataObjectGroup;
                            for (int k = 0; k < dataObjectGroupArray.Count; k++)
                            {
                                dataObjectGroup = dataObjectGroupArray.get_Element(i)
                                    ;
                                IDataObjectArray dataObjectArray =
                                    dataObjectGroup.DataObjectArray;
                                IDataObjectEx dataobject;
                                IPropertySet pPropSet = serverContext.CreateObject(
                                    "esriSystem.PropertySet")as IPropertySet;
                                System.Object names;
                                System.Object values;
                                for (int m = 0; m < dataObjectArray.Count; m++)
                                {
                                    dataobject = dataObjectArray.get_Element(m);
                                    pPropSet = dataobject.Properties;
                                    pPropSet.GetAllProperties(out names, out values);
                                    // Do something with Names and Values populated.
                                }
                            }
                        }
                    } // End of for j.
                }
            } // End of for i.
        }
    }
    catch (Exception ex)
    {
        if (serverContext != null)
            serverContext.ReleaseContext();
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    finally
    {
        serverContext.ReleaseContext();
    }
}

/// APPLY EDITS (ADD).

public static void FeatureServer_ApplyEdits_ADD()
{
    IServerContext serverContext = null;
    try
    {
        GISServerConnection serverConnection = new GISServerConnection();
        serverConnection.Connect("localhost");
        IServerObjectManager serverManager = serverConnection.ServerObjectManager;
        serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer");
        // Get the FeatureServer object extension.
        IServerObjectExtensionManager pSOEM = serverContext.ServerObject as
            IServerObjectExtensionManager;
        IGraphicFeatureServer featureServer = pSOEM.FindExtensionByTypeName(
            "FeatureServer")as IGraphicFeatureServer;
        IServiceDataOptions serviceDataOptions = serverContext.CreateObject(
            "esriCarto.ServiceDataOptions")as IServiceDataOptions;
        serviceDataOptions.Format = "Native";
        ITableEdit tableEdit = serverContext.CreateObject("esriCarto.TableEdit")as
            ITableEdit;

        //ADDING NEW Service Call OBJECT. 
        ESRI.ArcGIS.Geometry.IPoint pNewServicePoint = serverContext.CreateObject(
            "esriGeometry.Point")as ESRI.ArcGIS.Geometry.IPoint;
        double x = 509373.224;
        double y = 684800.542;
        pNewServicePoint.PutCoords(x, y);
        IGraphicFeature pGraphicFeature = serverContext.CreateObject(
            "esriCarto.GraphicFeature")as IGraphicFeature;
        pGraphicFeature.Geometry = pNewServicePoint;
        IPropertySet pNewPropSet = serverContext.CreateObject(
            "esriSystem.PropertySet")as IPropertySet;
        pNewPropSet.SetProperty("Name", "New Customer2");
        pNewPropSet.SetProperty("Service_Details", "Put new resource");
        pNewPropSet.SetProperty("Service_Type", "New Service2");
        pNewPropSet.SetProperty("Tracking_Number", 101);
        pGraphicFeature.Properties = pNewPropSet;
        IDataObjectArray dataObjectArray = serverContext.CreateObject(
            "esriCarto.DataObjectArray")as IDataObjectArray;
        dataObjectArray.Add(pGraphicFeature);

        IDataObjects addDataObjects = serverContext.CreateObject(
            "esriCarto.DataObjects")as IDataObjects;
        addDataObjects.DataObjectArray = dataObjectArray;

        //Create an empty IDataobjects object that can passed for updates.
        IDataObjects addDataObjects1 = serverContext.CreateObject(
            "esriCarto.DataObjects")as IDataObjects;

        //Create an empty ILongArray object that can passed for deletes.
        ILongArray lngArr = serverContext.CreateObject("esriSystem.LongArray")as
            ILongArray;
        tableEdit.LayerOrTableID = 4;
        tableEdit.Adds = addDataObjects;

        tableEdit.Updates = addDataObjects1; //This is empty.
        tableEdit.Deletes = lngArr; //This is empty.

        ITableEdits tableEdits = serverContext.CreateObject("esriCarto.TableEdits")
            as ITableEdits;
        tableEdits.Add(tableEdit);

        ITableEditResults tableEditResult = featureServer.ApplyEdits(tableEdits);
    }
    catch (Exception ex)
    {
        if (serverContext != null)
            serverContext.ReleaseContext();
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    finally
    {
        serverContext.ReleaseContext();
    }
}

//// APPLY_EDITS (UPDATE).
public static void FeatureServer_ApplyEdits_UPDATE()
{
    IServerContext serverContext = null;
    try
    {
        GISServerConnection serverConnection = new GISServerConnection();
        serverConnection.Connect("localhost");
        IServerObjectManager serverManager = serverConnection.ServerObjectManager;
        serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer");
        // Get the FeatureServer object extension.
        IServerObjectExtensionManager pSOEM = serverContext.ServerObject as
            IServerObjectExtensionManager;
        IGraphicFeatureServer featureServer = pSOEM.FindExtensionByTypeName(
            "FeatureServer")as IGraphicFeatureServer;
        IServiceDataOptions serviceDataOptions = serverContext.CreateObject(
            "esriCarto.ServiceDataOptions")as IServiceDataOptions;
        serviceDataOptions.Format = "Native";

        IQueryFilter pQFilter = serverContext.CreateObject(
            "esriGeodatabase.QueryFilter")as IQueryFilter;
        pQFilter.WhereClause = "Service_Type = 'New Service'";
        IServiceData serviceData = featureServer.Query(4, "", pQFilter,
            serviceDataOptions);
        System.Object obj = serviceData.Object;
        IDataObjects querydataObjects = obj as DataObjects;
        IDataObjectArray querydataObjectArray = querydataObjects.DataObjectArray;

        //Create an empty IDataObjects object that can passed for Add.
        IDataObjects addDataObjects1 = serverContext.CreateObject(
            "esriCarto.DataObjects")as IDataObjects;

        //Create an empty ILongArray object that can passed for deletes.
        ILongArray lngArr = serverContext.CreateObject("esriSystem.LongArray")as
            ILongArray;

        ITableEdit tableEdit = serverContext.CreateObject("esriCarto.TableEdit")as
            ITableEdit;
        tableEdit.LayerOrTableID = 4;
        tableEdit.Adds = addDataObjects1; //This is empty.
        tableEdit.Updates = querydataObjects;
        tableEdit.Deletes = lngArr; //This is empty.
        ITableEdits tableEdits = serverContext.CreateObject("esriCarto.TableEdits")
            as ITableEdits;
        tableEdits.Add(tableEdit);

        ITableEditResults tableEditResult = featureServer.ApplyEdits(tableEdits);
    }
    catch (Exception ex)
    {
        if (serverContext != null)
            serverContext.ReleaseContext();
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    finally
    {
        serverContext.ReleaseContext();
    }
}

/// APPLY EDITS (DELETE).
public static void FeatureServer_ApplyEdits_DELETE()
{
    IServerContext serverContext = null;
    try
    {
        GISServerConnection serverConnection = new GISServerConnection();
        serverConnection.Connect("localhost");
        IServerObjectManager serverManager = serverConnection.ServerObjectManager;
        serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer");
        // Get the FeatureServer object extension.
        IServerObjectExtensionManager pSOEM = serverContext.ServerObject as
            IServerObjectExtensionManager;
        IGraphicFeatureServer featureServer = pSOEM.FindExtensionByTypeName(
            "FeatureServer")as IGraphicFeatureServer;
        IServiceDataOptions serviceDataOptions = serverContext.CreateObject(
            "esriCarto.ServiceDataOptions")as IServiceDataOptions;
        serviceDataOptions.Format = "Native";

        //Create an empty IDataObjects object that can passed for Add.
        IDataObjects addDataObjects = serverContext.CreateObject(
            "esriCarto.DataObjects")as IDataObjects;

        //Create an empty IDataObjects object that can passed for Updates.
        IDataObjects updateDataObjects = serverContext.CreateObject(
            "esriCarto.DataObjects")as IDataObjects;

        IQueryFilter pQFilter = serverContext.CreateObject(
            "esriGeodatabase.QueryFilter")as IQueryFilter;
        pQFilter.WhereClause = "OBJECTID > 5 and OBJECTID < 10";
        ILongArray longOIDArray = serverContext.CreateObject("esriSystem.LongArray")
            as ILongArray;
        longOIDArray.Add(5);
        longOIDArray.Add(6);
        longOIDArray.Add(7);
        ITableEdit tableEdit = serverContext.CreateObject("esriCarto.TableEdit")as
            ITableEdit;
        tableEdit.LayerOrTableID = 4;
        tableEdit.Deletes = longOIDArray;

        tableEdit.Adds = addDataObjects; //this is empty
        tableEdit.Updates = updateDataObjects; //this is empty

        ITableEdits tableEdits = serverContext.CreateObject("esriCarto.TableEdits")
            as ITableEdits;
        tableEdits.Add(tableEdit);
        ITableEditResults tableEditResult = featureServer.ApplyEdits(tableEdits);
    }
    catch (Exception ex)
    {
        if (serverContext != null)
            serverContext.ReleaseContext();
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    finally
    {
        serverContext.ReleaseContext();
    }
}

/// ADD ATTACHEMENT.
public static void FeatureServer_AddAttachment()
{
    IServerContext serverContext = null;
    try
    {
        GISServerConnection serverConnection = new GISServerConnection();
        serverConnection.Connect("Localhost");
        IServerObjectManager serverManager = serverConnection.ServerObjectManager;
        serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer");
        // Get the FeatureServer object extension.
        IServerObjectExtensionManager pSOEM = serverContext.ServerObject as
            IServerObjectExtensionManager;
        IGraphicFeatureServer featureServer = pSOEM.FindExtensionByTypeName(
            "FeatureServer")as IGraphicFeatureServer;
        IDataObjectTables layersAndTables = featureServer.GetTables(false);
        IDataObjectTable layerOrTable = null;
        for (int x = 0; x < layersAndTables.Count; x++)
        {
            layerOrTable = layersAndTables.get_Element(x);
            if (layerOrTable.Name == "ServiceCalls")
            {
                if (layerOrTable.HasAttachments)
                {
                    IServiceDataOptions serviceDataOptions =
                        serverContext.CreateObject("esriCarto.ServiceDataOptions")as
                        IServiceDataOptions;
                    serviceDataOptions.Format = "Native";
                    IQueryFilter pQFilter = serverContext.CreateObject(
                        "esriGeodatabase.QueryFilter")as IQueryFilter;
                    pQFilter.WhereClause = "ObjectID = 8";
                    IServiceData serviceData = featureServer.Query(4, "", pQFilter,
                        serviceDataOptions);
                    System.Object obj = serviceData.Object;
                    IDataObjects dataObjects = obj as DataObjects;
                    IDataObjectArray dataObjectArray = dataObjects.DataObjectArray;
                    IDataObjectEx dataobject = null;
                    for (int i = 0; i < dataObjectArray.Count; i++)
                    {
                        dataobject = dataObjectArray.get_Element(i); 
                            //Get the row with object ID 8.
                        break;
                    }
                    if (dataobject != null)
                    {
                        string jpgContentType = "image/jpg";
                        //Get jpg bytes.
                        System.IO.FileStream jpgFile = new System.IO.FileStream(@
                            "C:\\Images\\IMG_1110.JPG", System.IO.FileMode.Open);
                        int byteLengthJPG = (int)jpgFile.Length;
                        System.IO.BinaryReader brJPG = new System.IO.BinaryReader
                            (jpgFile);
                        byte[] attDataBytesJPG = brJPG.ReadBytes(byteLengthJPG);
                        brJPG.Close();
                        jpgFile.Close();
                        IAttachmentDataArray attachmentsArray =
                            serverContext.CreateObject(
                            "esriGeodatabase.AttachmentDataArray")as
                            IAttachmentDataArray;
                        IAttachmentData attachmentData = serverContext.CreateObject(
                            "esriGeodatabase.AttachmentData")as IAttachmentData;
                        attachmentData.Data = attDataBytesJPG;
                        IAttachmentInfo attachmentInfo = serverContext.CreateObject(
                            "esriGeodatabase.AttachmentInfo")as IAttachmentInfo;
                        attachmentInfo.Name = "TestAttchmentWithAO";
                        attachmentInfo.ContentType = jpgContentType;
                        attachmentInfo.ParentID = 8;
                        attachmentData.AttachmentInfo = attachmentInfo;
                        attachmentsArray.Add(attachmentData);
                        IEditResults pResult = featureServer.AddAttachments(4,
                            attachmentsArray);
                    }
                }
                else
                {
                    Console.WriteLine("Layer/Table has no attachments");
                    return ;
                }
                break;
            }
        }
    }
    catch (Exception ex)
    {
        if (serverContext != null)
            serverContext.ReleaseContext();
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    finally
    {
        serverContext.ReleaseContext();
    }
}
[VB.NET]
'**** QUERY
Public Shared Sub FeatureServer_Query()
Dim serverContext As IServerContext = Nothing
Try
Dim serverConnection As New GISServerConnection()
serverConnection.Connect("Localhost")
Dim serverManager As IServerObjectManager = serverConnection.ServerObjectManager
serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer")
' Get the FeatureServer object extension.
Dim pSOEM As IServerObjectExtensionManager = TryCast(serverContext.ServerObject, IServerObjectExtensionManager)
Dim featureServer As IGraphicFeatureServer = TryCast(pSOEM.FindExtensionByTypeName("FeatureServer"), IGraphicFeatureServer)
Dim serviceDataOptions As IServiceDataOptions = TryCast(serverContext.CreateObject("esriCarto.ServiceDataOptions"), IServiceDataOptions)
serviceDataOptions.Format = "Native"
Dim pQFilter As IQueryFilter = TryCast(serverContext.CreateObject("esriGeodatabase.QueryFilter"), IQueryFilter)
pQFilter.WhereClause = "Service_Type = 'Repair'"
Dim serviceData As IServiceData = featureServer.Query(4, "", pQFilter, serviceDataOptions)
Dim obj As System.Object = serviceData.Object
If TypeOf obj Is IDataObjects Then
    Dim dataObjects As IDataObjects = TryCast(obj, DataObjects)
    Dim dataObjectArray As IDataObjectArray = dataObjects.DataObjectArray
    Dim dataobject As IDataObjectEx
    Dim pPropSet As IPropertySet = TryCast(serverContext.CreateObject("esriSystem.PropertySet"), IPropertySet)
    Dim names As System.Object
    Dim values As System.Object
    For i As Integer = 0 To dataObjectArray.Count - 1
        dataobject = dataObjectArray.Element(i)
        pPropSet = dataobject.Properties
        pPropSet.GetAllProperties(names, values)
        ' Do something with Names and Values populated which are nothing but field names and their values.
    Next i
ElseIf TypeOf obj Is IDataObjectGroups Then
    'If object is of type DataObjetGroups, do something.
End If
Catch ex As Exception
If serverContext IsNot Nothing Then
    serverContext.ReleaseContext()
End If
System.Diagnostics.Debug.WriteLine(ex.Message)
Finally
serverContext.ReleaseContext()
End Try
End Sub

'**** QUERYRELATEDOBJECTS
Public Shared Sub FeatureServer_QueryRelatedObjects()
Dim serverContext As IServerContext = Nothing
Try
Dim serverConnection As New GISServerConnection()
serverConnection.Connect("localhost")
Dim serverManager As IServerObjectManager = serverConnection.ServerObjectManager
serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer")
' Get the FeatureServer object extension.
Dim pSOEM As IServerObjectExtensionManager = TryCast(serverContext.ServerObject, IServerObjectExtensionManager)
Dim featureServer As IGraphicFeatureServer = TryCast(pSOEM.FindExtensionByTypeName("FeatureServer"), IGraphicFeatureServer)
Dim dataObjectTables As IDataObjectTables = featureServer.GetTables(False)
'Add some OIDs for which related records will be fetched.
Dim longOIDArray As ILongArray = TryCast(serverContext.CreateObject("esriSystem.LongArray"), ILongArray)
Dim elem As Integer = 0
For elem = 0 To 24
    longOIDArray.Add(elem)
Next elem

Dim relCount, relationshipID As Integer
If dataObjectTables.Count > 0 Then
    For i As Integer = 0 To dataObjectTables.Count - 1
        Dim srcTableID As Integer = dataObjectTables.Element(i).ID
        Dim relateInfos As IRelateInfos = dataObjectTables.Element(i).Relations
        If relateInfos IsNot Nothing Then
            Dim tableName As String = dataObjectTables.Element(i).Name
            relCount = relateInfos.Count
            Dim serviceDataOptions As IServiceDataOptions = TryCast(serverContext.CreateObject("esriCarto.ServiceDataOptions"), IServiceDataOptions)
            serviceDataOptions.Format = "Native"
            For j As Integer = 0 To relCount - 1
                relationshipID = relateInfos.Element(j).RelationshipID
                'Get the service data for the queried related objetcs.
                Dim serviceData As IServiceData = featureServer.QueryRelatedObjects(srcTableID, longOIDArray, relationshipID, "", "*", True, Nothing, Nothing, serviceDataOptions)
                Dim obj As System.Object = serviceData.Object
                If TypeOf obj Is DataObjects Then ' if paramater groupBySourceIds is false, dataObjects is returned
                    Console.WriteLine("Service data is Object")
                    'Do something with DataObjects.
                ElseIf TypeOf obj Is DataObjectGroups Then 'if paramater groupBySourceIds is true, dataObjectGroups is returned
                    Console.WriteLine("Service data is Object Group")
                    Dim dataObjectGroups As IDataObjectGroups = CType(obj, IDataObjectGroups)
                    Dim dataObjectGroupArray As IDataObjectGroupArray = dataObjectGroups.DataObjectGroupArray
                    Dim dataObjectGroup As IDataObjectGroup
                    For k As Integer = 0 To dataObjectGroupArray.Count - 1
                        dataObjectGroup = dataObjectGroupArray.Element(i)
                        Dim dataObjectArray As IDataObjectArray = dataObjectGroup.DataObjectArray
                        Dim dataobject As IDataObjectEx
                        Dim pPropSet As IPropertySet = TryCast(serverContext.CreateObject("esriSystem.PropertySet"), IPropertySet)
                        Dim names As System.Object
                        Dim values As System.Object
                        For m As Integer = 0 To dataObjectArray.Count - 1
                            dataobject = dataObjectArray.Element(m)
                            pPropSet = dataobject.Properties
                            pPropSet.GetAllProperties(names, values)
                            ' Do something with Names and Values populated.
                        Next m
                    Next k
                End If
            Next j ' end of for j
        End If
    Next i ' end of for i
End If
Catch ex As Exception
If serverContext IsNot Nothing Then
    serverContext.ReleaseContext()
End If
System.Diagnostics.Debug.WriteLine(ex.Message)
Finally
serverContext.ReleaseContext()
End Try
End Sub


'**** APPLYEDITS (ADD)
Public Shared Sub FeatureServer_ApplyEdits_ADD()
Dim serverContext As IServerContext = Nothing
Try
Dim serverConnection As New GISServerConnection()
serverConnection.Connect("localhost")
Dim serverManager As IServerObjectManager = serverConnection.ServerObjectManager
serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer")
' Get the FeatureServer object extension.
Dim pSOEM As IServerObjectExtensionManager = TryCast(serverContext.ServerObject, IServerObjectExtensionManager)
Dim featureServer As IGraphicFeatureServer = TryCast(pSOEM.FindExtensionByTypeName("FeatureServer"), IGraphicFeatureServer)
Dim serviceDataOptions As IServiceDataOptions = TryCast(serverContext.CreateObject("esriCarto.ServiceDataOptions"), IServiceDataOptions)
serviceDataOptions.Format = "Native"
Dim tableEdit As ITableEdit = TryCast(serverContext.CreateObject("esriCarto.TableEdit"), ITableEdit)
'ADDING NEW Service Call OBEJCT.
Dim pNewServicePoint As ESRI.ArcGIS.Geometry.IPoint = TryCast(serverContext.CreateObject("esriGeometry.Point"), ESRI.ArcGIS.Geometry.IPoint)
Dim x As Double = 509373.224
Dim y As Double = 684800.542
pNewServicePoint.PutCoords(x, y)
Dim pGraphicFeature As IGraphicFeature = TryCast(serverContext.CreateObject("esriCarto.GraphicFeature"), IGraphicFeature)
pGraphicFeature.Geometry = pNewServicePoint
Dim pNewPropSet As IPropertySet = TryCast(serverContext.CreateObject("esriSystem.PropertySet"), IPropertySet)
pNewPropSet.SetProperty("Name", "New Customer2")
pNewPropSet.SetProperty("Service_Details", "Put new resource")
pNewPropSet.SetProperty("Service_Type", "New Service2")
pNewPropSet.SetProperty("Tracking_Number", 101)
pGraphicFeature.Properties = pNewPropSet
Dim dataObjectArray As IDataObjectArray = TryCast(serverContext.CreateObject("esriCarto.DataObjectArray"), IDataObjectArray)
dataObjectArray.Add(pGraphicFeature)
Dim addDataObjects As IDataObjects = TryCast(serverContext.CreateObject("esriCarto.DataObjects"), IDataObjects)
addDataObjects.DataObjectArray = dataObjectArray
Dim addDataObjects1 As IDataObjects = TryCast(serverContext.CreateObject("esriCarto.DataObjects"), IDataObjects)
Dim lngArr As ILongArray = TryCast(serverContext.CreateObject("esriSystem.LongArray"), ILongArray)
tableEdit.LayerOrTableID = 4
tableEdit.Adds = addDataObjects
tableEdit.Updates = addDataObjects1
tableEdit.Deletes = lngArr
Dim tableEdits As ITableEdits = TryCast(serverContext.CreateObject("esriCarto.TableEdits"), ITableEdits)
tableEdits.Add(tableEdit)

Dim tableEditResult As ITableEditResults = featureServer.ApplyEdits(tableEdits)
Catch ex As Exception
If serverContext IsNot Nothing Then
    serverContext.ReleaseContext()
End If
System.Diagnostics.Debug.WriteLine(ex.Message)
Finally
serverContext.ReleaseContext()
End Try
End Sub

'**** APPLYEDITS (UPDATE)
Public Shared Sub FeatureServer_ApplyEdits_UPDATE()
Dim serverContext As IServerContext = Nothing
Try
Dim serverConnection As New GISServerConnection()
serverConnection.Connect("localhost")
Dim serverManager As IServerObjectManager = serverConnection.ServerObjectManager
serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer")
' Get the FeatureServer object extension.
Dim pSOEM As IServerObjectExtensionManager = TryCast(serverContext.ServerObject, IServerObjectExtensionManager)
Dim featureServer As IGraphicFeatureServer = TryCast(pSOEM.FindExtensionByTypeName("FeatureServer"), IGraphicFeatureServer)
Dim serviceDataOptions As IServiceDataOptions = TryCast(serverContext.CreateObject("esriCarto.ServiceDataOptions"), IServiceDataOptions)
serviceDataOptions.Format = "Native"

Dim pQFilter As IQueryFilter = TryCast(serverContext.CreateObject("esriGeodatabase.QueryFilter"), IQueryFilter)
pQFilter.WhereClause = "Service_Type = 'New Service'"
Dim serviceData As IServiceData = featureServer.Query(4, "", pQFilter, serviceDataOptions)
Dim obj As System.Object = serviceData.Object
Dim querydataObjects As IDataObjects = TryCast(obj, DataObjects)
Dim querydataObjectArray As IDataObjectArray = querydataObjects.DataObjectArray
Dim addDataObjects1 As IDataObjects = TryCast(serverContext.CreateObject("esriCarto.DataObjects"), IDataObjects)
Dim lngArr As ILongArray = TryCast(serverContext.CreateObject("esriSystem.LongArray"), ILongArray)
Dim tableEdit As ITableEdit = TryCast(serverContext.CreateObject("esriCarto.TableEdit"), ITableEdit)
tableEdit.LayerOrTableID = 4
tableEdit.Adds = addDataObjects1
tableEdit.Updates = querydataObjects
tableEdit.Deletes = lngArr
Dim tableEdits As ITableEdits = TryCast(serverContext.CreateObject("esriCarto.TableEdits"), ITableEdits)
tableEdits.Add(tableEdit)

Dim tableEditResult As ITableEditResults = featureServer.ApplyEdits(tableEdits)
Catch ex As Exception
If serverContext IsNot Nothing Then
    serverContext.ReleaseContext()
End If
System.Diagnostics.Debug.WriteLine(ex.Message)
Finally
serverContext.ReleaseContext()
End Try
End Sub

'**** APPLYEDITS (DELETE)
Public Shared Sub FeatureServer_ApplyEdits_DELETE()
Dim serverContext As IServerContext = Nothing
Try
Dim serverConnection As New GISServerConnection()
serverConnection.Connect("localhost")
Dim serverManager As IServerObjectManager = serverConnection.ServerObjectManager
serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer")
' Get the FeatureServer object extension.
Dim pSOEM As IServerObjectExtensionManager = TryCast(serverContext.ServerObject, IServerObjectExtensionManager)
Dim featureServer As IGraphicFeatureServer = TryCast(pSOEM.FindExtensionByTypeName("FeatureServer"), IGraphicFeatureServer)
Dim serviceDataOptions As IServiceDataOptions = TryCast(serverContext.CreateObject("esriCarto.ServiceDataOptions"), IServiceDataOptions)
serviceDataOptions.Format = "Native"
Dim addDataObjects As IDataObjects = TryCast(serverContext.CreateObject("esriCarto.DataObjects"), IDataObjects)
Dim updateDataObjects As IDataObjects = TryCast(serverContext.CreateObject("esriCarto.DataObjects"), IDataObjects)
Dim pQFilter As IQueryFilter = TryCast(serverContext.CreateObject("esriGeodatabase.QueryFilter"), IQueryFilter)
pQFilter.WhereClause = "OBJECTID > 5 and OBJECTID < 10"
Dim longOIDArray As ILongArray = TryCast(serverContext.CreateObject("esriSystem.LongArray"), ILongArray)
longOIDArray.Add(5)
longOIDArray.Add(6)
longOIDArray.Add(7)
Dim tableEdit As ITableEdit = TryCast(serverContext.CreateObject("esriCarto.TableEdit"), ITableEdit)
tableEdit.LayerOrTableID = 4
tableEdit.Deletes = longOIDArray
tableEdit.Adds = addDataObjects
tableEdit.Updates = updateDataObjects
Dim tableEdits As ITableEdits = TryCast(serverContext.CreateObject("esriCarto.TableEdits"), ITableEdits)
tableEdits.Add(tableEdit)
Dim tableEditResult As ITableEditResults = featureServer.ApplyEdits(tableEdits)
Catch ex As Exception
If serverContext IsNot Nothing Then
    serverContext.ReleaseContext()
End If
System.Diagnostics.Debug.WriteLine(ex.Message)
Finally
serverContext.ReleaseContext()
End Try
End Sub

'**** ADDATTACHMENT

Public Shared Sub FeatureServer_AddAttachment()
Dim serverContext As IServerContext = Nothing
Try
Dim serverConnection As New GISServerConnection()
serverConnection.Connect("Localhost")
Dim serverManager As IServerObjectManager = serverConnection.ServerObjectManager
serverContext = serverManager.CreateServerContext("LandbasePM", "MapServer")
' Get the FeatureServer object extension.
Dim pSOEM As IServerObjectExtensionManager = TryCast(serverContext.ServerObject, IServerObjectExtensionManager)
Dim featureServer As IGraphicFeatureServer = TryCast(pSOEM.FindExtensionByTypeName("FeatureServer"), IGraphicFeatureServer)
Dim layersAndTables As IDataObjectTables = featureServer.GetTables(False)
Dim layerOrTable As IDataObjectTable = Nothing
For x As Integer = 0 To layersAndTables.Count - 1
    layerOrTable = layersAndTables.Element(x)
    If layerOrTable.Name = "ServiceCalls" Then
        If layerOrTable.HasAttachments Then
            Dim serviceDataOptions As IServiceDataOptions = TryCast(serverContext.CreateObject("esriCarto.ServiceDataOptions"), IServiceDataOptions)
            serviceDataOptions.Format = "Native"
            Dim pQFilter As IQueryFilter = TryCast(serverContext.CreateObject("esriGeodatabase.QueryFilter"), IQueryFilter)
            pQFilter.WhereClause = "ObjectID = 8"
            Dim serviceData As IServiceData = featureServer.Query(4, "", pQFilter, serviceDataOptions)
            Dim obj As System.Object = serviceData.Object
            Dim dataObjects As IDataObjects = TryCast(obj, DataObjects)
            Dim dataObjectArray As IDataObjectArray = dataObjects.DataObjectArray
            Dim dataobject As IDataObjectEx = Nothing
            For i As Integer = 0 To dataObjectArray.Count - 1
                dataobject = dataObjectArray.Element(i) 'get the row with object ID 8
                Exit For
            Next i
            If dataobject IsNot Nothing Then
                Dim jpgContentType As String = "image/jpg"
                'Get jpg bytes.
                Dim jpgFile As New System.IO.FileStream("C:\\Images\\IMG_1110.JPG", System.IO.FileMode.Open)
                Dim byteLengthJPG As Integer = CInt(Fix(jpgFile.Length))
                Dim brJPG As New System.IO.BinaryReader(jpgFile)
                Dim attDataBytesJPG() As Byte = brJPG.ReadBytes(byteLengthJPG)
                brJPG.Close()
                jpgFile.Close()
                Dim attachmentsArray As IAttachmentDataArray = TryCast(serverContext.CreateObject("esriGeodatabase.AttachmentDataArray"), IAttachmentDataArray)
                Dim attachmentData As IAttachmentData = TryCast(serverContext.CreateObject("esriGeodatabase.AttachmentData"), IAttachmentData)
                attachmentData.Data = attDataBytesJPG
                Dim attachmentInfo As IAttachmentInfo = TryCast(serverContext.CreateObject("esriGeodatabase.AttachmentInfo"), IAttachmentInfo)
                attachmentInfo.Name = "TestAttchmentWithAO"
                attachmentInfo.ContentType = jpgContentType
                attachmentInfo.ParentID = 8
                attachmentData.AttachmentInfo = attachmentInfo
                attachmentsArray.Add(attachmentData)
                Dim pResult As IEditResults = featureServer.AddAttachments(4, attachmentsArray)
            End If
        Else
            Console.WriteLine("Layer/Table has no attachments")
            Return
        End If
        Exit For
    End If
Next x
Catch ex As Exception
If serverContext IsNot Nothing Then
    serverContext.ReleaseContext()
End If
System.Diagnostics.Debug.WriteLine(ex.Message)
Finally
serverContext.ReleaseContext()
End Try
End Sub