Example: Connected Data Source Extension for OLEDB Database access

This topic contains a code example to create a connected data source extension for connecting to a database by means of OLE/DB.

This example uses methods of the IMAEXtensibleFileImport interface to import data from an XML file and methods of the IMAExtensibleCallExport interface and the OLEDB Provider to export the information to a SQL database.

The following C# code example shows how to create a connected data source extension for call-based data sources.

using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using Microsoft.MetadirectoryServices;
using System.Data; 
using System.Data.SqlClient;  
using System.Data.OleDb;

namespace Miis_CallExport
{
  public class MACallExport :  
  IMAExtensibleFileImport, 
  IMAExtensibleCallExport
  {
  public MACallExport() {}

  // ------------------ C O N S T A N T S ------------------------
  private const string PARAM_SQLTABLENAME = "Table";
  private const string PARAM_SQLWHERECLAUSE = "SQLWhereClause";
  private const string PARAM_SQLDATABASE = "Database";
  private const string PARAM_SQLTIMEOUT = "Timeout";
  private const string PARAM_SQLSECURITY = "Security";
  private const string PARAM_SQLPROVIDER = "Provider";
  // Not needed: private const string 
  // PARAM_ESCAPEANCHOR = "EscapeAnchor";


  // ------------------  I M P O R T  -----------------------------
  //
  private string EscapeStringForImport(string escape)
  {
  if(escape == null)
  return null;

  escape.Replace("\"", "\"\""); 
  return String.Format("\"{0}\"", escape);
  } // EscapeStringForImport

  private string ConstructConnectionString
  (
  string                      connectTo, 
  string                      user, 
  string                      password, 
  ConfigParameterCollection   configParameters
  )
  {
  string connectionString = "";
  if(configParameters[PARAM_SQLSECURITY].Value.ToUpper().Equals
     ("SSPI"))
  {
  connectionString = String.Format("Provider={0};
     Persist Security Info=False;Integrated Security=SSPI;
     Initial Catalog={1};Data Source={2};Connect Timeout={3}",
  configParameters[PARAM_SQLPROVIDER].Value,
  configParameters[PARAM_SQLDATABASE].Value,
  connectTo,
  configParameters[PARAM_SQLTIMEOUT].Value);
  }
  else
  {
  connectionString = String.Format("Provider={0};
     Persist Security Info=False;User ID={1};Password={2};
     Initial Catalog={3};Data Source={4};Connect Timeout={5}",
  configParameters[PARAM_SQLPROVIDER].Value,
  user,
  password,
  configParameters[PARAM_SQLDATABASE].Value,
  connectTo,
  configParameters[PARAM_SQLTIMEOUT].Value);
  }
  return connectionString;
  } //ConstructConnectionString

  public void GenerateImportFile
  ( 
  string                      filename, 
  string                      connectTo, 
  string                      user, 
  string                      password, 
  ConfigParameterCollection   configParameters,
  bool                        fullImport, 
  TypeDescriptionCollection   types,
  ref string                  customData 
  )
  {
  if(!fullImport)
  {
  throw new TerminateRunException
     ("This MA only supports full import"); 
  }

  //---------------------------------------------------------------
  // Construct the columns to select from the SQL table by
  // enumerating through the attributes of the first object type.
  // This assumes that the DB MA schema exposes all attributes 
   // available for all object types
  //---------------------------------------------------------------
  string sqlColumns = "";
  string objectType = "";
  ArrayList attributeList = new ArrayList();
  foreach(TypeDescription t in types)
  {
  objectType = t.Name; 
  foreach(AttributeDescription a in t.Attributes)
  {
  sqlColumns = sqlColumns + a.Name + ","; 
  attributeList.Add(a.Name);
  }
  break;
  }
  if(sqlColumns.Equals(""))
  {
  throw new TerminateRunException(
     "No attributes in schema definition");
  }
   // remove last comma
  sqlColumns = sqlColumns.Substring(0, sqlColumns.Length-1); 

  //----------------------------------------------------------------
  // Construct the SQL Select statement for the intermediate import 
   // file.
  //----------------------------------------------------------------
  string commandString = String.Format("SELECT {0} FROM {1}",
  sqlColumns,
  configParameters[PARAM_SQLTABLENAME].Value);
  try
  {
  if(!configParameters[PARAM_SQLWHERECLAUSE].Value.Equals(""))
  {
  commandString = String.Format("{0} WHERE {1}", commandString, 
     configParameters[PARAM_SQLWHERECLAUSE].Value); 
  }
  }
  // Ignore if the parameter "SQLWhereClause" doesn't exist
   catch {  }
   
  //----------------------------------------------------------------
  // Construct the connection string and connect to the SQL database
  //----------------------------------------------------------------
  string connectionString = ConstructConnectionString(connectTo, 
   user, password, configParameters);

  OleDbConnection myConnection = new OleDbConnection
    (connectionString);
  OleDbCommand myCommand = new OleDbCommand(commandString, 
     myConnection);

  //--------------------------------------------------------------
  // Open the SQL database and create the intermediate file
  // Note that this code only supports String, Integer, GUID, and 
  // DBNULL values
  // Further datatypes must be added by extending the code.
  //---------------------------------------------------------------
  myConnection.Open(); 
  OleDbDataReader result = myCommand.ExecuteReader
     (CommandBehavior.CloseConnection);

  StreamWriter stream = new StreamWriter(filename, false, 
     System.Text.Encoding.Unicode);
  while(result.Read())
  {
  for(int i=0; i<result.FieldCount;i++)
  {
  if(result[i] is string)
  stream.WriteLine(String.Format("{0}: {1}", attributeList[i], 
        result[i]));
  else if (result[i] is System.Int64)
  stream.WriteLine(String.Format("{0}: {1}", attributeList[i],  
        result[i]));
  else if(result[i] is System.Guid)
  stream.WriteLine(String.Format("{0}: {{{1}}}", attributeList[i], 
        System.Convert.ToString(result[i])));
  else if (result[i] is System.DBNull)
  ; // no output --> NULL value
  else
  throw new UnexpectedDataException(String.Format
       ("Unknown type in SQL Column: {0}", attributeList[i]));  }
  stream.WriteLine(); // new record, separate by new line
  }
  stream.Close();

  } //GenerateImportFile


  // ------------------  E X P O R T  -------------------------------
  // Globals for Export routines
  private string ExportConnectionString;
  private string ExportTableName;
  private OleDbConnection ExportConnection;
  private TypeDescriptionCollection ExportTypes;
  // not needed: private bool ExportEscapeAnchor;

  public void BeginExport
  ( 
  string                      connectTo, 
  string                      user, 
  string                      password,
  ConfigParameterCollection   configParameters,
  TypeDescriptionCollection   types
  )
  {
  //----------------------------------------------------------------
  // Construct the connection string and connect to the SQL database
  //----------------------------------------------------------------
  ExportConnectionString = ConstructConnectionString(connectTo, user, 
     password, configParameters);
  ExportConnection = new OleDbConnection(ExportConnectionString);
  ExportConnection.Open(); 

  // Save Type (Schema) information for later to determine 
   // the anchor for a given object type
  ExportTypes = types;

  // Save the Database table name ro run the Insert/Update/Deletes
  ExportTableName = configParameters[PARAM_SQLTABLENAME].Value;

  // Save for later if in the where clause the anchor needs to get 
  // enclosed in ''
   // not needed: ExportEscapeAnchor = configParameters
   // [PARAM_ESCAPEANCHOR].Value.ToLower().Equals("yes") ? 
   // true : false;  
  }

  public void ExportEntry
  ( 
  ModificationType    modificationType, 
  string[]            changedAttributes,
  CSEntry             csentry 
  )
  {
  switch(modificationType)
  {
  case ModificationType.Replace:
  UpdateEntry(changedAttributes, csentry);
  break;

  case ModificationType.Add:
  InsertEntry(changedAttributes, csentry);
  break;

  case ModificationType.Delete:
  DeleteEntry(csentry);
  break;
  }
  } //ExportEntry

  private string EscapeStringForExport(string escape)
  {
  if(escape == null)
  return null;

  return escape.Replace("'", "''");
  } // EscapeStringForExport

  private string GetAnchorAttributeName(CSEntry cs)
  {
  TypeDescription t = ExportTypes[cs.ObjectType]; 
  //-----------------------------------------------------------
  // Note that this MA only supports one Anchor attribute
  //-----------------------------------------------------------
  if(t.AnchorAttributes.Count > 1) 
  throw new TerminateRunException(String.Format("ObjectType {0} 
     has more than one anchor attribute", cs.ObjectType));

  foreach(AttributeDescription attr in t.AnchorAttributes)
  {
  return attr.Name; 
  }
  return null;
  } // GetAnchorAttributeName

  private bool EscapeAnchorAttribute(CSEntry cs)
  {
  TypeDescription t = ExportTypes[cs.ObjectType]; 
  //-----------------------------------------------------------
  // Note that this MA only supports one Anchor attribute
  //-----------------------------------------------------------
  if(t.AnchorAttributes.Count > 1) 
  throw new TerminateRunException(String.Format("ObjectType {0} 
     has more than one anchor attribute", cs.ObjectType));

  foreach(AttributeDescription attr in t.AnchorAttributes)
  {
  switch (attr.DataType)
  {
  case AttributeType.String:
  return true;
  case AttributeType.Integer:
  return false;
  case AttributeType.Binary:
  return true;
  default:
  throw new TerminateRunException(String.Format("Anchor type 
       unsupported. ObjectType: {0}, Attribute: {1}, Type: {2}", 
       cs.ObjectType, attr.Name, attr.DataType.ToString()));
  }
  }
  return true;
  } // EscapeAnchorAttribute

  private void UpdateEntry(string[] changedAttributes, CSEntry cs)
  {
  //----------------------------------------------------------------
  // Build the SQL Update Query
  //----------------------------------------------------------------
  string commandString = String.Format("UPDATE {0} SET", 
     ExportTableName);
  foreach(string attribName in changedAttributes)
  {
  string val = "";
  Attrib attr = cs[attribName]; 
  if(attr.IsPresent)
  {
  switch(attr.DataType)
  {
  case AttributeType.String:
  val = "'" + EscapeStringForExport(attr.StringValue) + "'";
  break;
  case AttributeType.Integer:
  val = System.Convert.ToString(attr.IntegerValue, 10);   
  break;
  default:
  throw new UnexpectedDataException(String.Format("Unknown data 
        type for export update. Attr: {0}, Type: {1}", attribName, 
        attr.DataType.ToString())); 
  }
  }
  else
  {
  val = "NULL";
  }

  commandString = commandString + String.Format(" {0}={1},", 
      attribName, val);
  }
  commandString = commandString.Substring(0, commandString.Length-1); 
   // remove last comma

  string anchor = GetAnchorAttributeName(cs);
  string anchorValue = cs[anchor].Value.ToString();
  if(EscapeAnchorAttribute(cs))
  {
  anchorValue = String.Format("'{0}'", anchorValue); 
  }
  commandString = commandString + String.Format(" WHERE {0}={1}", 
    anchor, anchorValue);
  //----------------------------------------------------------------
  // Build the SQL Update Query
  //----------------------------------------------------------------

  //----------------------------------------------------------------
  // Execute SQL Update Query
  //----------------------------------------------------------------
  OleDbCommand myCommand = new OleDbCommand(commandString, 
     ExportConnection);
  try { myCommand.ExecuteNonQuery(); }
  catch { throw; } // need better exception to report back the 
     command sent to SQL

  } // UpdateEntry

  private void InsertEntry(string[] changedAttributes, CSEntry cs)
  {
  //---------------------------------------------------------------
  // Build the SQL Insert Query
  //---------------------------------------------------------------
  string commandString = String.Format("INSERT INTO {0} 
     (", ExportTableName);
  foreach(string attribName in changedAttributes)
  {
  commandString = commandString + attribName + ",";
  }
  commandString = commandString.Substring(0, commandString.Length-1); 
   // remove last comma
  commandString = commandString + ") VALUES (";
 
  foreach(string attribName in changedAttributes)
  {
  string val = "";
  Attrib attr = cs[attribName]; 
  if(attr.IsPresent)
  {
  switch(attr.DataType)
  {
  case AttributeType.String:
  val = "'" + EscapeStringForExport(attr.StringValue) + "'";
  break;
  case AttributeType.Integer:
  val = System.Convert.ToString(attr.IntegerValue, 10);   
  break;
  case AttributeType.Binary: // assuming GUID value (e.g. Anchor)
  val = "'" + attr.Value.ToString() + "'";  
  break;
  default:
  throw new UnexpectedDataException(String.Format("Unknown data 
        type for export add. Attr: {0} Type: {1}" + attribName, 
        attr.DataType.ToString())); 
  }
  }
  else
  {
  val = "NULL";
  }

  commandString = commandString + val + ",";
  }
  commandString = commandString.Substring(0, commandString.Length-1); 
   // remove last comma
  commandString = commandString + ")";
  //---------------------------------------------------------------
  // Build the SQL Insert Query
  //---------------------------------------------------------------

  //---------------------------------------------------------------
  // Execute the SQL Insert Query
  //---------------------------------------------------------------
  OleDbCommand myCommand = new OleDbCommand(commandString, 
    ExportConnection);
  try { myCommand.ExecuteNonQuery(); }
  catch { throw; } // need better exception to report back the command 
    sent to SQL
  } // insert entry

  private void DeleteEntry(CSEntry cs)
  {
  string anchor = GetAnchorAttributeName(cs);
  string anchorValue = cs[anchor].Value.ToString();
  if(EscapeAnchorAttribute(cs))
  {
  anchorValue = String.Format("'{0}'", anchorValue); 
  }

  // Build the SQL Delete Query
  string commandString = String.Format("DELETE FROM {0} 
     WHERE {1}={2}", ExportTableName, anchor, anchorValue);

  // Execute the SQL Delete Query
  OleDbCommand myCommand = new OleDbCommand(commandString, 
     ExportConnection);
  try { myCommand.ExecuteNonQuery(); }
  catch { throw; } // need better exception to report back the 
     command sent to SQL
  } 
  // DeleteEntry

  public void EndExport()
  {
  ExportConnection.Close();
  }
  }
}

The example assumes that the call-based data source consumes an XML file in the following format:

- <export-ma server="FABRIKAM" export-date="2004-07-12 20:20:56.033">
- <!-- WARNING>
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!
!! The contents of this file should not be edited.
!! Any modifications to this file may result in errors during import.
!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
</WARNING
-->
- <ma-data>
  <format-version>1</format-version> 
  <id>{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}</id> 
  <name>OLEDB Database MA</name> 
  <category>Extensible</category> 
  <subtype /> 
  <ma-listname /> 
  <ma-companyname /> 
  <creation-time>2004-07-12 19:11:08.183</creation-time> 
  <last-modification-time>2004-07-12 20:17:57.336_
  </last-modification-time> 
  <version>4</version> 
  <password-sync-allowed>0</password-sync-allowed> 
- <schema>
  - <dsml:dsml xmlns:dsml="http://www.fabrikam.com/DSML"_
    xmlns:ms-dsml="http://www.fabrikam.com/MMS/DSML">
    - <dsml:directory-schema _
       ms-dsml:no-objectclass-validation="true">
      - <dsml:class id="person" type="structural">
         <dsml:name>person</dsml:name> 
         <dsml:attribute ref="#accountType" required="false" /> 
         <dsml:attribute ref="#company" required="false" /> 
         <dsml:attribute ref="#costCenter" required="false" /> 
         <dsml:attribute ref="#department" required="false" /> 
         <dsml:attribute ref="#displayName" required="false" /> 
         <dsml:attribute ref="#domainName" required="false" /> 
         <dsml:attribute ref="#employeeID" required="true" /> 
         <dsml:attribute ref="#firstname" required="false" /> 
         <dsml:attribute ref="#identityGuid" required="false" /> 
         <dsml:attribute ref="#lastname" required="false" /> 
         <dsml:attribute ref="#logonName" required="false" /> 
         <dsml:attribute ref="#mail" required="false" /> 
         <dsml:attribute ref="#mailNickname" required="false" /> 
         <dsml:attribute ref="#managerEmployeeID" required="false" /> 
         <dsml:attribute ref="#objectType" required="false" /> 
         <dsml:attribute ref="#phoneNumber" required="false" /> 
         <dsml:attribute ref="#samAccountName" required="false" /> 
         <dsml:attribute ref="#title" required="false" /> 
         <dsml:attribute ref="#pager" required="false" /> 
         <dsml:attribute ref="#mobile" required="false" /> 
         <dsml:attribute ref="#export_password" required="false" /> 
       </dsml:class>
    - <dsml:attribute-type id="accountType" single-value="true">
        <dsml:name>accountType</dsml:name> 
        <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
      </dsml:attribute-type>
    - <dsml:attribute-type id="company" single-value="true">
       <dsml:name>company</dsml:name> 
       <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
      </dsml:attribute-type>
    - <dsml:attribute-type id="costCenter" single-value="true">
       <dsml:name>costCenter</dsml:name> 
       <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
      </dsml:attribute-type>
    - <dsml:attribute-type id="department" single-value="true">
       <dsml:name>department</dsml:name> 
       <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
      </dsml:attribute-type>
    - <dsml:attribute-type id="displayName" single-value="true">
       <dsml:name>displayName</dsml:name> 
       <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
      </dsml:attribute-type>
    - <dsml:attribute-type id="domainName" single-value="true">
         <dsml:name>domainName</dsml:name> 
         <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
      </dsml:attribute-type>
    - <dsml:attribute-type id="employeeID" single-value="true"_
      ms-dsml:immutable="true">
         <dsml:name>employeeID</dsml:name> 
         <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
      </dsml:attribute-type>
    - <dsml:attribute-type id="firstname" single-value="true">
         <dsml:name>firstname</dsml:name> 
         <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
      </dsml:attribute-type>
   - <dsml:attribute-type id="identityGuid" single-value="true">
         <dsml:name>identityGuid</dsml:name> 
         <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="lastname" single-value="true">
         <dsml:name>lastname</dsml:name> 
         <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="logonName" single-value="true">
     <dsml:name>logonName</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="mail" single-value="true">
     <dsml:name>mail</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="mailNickname" single-value="true">
     <dsml:name>mailNickname</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="managerEmployeeID" _
     single-value="true">
     <dsml:name>managerEmployeeID</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="objectType" single-value="true">
     <dsml:name>objectType</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="phoneNumber" single-value="true">
     <dsml:name>phoneNumber</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="samAccountName" single-value="true">
     <dsml:name>samAccountName</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="title" single-value="true">
     <dsml:name>title</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="pager" single-value="true">
     <dsml:name>pager</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="mobile" single-value="true">
     <dsml:name>mobile</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
   - <dsml:attribute-type id="export_password" _
     single-value="true" ms-dsml:encrypted="true" _
     ms-dsml:export-only="true">
     <dsml:name>export_password</dsml:name> 
     <dsml:syntax>1.3.6.1.4.1.1466.115.121.1.15</dsml:syntax> 
     </dsml:attribute-type>
    </dsml:directory-schema>
   </dsml:dsml>
  </schema>
- <attribute-inclusion>
   <attribute>accountType</attribute> 
   <attribute>company</attribute> 
   <attribute>costCenter</attribute> 
   <attribute>department</attribute> 
   <attribute>displayName</attribute> 
   <attribute>domainName</attribute> 
   <attribute>employeeID</attribute> 
   <attribute>firstname</attribute> 
   <attribute>identityGuid</attribute> 
   <attribute>lastname</attribute> 
   <attribute>logonName</attribute> 
   <attribute>mail</attribute> 
   <attribute>mailNickname</attribute> 
   <attribute>managerEmployeeID</attribute> 
   <attribute>objectType</attribute> 
   <attribute>phoneNumber</attribute> 
   <attribute>samAccountName</attribute> 
   <attribute>title</attribute> 
   <attribute>pager</attribute> 
   <attribute>mobile</attribute> 
   <attribute>export_password</attribute> 
  </attribute-inclusion>
  <stay-disconnector /> 
- <join>
 - <join-profile cd-object-type="person">
  - <join-criterion id="{45B13AEB-A596-4AFC-B0CD-D9465D835D76}">
   - <search mv-object-type="person">
    - <attribute-mapping mv-attribute="employeeID">
     - <direct-mapping>
        <src-attribute>employeeID</src-attribute> 
       </direct-mapping>
      </attribute-mapping>
     </search>
   - <resolution type="none">
      <script-context /> 
     </resolution>
    </join-criterion>
   </join-profile>
  </join>
- <projection>
 - <class-mapping type="declared" id="_
   {7D985F8D-0FF3-430B-B207-E77F01844AE0}" cd-object-type="person">
    <mv-object-type>person</mv-object-type> 
   </class-mapping>
  </projection>
  <export-attribute-flow /> 
- <provisioning-cleanup type="declared">
   <action>make-normal-disconnector</action> 
  </provisioning-cleanup>
  <extension /> 
- <controller-configuration>
   <application-protection>high</application-protection> 
  </controller-configuration>
  <description /> 
- <ma-ui-settings>
  - <account-joiner-queries>
   - <attributes>
    - <cs>
       <attribute name="employeeID" header="employeeID" size="100" /> 
       <attribute name="accountType" header="accountType" size="100" /> 
       <attribute name="company" header="company" size="100" /> 
      </cs>
     <mv/> 
    </attributes>
    <filters max_mv_search_results="" /> 
   </account-joiner-queries>
  </ma-ui-settings>
- <private-configuration>
 - <MAConfig>
  - <ui-data>
   - <xmlwizard>
    - <properties>
      <sample_file>C:\import.csv</sample_file> 
      <code_page_description>Unicode</code_page_description> 
     </properties>
   - <partitions>
    - <partition cd_name="default" guid="_
      {483FBBF8-E722-4DB4-9D2F-1CC58D9CB3E6}" version="3">
       <object_class>person</object_class> 
      </partition>
     </partitions>
   - <primary_class_mappings>
    - <mapping object_class="person" primary_class="person"_
      user_define="-1">
       <attribute>accountType</attribute> 
       <attribute>company</attribute> 
       <attribute>costCenter</attribute> 
       <attribute>department</attribute> 
       <attribute>displayName</attribute> 
       <attribute>domainName</attribute> 
       <attribute>employeeID</attribute> 
       <attribute>firstname</attribute> 
       <attribute>identityGuid</attribute> 
       <attribute>lastname</attribute> 
       <attribute>logonName</attribute> 
       <attribute>mail</attribute> 
       <attribute>mailNickname</attribute> 
       <attribute>managerEmployeeID</attribute> 
       <attribute>objectType</attribute> 
       <attribute>phoneNumber</attribute> 
       <attribute>samAccountName</attribute> 
       <attribute>title</attribute> 
       <attribute>pager</attribute> 
       <attribute>mobile</attribute> 
      </mapping>
     </primary_class_mappings>
   - <object_classes>
    - <object_class cd_name="person" selected="-1" _
      user_define="-1" configured="-1" anchor="" dn_as_anchor="0">
       <attribute mandatory="0">accountType</attribute> 
       <attribute mandatory="0">company</attribute> 
       <attribute mandatory="0">costCenter</attribute> 
       <attribute mandatory="0">department</attribute> 
       <attribute mandatory="0">displayName</attribute> 
       <attribute mandatory="0">domainName</attribute> 
       <attribute mandatory="-1">employeeID</attribute
       <attribute mandatory="0">firstname</attribute> 
       <attribute mandatory="0">identityGuid</attribute> 
       <attribute mandatory="0">lastname</attribute> 
       <attribute mandatory="0">logonName</attribute> 
       <attribute mandatory="0">mail</attribute> 
       <attribute mandatory="0">mailNickname</attribute> 
       <attribute mandatory="0">managerEmployeeID</attribute> 
       <attribute mandatory="0">objectType</attribute> 
       <attribute mandatory="0">phoneNumber</attribute> 
       <attribute mandatory="0">samAccountName</attribute> 
       <attribute mandatory="0">title</attribute> 
       <attribute mandatory="0">pager</attribute> 
       <attribute mandatory="0">mobile</attribute> 
      </object_class>
     </object_classes>
   - <attributes>
      <attribute cd_name="accountType" binary="0" sample_data="53"_
      multi_valued="0" file_reference="0" selected="-1" _
      type="String" lower_bound="" upper_bound="" user_define="0" /> 
      <attribute cd_name="company" binary="0" _
      sample_data="CONTOSO" multi_valued="0" file_reference="0" _
      selected="-1" type="String" lower_bound="" upper_bound="" _
      user_define="0" /> 
      <attribute cd_name="costCenter" binary="0" sample_data="90622"_
      multi_valued="0" file_reference="0" selected="-1" _
      type="String" lower_bound="" upper_bound="" user_define="0" /> 
      <attribute cd_name="department" binary="0" _
      sample_data="US-SAP Analysis & Support" multi_valued="0" _
      file_reference="0" selected="-1" type="String" lower_bound="_
      " upper_bound="" user_define="0" /> 
      <attribute cd_name="displayName" binary="0" _
      sample_data=" (US-SAP Analysis & Support)"_
      multi_valued="0" file_reference="0" selected="-1" type="String"_
      lower_bound="" upper_bound="" user_define="0" /> 
      <attribute cd_name="domainName" binary="0" _
      sample_data="DomainName" multi_valued="0" file_reference="0" _
      selected="-1" type="String" lower_bound="" upper_bound="" _
      user_define="0" /> 
      <attribute cd_name="employeeID" binary="0" _
      sample_data="216959" multi_valued="0" file_reference="0" _
      selected="-1" type="String" lower_bound="" upper_bound="" _
      user_define="0" /> 
      <attribute cd_name="firstname" binary="0" _
      sample_data="Wright" multi_valued="0" file_reference="0" _
      selected="-1" type="String" lower_bound="" upper_bound="_
      " user_define="0" /> 
      <attribute cd_name="identityGuid" binary="0" _
      sample_data="{371df4cd-ac02-4e82-82cf-00eebcf31d38}" _
      multi_valued="0" file_reference="0" selected="-1" _
      type="String" lower_bound="" upper_bound="" user_define="0" /> 
      <attribute cd_name="lastname" binary="0" _
      sample_data="Steven 123" multi_valued="0" file_reference="0"_
      selected="-1" type="String" lower_bound="" upper_bound="_
      " user_define="0" /> 
      <attribute cd_name="logonName" binary="0" _
      sample_data="DomainName\t-steven" multi_valued="0" _
      file_reference="0" selected="-1" type="String" _
      lower_bound="" upper_bound="" user_define="0" /> 
      <attribute cd_name="mail" binary="0" _
      sample_data="t-steven@contoso.com" multi_valued="0" _
      file_reference="0" selected="-1" type="String" lower_bound="_
      " upper_bound="" user_define="0" /> 
      <attribute cd_name="mailNickname" binary="0" _
      sample_data="t-steven" multi_valued="0" file_reference="0"_
      selected="-1" type="String" lower_bound="" upper_bound="_
      " user_define="0" /> 
      <attribute cd_name="managerEmployeeID" binary="0" _
      sample_data="114635" multi_valued="0" file_reference="0" _
      selected="-1" type="String" lower_bound="" upper_bound="_
      " user_define="0" /> 
      <attribute cd_name="objectType" binary="0" _
      sample_data="MSPerson" multi_valued="0" file_reference="0" _
      selected="-1" type="String" lower_bound="" upper_bound="_
      " user_define="0" /> 
      <attribute cd_name="phoneNumber" binary="0" _
      sample_data="+1 (555) 5550123 X50123" multi_valued="0" _
      file_reference="0" selected="-1" type="String" _
      lower_bound="" upper_bound="" user_define="0" /> 
      <attribute cd_name="samAccountName" binary="0" _
      sample_data="t-steven" multi_valued="0" file_reference="0"_
      selected="-1" type="String" lower_bound="" upper_bound="_
      " user_define="0" /> 
      <attribute cd_name="title" binary="0" _
      sample_data="WINTER PROGRAM MANAGER INTERN" multi_valued="0"_
      file_reference="0" selected="-1" type="String" lower_bound="_
      " upper_bound="" user_define="0" /> 
      <attribute cd_name="pager" binary="0" _
      sample_data="555-555-0196" multi_valued="0" file_reference="0"_
      selected="-1" type="String" lower_bound="" upper_bound="_
      " user_define="0" /> 
      <attribute cd_name="mobile" binary="0" _
      sample_data="555-555-0145" multi_valued="0" _
      file_reference="0" selected="-1" type="String" _
      lower_bound="" upper_bound="" user_define="0" /> 
     </attributes>
    </xmlwizard>
   </ui-data>
- <importing>
 - <dn>
    <attribute>employeeID</attribute> 
   </dn>
- <anchor>
   <attribute>employeeID</attribute> 
  </anchor>
  <per-class-settings /> 
  <default_object_class>person</default_object_class> 
 </importing>
 <exporting /> 
 <ldap-dn>0</ldap-dn> 
- <attribute_value_pair_format>
   <code_page>1200</code_page> 
  </attribute_value_pair_format>
- <primary_class_mappings>
 - <mapping>
    <primary_class>person</primary_class> 
    <oc-value>person</oc-value> 
   </mapping>
  </primary_class_mappings>
- <password-extension-config>
   <password-extension-enabled>0</password-extension-enabled> 
   <dll /> 
  <password-set-enabled /> 
  <password-change-enabled /> 
- <connection-info>
   <connect-to /> 
   <user /> 
  </connection-info>
  <timeout /> 
  </password-extension-config>
- <extension-config>
   <filename>OLEDB Database MAExtension.dll</filename> 
   <export-mode>call-based</export-mode> 
   <import-enabled>1</import-enabled> 
   <export-enabled>1</export-enabled> 
- <connection-info>
   <connect-to>localhost</connect-to> 
   <user>sa</user> 
  </connection-info>
- <attributes>
   <attribute name="Database">MIISSA</attribute> 
   <attribute name="Table">IdentityStore</attribute> 
   <attribute name="SQLWhereClause">CostCenter in ('90622')_
   </attribute> 
   <attribute name="Provider">SQLOLEDB</attribute> 
   <attribute name="Security">SSPI</attribute> 
   <attribute name="Timeout">30</attribute> 
  </attributes>
  </extension-config>
  <file-type>AVP</file-type> 
 </MAConfig>
 </private-configuration>
- <ma-partition-data>
- <partition>
   <id>{483FBBF8-E722-4DB4-9D2F-1CC58D9CB3E6}</id> 
   <name>default</name> 
   <creation-time>2004-07-12 19:11:08.183</creation-time> 
   <last-modification-time>2004-07-12 20:17:57.327_
   </last-modification-time> 
   <version>4</version> 
   <selected>1</selected> 
 - <filter>
  - <object-classes>
     <object-class>person</object-class> 
    </object-classes>
 - <containers>
    <exclusions /> 
  - <inclusions>
     <inclusion /> 
    </inclusions>
   </containers>
  </filter>
  <allowed-operations>31</allowed-operations> 
- <current>
   <batch-number>1</batch-number> 
   <sequence-number>0</sequence-number> 
  </current>
  <last-successful-batch>0</last-successful-batch> 
- <filter-hints> 
 - <object-classes>
  - <object-class>
     <name>person</name> 
   - <hierarchy>
      <object-class>person</object-class> 
     </hierarchy>
     <included>1</included> 
    </object-class>
   </object-classes>
  </filter-hints>
 </partition>
</ma-partition-data>
- <ma-run-data>
- <run-configuration>
   <id>{1D98F06C-094E-4236-9F0F-A5981BCE687D}</id> 
   <name>Export</name> 
   <creation-time>2004-07-12 20:14:01.940</creation-time> 
   <version>1</version> 
   <last-modification-time>2004-07-12 20:14:01.940_
   </last-modification-time> 
- <configuration>
- <step>
   <step-type type="export" /> 
   <threshold /> 
   <partition>{483FBBF8-E722-4DB4-9D2F-1CC58D9CB3E6}</partition> 
- <custom-data>
 - <run-config>
    <input-file /> 
    <timeout>0</timeout> 
   </run-config>
  </custom-data>
 </step>
</configuration>
</run-configuration>
- <run-configuration>
   <id>{74374014-3FDB-44EC-A194-00FF139AB44F}</id> 
   <name>Export+FullImport+DeltaSync</name> 
   <creation-time>2004-07-12 20:14:01.940</creation-time> 
   <version>1</version> 
   <last-modification-time>2004-07-12 20:14:01.940_
   </last-modification-time> 
 - <configuration>
  - <step>
    <step-type type="export" /> 
    <threshold /> 
    <partition>{483FBBF8-E722-4DB4-9D2F-1CC58D9CB3E6}</partition> 
  - <custom-data>
   - <run-config>
      <input-file /> 
      <timeout>0</timeout> 
     </run-config>
    </custom-data>
   </step>
 - <step>
    <step-type type="full-import" /> 
    <threshold /> 
    <partition>{483FBBF8-E722-4DB4-9D2F-1CC58D9CB3E6}</partition> 
  - <custom-data>
   - <run-config>
      <input-file>import.avp.txt</input-file> 
      <delete-file-after-use>0</delete-file-after-use> 
      <timeout>0</timeout> 
     </run-config>
    </custom-data>
   </step>
  </configuration>
 </run-configuration>
- <run-configuration>
   <id>{18B8482E-BE7A-456B-B084-23DB27D14027}</id> 
   <name>FullImport+DeltaSync</name> 
   <creation-time>2004-07-12 20:14:01.930</creation-time> 
   <version>2</version> 
   <last-modification-time>2004-07-12 20:14:32.903_
   </last-modification-time> 
 - <configuration>
  - <step>
     <step-type type="full-import" /> 
     <threshold /> 
     <partition>{483FBBF8-E722-4DB4-9D2F-1CC58D9CB3E6}</partition> 
   - <custom-data>
    - <run-config>
       <input-file>import.avp.txt</input-file> 
       <delete-file-after-use>0</delete-file-after-use> 
       <timeout>0</timeout> 
      </run-config>
     </custom-data>
    </step>
   </configuration>
  </run-configuration>
 </ma-run-data>
 <capabilities-mask>7b801</capabilities-mask> 
 <export-type>3</export-type> 
- <dn-construction>
   <attribute>employeeID</attribute> 
  </dn-construction>
- <password-sync>
   <maximum-retry-count>10</maximum-retry-count> 
   <retry-interval>60</retry-interval> 
   <allow-low-security>0</allow-low-security> 
  </password-sync>
  </ma-data>
- <mv-data>
 - <import-attribute-flow>
  - <import-flow-set mv-object-type="person">
   - <import-flows mv-attribute="displayName" type="ranked">
    - <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}_
    " cd-object-type="person" id="_
    {B1F95D79-E7EE-4983-A52C-EFE4DD2EA2B6}">
     - <direct-mapping>
        <src-attribute>displayName</src-attribute> 
       </direct-mapping>
      </import-flow>
    - <import-flow src-ma="{54686980-A9D6-463D-859F-32AFAC045B1A}_
      " cd-object-type="person" id="_
      {792C99AA-0ED3-4F48-9932-91327D92ADED}">
     - <direct-mapping>
        <src-attribute>displayName</src-attribute> 
       </direct-mapping>
      </import-flow>
     </import-flows>
   - <import-flows mv-attribute="givenName" type="ranked">
    - <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}_
      " cd-object-type="person" id="_
      {F20E677D-B5E7-4EC4-A30E-E8E56CF01DD1}">
     - <direct-mapping>
        <src-attribute>firstname</src-attribute> 
       </direct-mapping>
      </import-flow>
   - <import-flow src-ma="{54686980-A9D6-463D-859F-32AFAC045B1A}" _
   cd-object-type="person" id="_
   {8E7C124A-D0E6-4B18-A9A3-EE20DE019250}">
    - <direct-mapping>
       <src-attribute>first</src-attribute> 
      </direct-mapping>
     </import-flow>
    </import-flows>
 - <import-flows mv-attribute="sn" type="ranked">
  - <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" _
    cd-object-type="person" id="_
    {662F7FFC-AC3B-4D2F-BBC2-7098B6E07DDD}">
   - <direct-mapping>
      <src-attribute>lastname</src-attribute> 
     </direct-mapping>
    </import-flow>
   </import-flows>
 - <import-flows mv-attribute="company" type="ranked">
  - <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" _
    cd-object-type="person" id="_
    {EAF1F4B2-AD8F-4A1C-8526-74B8655F0F8E}">
   - <direct-mapping>
      <src-attribute>company</src-attribute> 
     </direct-mapping>
    </import-flow>
 - <import-flow src-ma="{54686980-A9D6-463D-859F-32AFAC045B1A}" _
    cd-object-type="person" id="_
    {5990AB3C-0FED-4EA0-809C-944A71DBBFB5}">
 - <direct-mapping>
    <src-attribute>company</src-attribute> 
   </direct-mapping>
  </import-flow>
 </import-flows>
- <import-flows mv-attribute="mailNickname" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" _
  cd-object-type="person" id="_
  {F31E1BF1-2815-4097-90F9-43027A2BD47F}">
- <direct-mapping>
  <src-attribute>samAccountName</src-attribute> 
  </direct-mapping>
  </import-flow>
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" _
  cd-object-type="person" id="_
  {C4908202-6AE6-44FB-B91E-8627F2846A0B}">
- <direct-mapping>
  <src-attribute>mailNickname</src-attribute> 
  </direct-mapping>
  </import-flow>
- <import-flow src-ma="{54686980-A9D6-463D-859F-32AFAC045B1A}" _
  cd-object-type="person" id="_
  {350D4BA7-AFC2-4610-BC76-FAD46C1AFE72}">
- <direct-mapping>
  <src-attribute>samAccountName</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="department" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" _
  cd-object-type="person" id="_
  {AE8AED48-ABA5-4D13-BCF6-7F087341448B}">
- <direct-mapping>
  <src-attribute>department</src-attribute> 
  </direct-mapping>
  </import-flow>
- <import-flow src-ma="{54686980-A9D6-463D-859F-32AFAC045B1A}" _
  cd-object-type="person" id="_
  {5C7CE82C-9402-4CF3-A05E-CFCD1B0A9F00}">
- <direct-mapping>
  <src-attribute>department</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="employeeType" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" _
  cd-object-type="person" id="_
  {C763C66B-3E19-491E-AD41-B8FAF6F1ED69}">
- <direct-mapping>
  <src-attribute>accountType</src-attribute> 
  </direct-mapping>
  </import-flow>
- <import-flow src-ma="{54686980-A9D6-463D-859F-32AFAC045B1A}" _
  cd-object-type="person" id="_
  {AD0E35CC-C0F2-4DFF-9483-F324342E6EAD}">
- <scripted-mapping>
  <src-attribute>accountType</src-attribute> 
  <script-context>cd.person:accountType->mv.person:_
  employeeType</script-context> 
  </scripted-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="division" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" _
  cd-object-type="person" id="_
  {B7EEDD5F-FB0F-4BD0-B55C-BF2E6F6018B6}">
- <direct-mapping>
  <src-attribute>costCenter</src-attribute> 
  </direct-mapping>
  </import-flow>
- <import-flow src-ma="{54686980-A9D6-463D-859F-32AFAC045B1A}" _
  cd-object-type="person" id="{5A324740-68F4-46D6-8C22-09F9C3D34D77}">
- <direct-mapping>
  <src-attribute>costCenter</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="employeeID" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" cd-object-type="person" id="{6BF349C1-A81E-4672-89A0-E585027DDE59}">
- <direct-mapping>
  <src-attribute>employeeID</src-attribute> 
  </direct-mapping>
  </import-flow>
- <import-flow src-ma="{54686980-A9D6-463D-859F-32AFAC045B1A}" cd-object-type="person" id="{DB2559CA-52C6-4448-BE31-4FFF84F9B27A}">
- <direct-mapping>
  <src-attribute>employeeID</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="mail" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}"_
  cd-object-type="person" id="_
  {38642D45-5F34-49F7-B94D-1CA56DBB4146}">
- <direct-mapping>
  <src-attribute>mail</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="mobile" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}"_
   cd-object-type="person" id="_
  {43EFC2E5-823D-4A21-BE50-B2C22C211334}">
- <direct-mapping>
  <src-attribute>mobile</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="pager" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}"_
   cd-object-type="person" id="_
   {84C099ED-0414-48EB-92E1-E62C9D545429}">
- <direct-mapping>
  <src-attribute>pager</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="telephoneNumber" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}" _
  cd-object-type="person" id="{11C5EA30-A173-4A5B-814E-BF4266AC1F90}">
- <direct-mapping>
  <src-attribute>phoneNumber</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
- <import-flows mv-attribute="title" type="ranked">
- <import-flow src-ma="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}"_
   cd-object-type="person" id="_
   {DAB2FB28-E7C6-477E-B083-9F4DC989A390}">
- <direct-mapping>
  <src-attribute>title</src-attribute> 
  </direct-mapping>
  </import-flow>
  </import-flows>
  </import-flow-set>
- <per-ma-options>
- <ma-options ma-id="{54686980-A9D6-463D-859F-32AFAC045B1A}">
  <enable-recall>true</enable-recall> 
  </ma-options>
- <ma-options ma-id="{1F41DB0A-8E02-4BF8-B77A-81AF5C6FB2F6}">
  <enable-recall>true</enable-recall> 
  </ma-options>
- <ma-options ma-id="{9DCAE092-8BF0-4483-A943-BBF1BD0C2CE7}">
  <enable-recall>true</enable-recall> 
  </ma-options>
  </per-ma-options>
  </import-attribute-flow>
  </mv-data>
  </export-ma>

The example then generates a comma-delimited file whose contents are imported into the metaverse and then exported to a call-based data source.

Send comments about this topic to Microsoft

Build date: 2/16/2009