IMAExtensible2CallImport.GetImportEntries Method

Persists a batch of entries in the connected system. Called for multiple entries that are imported. Cans assume OpenImportConnectionhas been called successfully.

Namespace: Microsoft.MetadirectoryServices
Assembly: Microsoft.MetadirectoryServicesEx (in Microsoft.MetadirectoryServicesEx.dll)

Usage

'Usage
Dim instance As IMAExtensible2CallImport
Dim importRunStep As GetImportEntriesRunStep
Dim returnValue As GetImportEntriesResults

returnValue = instance.GetImportEntries(importRunStep)

Syntax

'Declaration
Function GetImportEntries ( _
    importRunStep As GetImportEntriesRunStep _
) As GetImportEntriesResults
GetImportEntriesResults GetImportEntries (
    GetImportEntriesRunStep importRunStep
)
GetImportEntriesResults^ GetImportEntries (
    GetImportEntriesRunStep^ importRunStep
)
GetImportEntriesResults GetImportEntries (
    GetImportEntriesRunStep importRunStep
)
function GetImportEntries (
    importRunStep : GetImportEntriesRunStep
) : GetImportEntriesResults

Parameters

Return Value

Returns GetImportEntriesResultsobject that contains the custom data, whether there are more objects to import, and a list of GetImportEntriesRunStep objects..

Remarks

GetImportEntries is the workhorse of import. This method will read all data from the connected system and translate the information to the object model used by the Synchronization Service. There are three different contexts the method will be called in: “Full Import”, “Delta Import”, and “Full Object Import”. The first two are created as run profiles by the administrator. The last can only be invoked by the engine.

If you implement this method then you must support “Full Import”. A Full Import should be designed so it will always return the data as if it was the first time the data has been read from the connected directory, i.e. everything should be returned as new (Add) objects. All objects must be returned and they should only be presented once to the engine. The engine is responsible for correlating the supplied information with the data already present in the connector space. At the end of the run all objects not returned but present in the connector space will be marked as obsolete and deleted. For this reason if the run wasn’t successful make sure to throw an exception to make sure objects are not incorrectly obsoleted. At the end of the run you should return a watermark in CustomDataso a delta import can start from where full import ended.

Supporting “Delta Import” is optional and set in the IMAExtensible2GetCapabilities interface. In a delta import the returned data should look like a list of changes as read from the connected directory. This list can contain new, changed, and deleted objects and attributes. For changed objects the engine is responsible for merging supplied changes with the data in the connector space. The bookmark for where to read from is generally referred to as the watermark and stored in CustomData. The watermark is persisted between the runs on condition that no error was returned. If an object level error or exception is returned then the watermark will not be persisted; this will in a real environment lead to longer and longer delta import times and usually has to be remediated by a full import.

The mode “Full Object Import” goes with Delta import is invoked by the engine when a batch returns updates to objects for which there is no representation in the connector space. Since the engine can’t determine how the new object should look like this method is called with a list of object identifiers for which the engine need a full object representation.

The number of objects which can be returned is defined on the run step as the page size. The actual number of objects returned can be smaller but it cannot be more than this limit.

This method is called until the result collection’s MoreToImport is set to false.

For the engine there is a difference between returning a “Full object” and a “Delta object”. When a full object is returned it is considered to be “this is how the object should look like, if an attribute isn’t supplied it is implicitly deleted”. When a delta object is returned it is considered to be “this is changes to an existing object, if I didn’t supply the attribute it should remain unchanged with its current value”. Full objects are represented by the Add and Replace and delta objects with Update, and Delete. When you return an object you must set ObjectModificationType before you set attribute changes otherwise the default Addwill be used.

In a Full import you must only return the full object using Add. In Delta import you can use all modification types and can mix them freely. You can decide if you want to return changes to existing objects as Full Objects using Replace or as Delta Objects using Update.

Attribute changes will follow the object modification. For Full Objects you can only return attribute add. For an object Update you can return the full list of attribute modifications: Add, Replace, Update, and Delete. The concept for attribute modifications is similar to object modifications. The special case is for Update when working with multi-valued attributes including multi-valued reference attributes, e.g. member. In this case you can also return value level modifications of type Add and Delete.

This is a sample for how to return a Full Object using an object modification Add.

CSEntryChange csentry1 = CSEntryChange.Create();
 
                csentry1.ObjectModificationType = ObjectModificationType.Add;
                csentry1.ObjectType = "Person";
                csentry1.DN = "CN=Object1,CN=Users,DC=contoso,DC=com";
 
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("anchor-attribute", "1"));
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("name", "Object1"));
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("email", "Object1@contoso.com"));
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("multiAttr", new List<object>() { "value1", "value1", "value3" }));
 
                csentries.Add(csentry1);

This is a sample returning a Full object using Replace in a Delta import. Note that all attributes and values are returned as CreateAttributeAdd(String,Object).

csentry1.ObjectModificationType = ObjectModificationType.Replace;
csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("anchor-attribute", "1"));

This is a sample returning a Delta object using object modification Update. The attributes are returned as CreateAttributeReplace(String,Object).

csentry1.ObjectModificationType = ObjectModificationType.Update;
csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeReplace("anchor-attribute", "1"));

This is a sample returning a Delta object with Update and with attribute level CreateAttributeUpdate(String,Object).

csentry1.ObjectModificationType = ObjectModificationType.Update;
csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeUpdate("company", IList<ValueChange> valueChanges));
csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeUpdate("company”));

Exceptions: Return values, Errors, and Exceptions

The following is an example of GetImportEntries.

  public GetImportEntriesResults GetImportEntries(GetImportEntriesRunStep importRunStep)
        {
            //
            // In our sample below, we create objects using a fixed format.
            //
            GetImportEntriesResults importReturnInfo;
            List<CSEntryChange> csentries = new List<CSEntryChange>();
 
            // Full Import.
            if (OperationType.Full == m_importOperation)
            {
                // Object 1
                CSEntryChange csentry1 = CSEntryChange.Create();
 
                csentry1.ObjectModificationType = ObjectModificationType.Add;
                csentry1.ObjectType = "Person";
                csentry1.DN = "CN=Object1,CN=Users,DC=contoso,DC=com";
 
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("anchor-attribute", "1"));
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("name", "Object1"));
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("email", "Object1@contoso.com"));
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("multiAttr", new List<object>() { "value1", "value1", "value3" }));
 
                csentries.Add(csentry1);
 
                // Object 2
                CSEntryChange csentry2 = CSEntryChange.Create();
 
                csentry2.ObjectModificationType = ObjectModificationType.Add;
                csentry2.ObjectType = "Person";
                csentry2.DN = "CN=Object2,CN=Users,DC=contoso,DC=com";
 
                csentry2.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("anchor-attribute", "2"));
                csentry2.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("name", "Object2"));
                csentry2.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("email", "Object2@contoso.com"));
                csentry2.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("multiAttr", new List<object>() { "value4", "value5", "value6" }));
 
                csentries.Add(csentry2);
            }
 
            // Delta Import.
            else if (OperationType.Delta == m_importOperation)
            {
                // Replace "name" for object 1
                CSEntryChange csentry1 = CSEntryChange.Create();
 
                csentry1.ObjectModificationType = ObjectModificationType.Update;
                csentry1.DN = "CN=Object1,CN=Users,DC=contoso,DC=com";
 
                csentry1.AttributeChanges.Add(AttributeChange.CreateAttributeReplace("name", "Object1-A"));
 
                csentries.Add(csentry1);
 
                // Add/remove multi-valued attributes values for object 1
                CSEntryChange csentry2 = CSEntryChange.Create();
 
                csentry2.ObjectModificationType = ObjectModificationType.Update;
                csentry2.DN = "CN=Object2,CN=Users,DC=contoso,DC=com";
 
                List<ValueChange> valueChanges = new List<ValueChange>();
                valueChanges.Add(ValueChange.CreateValueDelete("value6"));
                valueChanges.Add(ValueChange.CreateValueAdd("value7"));
                csentry2.AttributeChanges.Add(AttributeChange.CreateAttributeUpdate("multiAttr", valueChanges));
 
                csentries.Add(csentry2);
            }
 
            // Create the result
            importReturnInfo = new GetImportEntriesResults();
            importReturnInfo.MoreToImport = false;
            importReturnInfo.CSEntries = csentries;
 
            // Also, GetImportEntriesResults.CustomData can be used for retaining necessary data
            // for performing a subsequent import. 
            // A typical case of this might be the watermark used 
            // for delta import.
            //
            return importReturnInfo;
        }

Thread Safety

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Platforms

Target Platforms

Change History

See Also

Reference

IMAExtensible2CallImport Interface
IMAExtensible2CallImport Members
Microsoft.MetadirectoryServices Namespace