Esempio n. 1
0
        /// <summary>
        /// Initializes the Catalog
        /// </summary>
        private void InitializeMetadataStore()
        {
            // Open the shared metadatacatalog cache on the client to
            // read LOB information. This class represnts the Office
            // client shared storage for BCS metadata. Once on client,
            // this metadata can be accessed from any Office application
            catalog = new RemoteSharedFileBackedMetadataCatalog();

            // Get the SalesOrderHeader entity instance using
            // namespace and name
            entitySalesOrderHeader = catalog.GetEntity(
                SalesOrderHeaderNamespace,
                SalesOrderHeader);

            // Get the SalesOrderLine entity instance using
            // namespace and name
            entitySalesOrderLine = catalog.GetEntity(
                SalesOrderHeaderNamespace,
                SalesOrderLine);

            salesOrderLineEntityIds =
                entitySalesOrderLine.GetIdentifiers();

            // Get the handle to LobSystem
            lobInstance =
                catalog.GetLobSystem(SalesOrderLobSystemName).
                GetLobSystemInstances()[SalesOrderLobSystemInstanceName];

            // Create list to hold changed rows
            changedSalesLineRows = new List <DataRow>();
        }
Esempio n. 2
0
        /// <summary>
        /// Get the instance of a Business Data Connectivity entity
        /// </summary>
        /// <param name="site"></param>
        /// <param name="nameSpace"></param>
        /// <param name="entityName"></param>
        /// <param name="entityId"></param>
        /// <returns></returns>
        private static IEntityInstance GetEntityInstance(SPSite site, string nameSpace, string entityName, string entityId)
        {
            //Use the scope of the currently opened site
            SPServiceContext      ctx   = SPServiceContext.GetContext(site);
            SPServiceContextScope scope = new SPServiceContextScope(ctx);

            //Get the BDC service of the local SP farm
            BdcService         service           = SPFarm.Local.Services.GetValue <BdcService>();
            IMetadataCatalog   catalog           = service.GetDatabaseBackedMetadataCatalog(ctx);
            IEntity            entity            = catalog.GetEntity(nameSpace, entityName);
            ILobSystemInstance LobSysteminstance = entity.GetLobSystem().GetLobSystemInstances()[0].Value;
            IEntityInstance    entInstance       = null;

            //Loop through the methods defined in the LOB
            foreach (KeyValuePair <string, IMethod> method in entity.GetMethods())
            {
                IMethodInstance methodInstance = method.Value.GetMethodInstances()[method.Key];
                //Get the Specific Finder method of the LOB
                if (methodInstance.MethodInstanceType == MethodInstanceType.SpecificFinder)
                {
                    //Find the record with the ID from the datasource
                    Microsoft.BusinessData.Runtime.Identity id = new Microsoft.BusinessData.Runtime.Identity(entityId);
                    entInstance = entity.FindSpecific(id, entity.GetLobSystem().GetLobSystemInstances()[0].Value);
                }
            }

            return(entInstance);
        }
Esempio n. 3
0
 public PartManagementRepository()
 {
     bdcService = SPFarm.Local.Services.GetValue <BdcService>();
     catalog    = bdcService.GetDatabaseBackedMetadataCatalog(SPServiceContext.Current);
     partsManagementLobSystemInstance = catalog.GetLobSystem(Constants.LobSystemName).GetLobSystemInstances()[Constants.LobSystemName];
     contactsLobSystemInstance        = catalog.GetLobSystem(Constants.ContactsLobSystemName).GetLobSystemInstances()[Constants.ContactsLobSystemName];
 }
Esempio n. 4
0
        /// <summary>
        /// Gets a LOB system instance from a INamedLobSystemInstanceDictionary object using a key and a specific string comparer to examine the keys.
        /// </summary>
        /// <param name="lobInstances">A INamedLobSystemInstanceDictionary object to be searched.</param>
        /// <param name="key">The key to search for.</param>
        /// <param name="comparisonType">The string comparer to use to compare the keys.</param>
        /// <returns>A ILobSystemInstance object that matches the key; otherwise, null.</returns>
        public static ILobSystemInstance GetByKey(this INamedLobSystemInstanceDictionary lobInstances, string key, StringComparison comparisonType)
        {
            ILobSystemInstance lobInstance = null;

            foreach (string lobInstanceKey in lobInstances.Keys)
            {
                if (lobInstanceKey.Equals(key, comparisonType))
                {
                    lobInstance = lobInstances[lobInstanceKey];
                    break;
                }
            }
            return(lobInstance);
        }
Esempio n. 5
0
        static void ExecuteBcsEctMethods(string siteUrl)
        {
            using (SPSite site = new SPSite(siteUrl))
            {
                using (new SPServiceContextScope(SPServiceContext.GetContext(site)))
                {
                    BdcServiceApplicationProxy    proxy  = (BdcServiceApplicationProxy)SPServiceContext.Current.GetDefaultProxy(typeof(BdcServiceApplicationProxy));
                    DatabaseBackedMetadataCatalog model  = proxy.GetDatabaseBackedMetadataCatalog();
                    IEntity            entity            = model.GetEntity("EmployeeEntityModel.BdcModel1", "Entity1");     // Namespace, Entity name
                    ILobSystemInstance lobSystemInstance = entity.GetLobSystem().GetLobSystemInstances()[0].Value;
                    IMethodInstance    method            = entity.GetMethodInstance("ReadList", MethodInstanceType.Finder); // Finder method name
                    IView view = entity.GetFinderView(method.Name);

                    IFilterCollection         filterCollection         = entity.GetDefaultFinderFilters();
                    IEntityInstanceEnumerator entityInstanceEnumerator = entity.FindFiltered(filterCollection, method.Name, lobSystemInstance, OperationMode.Online);
                    Console.WriteLine("Employee Login ID | Job Title");
                    while (entityInstanceEnumerator.MoveNext())
                    {
                        Console.WriteLine(entityInstanceEnumerator.Current["LoginID"].ToString() + " - " + entityInstanceEnumerator.Current["JobTitle"].ToString()); // Column names
                    }
                    Console.ReadLine();
                }
            }
        }
Esempio n. 6
0
        private static IEntityInstance GetEntityInstance(SPBusinessDataField dataField, string entityId, SPSite site, SPListItem item, string finderMethodName)
        {
            IEntityInstance entInstance = null;

            try
            {
                IEntity            entity            = GetEntity(site, dataField);
                ILobSystemInstance lobSystemInstance = entity.GetLobSystem().GetLobSystemInstances()[0].Value;

                // Get methods collection
                foreach (KeyValuePair <string, IMethod> method in entity.GetMethods())
                {
                    // Get current method's instance
                    IMethodInstance methodInstance = method.Value.GetMethodInstances()[method.Key];
                    // Execute specific finder method
                    if (methodInstance.MethodInstanceType == MethodInstanceType.SpecificFinder && methodInstance.Name == finderMethodName)
                    {
                        Identity id = null;

                        if (EntityInstanceIdEncoder.IsEncodedIdentifier(entityId))
                        {
                            object[] oIDList = EntityInstanceIdEncoder.DecodeEntityInstanceId(entityId);
                            id = new Identity(oIDList[0]);

                            // Execute specific finder method and get the entity instance
                            entInstance = entity.FindSpecific(id, methodInstance.Name, entity.GetLobSystem().GetLobSystemInstances()[0].Value);
                            item[dataField.RelatedField] = entityId.ToString();
                        }
                        else
                        {
                            object oID = GetTypedIDValue(entityId, entity);
                            id = new Identity(oID);
                            string encodedIdentifier = EntityInstanceIdEncoder.EncodeEntityInstanceId(new object[] { oID });
                            // Execute specific finder method and get the entity instance
                            entInstance = entity.FindSpecific(id, methodInstance.Name, entity.GetLobSystem().GetLobSystemInstances()[0].Value);
                            item[dataField.RelatedField] = encodedIdentifier;
                        }
                    }
                }
            }
            catch (ObjectNotFoundException notFoundException)
            {
                LogError("GetEntityInstance errored with message " + notFoundException.Message + ". Adding item to Guidewire.");
                Console.WriteLine("GetEntityInstance errored with message " + notFoundException.Message + ". Adding item to Guidewire.");
                bool   addDocumentToGuidewire = CallGuidewire(item, GuidewireOperationType.New);
                string outMessage             = "";
                if (addDocumentToGuidewire)
                {
                    outMessage = string.Format("Item with ID {0} added to Guidewire", item.ID);
                }
                else
                {
                    outMessage = string.Format("Item with ID {0} could not be added to Guidewire", item.ID);
                    if (Settings.Default.DeleteFailures)
                    {
                        try
                        {
                            // Recycle the item if it can't be added to guidewire and it's older than 30 days
                            if (DateTime.Now.AddDays(-30) > (DateTime)item[SPBuiltInFieldId.Modified])
                            {
                                item.Recycle();
                            }
                        }
                        catch
                        {
                            // Swallow this error. The item doesn't exist in Guidewire and can't be deleted in SharePoint. It has problems
                        }
                    }
                    LogError(outMessage);
                }
                Console.WriteLine(outMessage);
            }
            catch (Exception ex)
            {
                // Swallow this error
                LogError("GetEntityInstance errored with message " + ex.Message);
                Console.WriteLine("GetEntityInstance errored with message " + ex.Message);
            }
            return(entInstance);
        }
Esempio n. 7
0
        protected void CreateNewCustomer_Click(object sender,
                                               EventArgs e)
        {
            // Make sure we have values for the entity namespace and name.
            if (!EntityValuesAreSet)
            {
                DisplaySetPropertyValuePrompt(true);
                return;
            }
            else
            {
                DisplaySetPropertyValuePrompt(false);
            }

            try
            {
                using (new Microsoft.SharePoint.SPServiceContextScope(
                           SPServiceContext.GetContext(SPContext.Current.Site)))
                {
                    // Get the BDC service and metadata catalog.
                    BdcService service =
                        SPFarm.Local.Services.GetValue <BdcService>(String.Empty);
                    IMetadataCatalog catalog =
                        service.GetDatabaseBackedMetadataCatalog(
                            SPServiceContext.Current);

                    // Get the entity using the specified name and namespace.
                    IEntity entity =
                        catalog.GetEntity(EntityNamespace, EntityName);
                    ILobSystemInstance LobSysteminstance =
                        entity.GetLobSystem().GetLobSystemInstances()[0].Value;

                    // Get the fields on the entity.
                    IView createView =
                        entity.GetCreatorView("CreateCustomer");
                    IFieldValueDictionary valueDictionary =
                        createView.GetDefaultValues();

                    // Set the values of the entity fields.
                    valueDictionary["EmailAddress"] = Email.Text;
                    valueDictionary["FirstName"]    = FirstName.Text;
                    valueDictionary["LastName"]     = LastName.Text;
                    valueDictionary["MiddleName"]   = MiddleName.Text;
                    valueDictionary["Phone"]        = Phone.Text;
                    valueDictionary["Title"]        = Title.Text;

                    // Call the creator method and display the returned
                    // Customer ID.
                    Identity id = entity.Create(valueDictionary,
                                                LobSysteminstance);

                    CustomerID.Text =
                        id.GetIdentifierValues().GetValue(0).ToString();

                    StatusLabel.ForeColor = Color.Green;
                    StatusLabel.Text      = "Customer successfully created.";
                }
            }
            catch (Exception ex)
            {
                StatusLabel.ForeColor = Color.Red;
                StatusLabel.Text      = "Unable to create customer." +
                                        ex.Message;
            }
        }
Esempio n. 8
0
        protected void UpdateCustomer_Click(object sender, EventArgs e)
        {
            // Make sure we have values for the entity namespace and name.
            if (!EntityValuesAreSet)
            {
                DisplaySetPropertyValuePrompt(true);
                return;
            }
            else
            {
                DisplaySetPropertyValuePrompt(false);
            }

            // Do simple validation of the customer ID. Make sure it is
            // an integer.
            int customerID = -1;

            if (!ValidateCustomerID(CustomerID.Text, ref customerID))
            {
                StatusLabel.ForeColor = Color.Red;
                StatusLabel.Text      =
                    "Please enter an integer for the Customer ID value.";
                return;
            }

            try
            {
                using (new Microsoft.SharePoint.SPServiceContextScope(
                           SPServiceContext.GetContext(SPContext.Current.Site)))
                {
                    // Get the BDC service and metadata catalog.
                    BdcService service =
                        SPFarm.Local.Services.GetValue <BdcService>(String.Empty);
                    IMetadataCatalog catalog =
                        service.GetDatabaseBackedMetadataCatalog(
                            SPServiceContext.Current);

                    // Get the entity using the specified name and namespace.
                    IEntity entity =
                        catalog.GetEntity(EntityNamespace, EntityName);
                    ILobSystemInstance LobSysteminstance =
                        entity.GetLobSystem().GetLobSystemInstances()[0].Value;

                    // Create an Identity based on the specified Customer ID.
                    Identity identity = new Identity(customerID);

                    // Get a method instance for the Updater method.
                    IMethodInstance method =
                        entity.GetMethodInstance("UpdateCustomer",
                                                 MethodInstanceType.Updater);

                    // The UpdateCustomer method of the external content type
                    // maps to the UpdateCustomer method in the AdventureWorks
                    // web service. Looking at the source for the web service
                    // shows that the UpdateCustomer method has the following
                    // signature:
                    //
                    // public void UpdateCustomer(SalesCustomer customer)
                    //
                    // The SalesCustomer type has the following layout:
                    //
                    // public class SalesCustomer
                    // {
                    //     public int CustomerId { get; set; }
                    //     public String Title { get; set; }
                    //     public String FirstName { get; set; }
                    //     public String MiddleName { get; set; }
                    //     public String LastName   { get; set; }
                    //     public String EmailAddress { get; set; }
                    //     public String Phone { get; set; }
                    //     public DateTime ModifiedDate { get; set; }
                    // }

                    // Get the collection of parameters for the method.
                    // In this case there is only one.
                    IParameterCollection parameters =
                        method.GetMethod().GetParameters();

                    // Use type reflection to get an instance of a
                    // SalesCustomer object to pass as a parameter.
                    ITypeReflector  reflector          = parameters[0].TypeReflector;
                    ITypeDescriptor rootTypeDescriptor =
                        parameters[0].GetRootTypeDescriptor();

                    object[] methodParamInstances =
                        method.GetMethod().CreateDefaultParameterInstances(
                            method);
                    Object instance = methodParamInstances[0];

                    // Get type descriptors for each of the SalesCustomer
                    // members.
                    ITypeDescriptor customerIDTypeDescriptor =
                        rootTypeDescriptor.GetChildTypeDescriptors()[0];
                    ITypeDescriptor titleTypeDescriptor =
                        rootTypeDescriptor.GetChildTypeDescriptors()[1];
                    ITypeDescriptor firstNameTypeDescriptor =
                        rootTypeDescriptor.GetChildTypeDescriptors()[2];
                    ITypeDescriptor middleNameTypeDescriptor =
                        rootTypeDescriptor.GetChildTypeDescriptors()[3];
                    ITypeDescriptor lastNameTypeDescriptor =
                        rootTypeDescriptor.GetChildTypeDescriptors()[4];
                    ITypeDescriptor emailAddressTypeDescriptor =
                        rootTypeDescriptor.GetChildTypeDescriptors()[5];
                    ITypeDescriptor phoneTypeDescriptor =
                        rootTypeDescriptor.GetChildTypeDescriptors()[6];
                    ITypeDescriptor modifiedDateTypeDescriptor =
                        rootTypeDescriptor.GetChildTypeDescriptors()[7];

                    // Set the values of the SalesCustomer object members
                    // with the values specified by the user.
                    reflector.Set(customerIDTypeDescriptor,
                                  rootTypeDescriptor,
                                  ref instance, customerID);
                    reflector.Set(titleTypeDescriptor, rootTypeDescriptor,
                                  ref instance, Title.Text);
                    reflector.Set(firstNameTypeDescriptor, rootTypeDescriptor,
                                  ref instance, FirstName.Text);
                    reflector.Set(middleNameTypeDescriptor,
                                  rootTypeDescriptor,
                                  ref instance, MiddleName.Text);
                    reflector.Set(lastNameTypeDescriptor, rootTypeDescriptor,
                                  ref instance, LastName.Text);
                    reflector.Set(emailAddressTypeDescriptor,
                                  rootTypeDescriptor,
                                  ref instance, Email.Text);
                    reflector.Set(phoneTypeDescriptor, rootTypeDescriptor,
                                  ref instance, Phone.Text);
                    reflector.Set(modifiedDateTypeDescriptor,
                                  rootTypeDescriptor,
                                  ref instance, DateTime.Now);

                    // Execute the updater method, passing the parameter.
                    entity.Execute(method, LobSysteminstance,
                                   ref methodParamInstances);

                    StatusLabel.ForeColor = Color.Green;
                    StatusLabel.Text      = "Customer successfully updated.";
                }
            }
            catch (Exception ex)
            {
                StatusLabel.ForeColor = Color.Red;
                StatusLabel.Text      = "Unable to find customer with ID = " +
                                        CustomerID.Text + ". " + ex.Message;
            }
        }
Esempio n. 9
0
        protected void FindCustomerByID_Click(
            object sender, EventArgs e)
        {
            // Make sure we have values for the entity namespace and name.
            if (!EntityValuesAreSet)
            {
                DisplaySetPropertyValuePrompt(true);
                return;
            }
            else
            {
                DisplaySetPropertyValuePrompt(false);
            }

            // Do simple validation of the customer ID. Make sure it is
            // an integer.
            int customerID = -1;

            if (!ValidateCustomerID(CustomerID.Text, ref customerID))
            {
                ClearFields(false);
                StatusLabel.ForeColor = Color.Red;
                StatusLabel.Text      =
                    "Please enter an integer for the Customer ID value.";
                return;
            }

            try
            {
                using (new Microsoft.SharePoint.SPServiceContextScope(
                           SPServiceContext.GetContext(SPContext.Current.Site)))
                {
                    // Get the BDC service and metadata catalog.
                    BdcService service =
                        SPFarm.Local.Services.GetValue <BdcService>(String.Empty);
                    IMetadataCatalog catalog =
                        service.GetDatabaseBackedMetadataCatalog(
                            SPServiceContext.Current);

                    // Get the entity using the specified name and namespace.
                    IEntity entity =
                        catalog.GetEntity(EntityNamespace, EntityName);
                    ILobSystemInstance LobSysteminstance =
                        entity.GetLobSystem().GetLobSystemInstances()[0].Value;

                    // Create an Identity based on the specified Customer ID.
                    Identity identity = new Identity(customerID);

                    // Get a method instance for the SpecificFinder method.
                    IMethodInstance method =
                        entity.GetMethodInstance("GetCustomerById",
                                                 MethodInstanceType.SpecificFinder);

                    // Execute the Specific Finder method to return the
                    // customer data.
                    IEntityInstance iei =
                        entity.FindSpecific(identity, LobSysteminstance);

                    // Display the data for the returned customer in the UI.
                    Title.Text = iei["Title"] != null ?
                                 iei["Title"].ToString() : string.Empty;
                    FirstName.Text = iei["FirstName"] != null ?
                                     iei["FirstName"].ToString() : string.Empty;
                    MiddleName.Text = iei["MiddleName"] != null ?
                                      iei["MiddleName"].ToString() : string.Empty;
                    LastName.Text = iei["LastName"] != null ?
                                    iei["LastName"].ToString() : string.Empty;
                    Email.Text = iei["EmailAddress"] != null ?
                                 iei["EmailAddress"].ToString() : string.Empty;
                    Phone.Text = iei["Phone"] != null ?
                                 iei["Phone"].ToString() : string.Empty;
                }
            }
            catch (Exception ex)
            {
                ClearFields(false);

                StatusLabel.ForeColor = Color.Red;
                StatusLabel.Text      = "Unable to find customer with ID = " +
                                        CustomerID.Text + ". " + ex.Message;
            }
        }
Esempio n. 10
0
        public void ExecuteStatic(IMethodInstance methodInstance, ILobSystemInstance lobSystemInstance, object[] methodSignatureArgs, IExecutionContext context)
        {
            if (methodInstance == null)
            {
                throw (new ArgumentNullException("methodInstance"));
            }
            if (lobSystemInstance == null)
            {
                throw (new ArgumentNullException("lobSystemInstance"));
            }
            if (methodSignatureArgs == null)
            {
                throw (new ArgumentNullException("args"));
            }

            #region validate the base folder
            object baseFolderValue;
            if (!lobSystemInstance.GetProperties().TryGetValue(baseFolderPropertyName, out baseFolderValue))
            {
                throw new InvalidOperationException("BaseFolder property is missing");
            }

            String baseFolderName = baseFolderValue as string;

            if (String.IsNullOrEmpty(baseFolderName))
            {
                throw new InvalidOperationException("BaseFolder proeprty contains an invalid value.");
            }

            DirectoryInfo baseFolder = new DirectoryInfo(baseFolderName);

            if (!baseFolder.Exists)
            {
                throw new InvalidOperationException("Base folder doesn't exist.");
            }
            #endregion

            //This connector works based on the type of the MethodInstance
            //Most other connectors work on the name of the method
            if (methodInstance.MethodInstanceType == MethodInstanceType.Finder)
            {
                //Connector assumption:
                //First parameter will always be a wildcarded search string for file name
                //Second parameter will always be the return value
                String           wildcard = methodSignatureArgs[0] as string;
                IList <FileInfo> results  = new List <FileInfo>();
                methodSignatureArgs[1] = baseFolder.GetFiles(wildcard);
            }
            else if (methodInstance.MethodInstanceType == MethodInstanceType.SpecificFinder)
            {
                //Connector assumption:
                //First parameter will always be the file name
                //Second parameter will always be the return value
                string   fileName = methodSignatureArgs[0] as string;
                FileInfo result   = new FileInfo(Path.Combine(baseFolder.FullName, fileName));
                if (result.Exists && result.Directory.FullName.Equals(baseFolder.FullName))
                {
                    methodSignatureArgs[1] = result;
                }
            }
            else if (methodInstance.MethodInstanceType == MethodInstanceType.StreamAccessor)
            {
                //Connector assumption:
                //First parameter will always be the file name
                //Second parameter will always be the return value
                string   fileName = methodSignatureArgs[0] as string;
                FileInfo result   = new FileInfo(Path.Combine(baseFolder.FullName, fileName));
                if (result.Exists && result.Directory.FullName.Equals(baseFolder.FullName))
                {
                    methodSignatureArgs[1] = result.OpenRead();
                }
            }
        }
 public Uri GetDisplayUri(ILobSystemInstance lobSystemInstance)
 {
     throw new NotImplementedException();
 }
 public Uri GetDisplayUri(IEntity entity, ILobSystemInstance lobSystemInstance)
 {
     return(this.accessUri);
 }
 public Uri GetAccessUri(IEntity entity, ILobSystemInstance lobSystemInstance)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Generates display URL for a LobSystemInstance.
 /// </summary>
 public Uri GetDisplayUri(ILobSystemInstance lobSystemInstance)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Generates access URL for an Entity.
 /// </summary>
 public Uri GetAccessUri(IEntity entity, ILobSystemInstance lobSystemInstance)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// This method does the processing of incoming URLs. The intent here is to receive a URL via this context
        /// object, parse it to determine what metadata object it refers to, and then populate members of this class
        /// with this information.
        /// </summary>
        /// <param name="context">
        /// Supplies the connection context. The context contains (most importantly) the URL of the item being crawled,
        /// and also other information about the current crawl.
        /// </param>
        public override void Initialize(
            Microsoft.Office.Server.Search.Connector.IConnectionContext context)
        {
            Uri sourceUri = context.Path;

            //
            // A URL can point to a LobSystem, a LobSystemInstance, an Entity, or a specific instance of an Entity.
            // A specific instance of an Entity for MyFileConnector would be, of course, an actual file or folder on
            // disk. The other BCS metadata objects exist to provide you more flexibility in designing your connector
            // by providing slightly different crawling behaviors (which we'll detail below).
            //
            // Your job in this method is to parse the URL and decide what it's pointing to. Then, populate the
            // appropriate class members to indicate what it's pointing to.
            //
            // To indicate that the supplied URL refers to a(n):         Populate only these class members:
            //
            //                                         LobSystem         this.LobSystem
            //
            //                                 LobSystemInstance         this.LobSystem
            //                                                           this.LobSystemInstance
            //
            //                                            Entity         this.LobSystem
            //                                                           this.LobSystemInstance
            //                                                           this.Entity
            //
            //                                   Entity instance         this.LobSystem
            //                                                           this.LobSystemInstance
            //                                                           this.Entity
            //                                                           this.Identity
            //
            // What happens when these BCS metadata objects are crawled? Obviously, if you've got an entity instance,
            // you're crawling an actual item in your repository. But what about the others? In general, there's no real
            // data or metadata associated with any of them until you get down to an actual Entity instance (i.e., a
            // file or folder on disk, in the case of this connector). So the only real thing that happens when these
            // objects are crawled is that they emit their children, which will then subsequently be crawled. So here's
            // what the "children" of each of these metadata objects are:
            //
            //  Metadata object type    Children that are emitted when crawled
            //
            //  LobSystem               All LobSystemInstances in the model file that are marked with the
            //                          'ShowInSearchUI' property.
            //
            //  LobSystemInstance       If at least one Entity defined in this LobSystemInstance has a Finder method
            //                          with the 'RootFinder' property set, the LobSystemInstance will emit all Entities
            //                          that have Finder methods marked with the 'RootFinder' property. If an Entity
            //                          does not have a RootFinder, it will not be emitted.
            //
            //                          If no Entities in the LobSystemInstance with a Finder marked with the
            //                          'RootFinder' property, the LobSystemInstance will emit any Entities that have
            //                          both IdEnumerator and SpecificFinder methods defined in the model file. Note: If
            //                          you define only one of the two (either IdEnumerator or SpecificFinder) in this
            //                          case, an exception will be thrown at crawl time. You must define both to be
            //                          crawled in this manner.
            //
            // (Up to this point, with the previous two metadata objects, we had not yet called into the custom
            // connector shim. Instead, we were able to figure out what to emit from the model file alone. Starting with
            // the Entity, we will be calling into the custom connector shim, and also the full and incremental crawl
            // behavior can be different...)
            //
            // Metadata object type     Children that are emitted when crawled
            //
            // Entity                   Full crawl:
            //                          If the Entity has a Finder with the 'RootFinder' property set, that method is
            //                          called. Whatever entity instances your shim emits are the child items of the
            //                          Entity. If there is no Finder with the 'RootFinder' property set, but there
            //                          is an IdEnumerator defined for the entity, that method will be called, and
            //                          whatever entity instances your shim emits are the child items of the Entity.
            //
            //                          Incremental crawl:
            //                          If the Entity is the source for any AssociationNavigator methods that are marked
            //                          with the 'DirectoryLink' property, the behavior is the same as in the full
            //                          crawl. If there are no AssociationNavigator methods where the Entity is the
            //                          source, marked with the 'DirectoryLink' property, and the Entity has both a
            //                          ChangedIdEnumerator and DeletedIdEnumerator defined, then both of those methods
            //                          will be called in an incremental crawl. If none of the above is true, the
            //                          incremental crawl behavior is the same as full crawl.
            //
            // (Now, for an actual Entity instance (e.g., a file or folder on disk, in this case), it will be helpful to
            // define the concept of 'container'-type Entities. A 'container' type Entity is an Entity that is defined
            // in your model file as the SourceEntity of any AssociationNavigator marked with the 'DirectoryLink'
            // property.)
            //
            // Metadata object type     Children that are emitted when crawled
            //
            // Container-type           Full crawl:
            //  Entity instance         The association navigators for which the Entity type is the SourceEntity are
            //                          called.
            //
            //                          Incremental crawl:
            //                          This is the same as in a full crawl, unless several things are configured to
            //                          enable your shim to more intelligently decide what to emit. Here's what needs
            //                          to be configured to enable this behavior:
            //
            //                          1.  The SpecificFinder of the Entity has to return a field containing the number
            //                              of deleted direct child items in that particular container and this field
            //                              must be identified in the model file by defining the 'DeletedCountField'
            //                              property on the SpecificFinder method instance, where its value must be the
            //                              name of the field that returns the delete count.
            //
            //                          2.  The AssociationNavigator for which this Entity is the SourceEntity must
            //                              include in its return type descriptor a last modified time DateTime field
            //                              and this field must be identified in the model file by defining the
            //                              'LastModifiedTimeStamp' property on the AssociationNavigator method
            //                              instance, where its value must be the name of the fiels that returns the
            //                              last modified DateTime.
            //
            //                          3.  The AssociationNavigator for which this Entity is the SourceEntity must
            //                              have an input filter defined, and that input filter must have the
            //                              'CrawlStartTime' string property defined:
            //
            //                                  <FilterDescriptor Name="LastModifiedFilter" Type="Input">
            //                                      <Properties>
            //                                          <Property Name="CrawlStartTime" Type="String">x</Property>
            //                                      </Properties>
            //                                  </FilterDescriptor>
            //
            //                          4.  The AssociationNavigator for this this Entity is the SourceEntity must
            //                              take a DateTime input parameter, and that parameter must be associated with
            //                              the filter described in #3:
            //
            //                                  <Parameter Name="lastModifiedTime" Direction="In">
            //                                      <TypeDescriptor
            //                                          Name="lastModifiedTime"
            //                                          TypeName="System.DateTime"
            //                                          AssociatedFilter="LastModifiedFilter" />
            //                                  </Parameter>
            //
            //                          If this is the case, then the association navigator is called, and your shim
            //                          will be provided the last modified time to determine what items to return.
            //
            // Non-container-type       Full and incremental crawl behavior is the same. The SpecificFinder of the
            //  Entity instance         non-container Entity is called. You can also enable caching behavior, if the
            //                          method that emitted this Entity instance has the 'UseClientCachingForSearch'
            //                          property defined on its method instance. If caching is enabled in this way,
            //                          the SpecificFinder is not called, and only the data returned by the method
            //                          that originally emitted this Entity instance (i.e., an AssociationNavigator
            //                          or IdEnumerator, etc.) will be used to index the item. Note: If you return a
            //                          security descriptor in the return type descriptor, identified by the
            //                          'WindowsSecurityDescriptorField' defined on the method instance, then items
            //                          will *not* be cached, regardless of if you set the 'UseClientCachingForSearch'
            //                          property or not. The reason is that the SharePoint Search crawler has a limited
            //                          size for caching an individual item, and security descriptors can regularly
            //                          exceed that size.
            //

            //
            // As we mentioned above, we expect that every URL will resolve to a valid folder or file once we
            // translate it. Because of this, we won't really need to crawl any of the BCS metadata objects (LobSystem,
            // LobSystemInstance or Entity) - we'll only be crawling Entity instances. So based on the above, we know
            // that this method must end up populating all four LobUri properties.
            //

            //
            // We already populated this.lobSystem in the constructor. Now here's this.lobSystemInstance.
            // LobSystemInstances are statically defined in your model file. In this sample, we've only defined one.
            //
            this.lobSystemInstance = this.lobSystem.GetLobSystemInstances()[0].Value;

            //
            // Next, we need to figure out what Entity to which the URL refers to populate this.Entity. So for starters,
            // let's read the first segment to see what entity type we should assign to this.Entity.
            //
            String entityType = sourceUri.Segments[1].Replace("/", "");
            if(entityType.Equals("MyFolder", StringComparison.OrdinalIgnoreCase))
            {
                this.entity = this.Catalog.GetEntity("MyFileConnector", "MyFolder");
            }
            else if (entityType.Equals("MyFile", StringComparison.OrdinalIgnoreCase))
            {
                this.entity = this.Catalog.GetEntity("MyFileConnector", "MyFile");
            }
            else
            {
                throw new Microsoft.BusinessData.Runtime.RuntimeException(String.Format(
                    "Invalid entity type {0} specified in URL {1}",
                    entityType,
                    sourceUri.ToString()));
            }

            //
            // Finally, populate this.identity. Generally, the 'identity' is whatever your repository needs to uniquely
            // identify an Entity instance. In the case of our repository, an NTFS file system, that would conveniently
            // just be the path to the file. So reconstruct the URL as a UNC path, minus the first segment.
            //
            StringBuilder path = new StringBuilder(@"\\");
            path.Append(sourceUri.Host);
            path.Append(@"\");
            for (int i = 2; i < sourceUri.Segments.Length; ++i)
            {
                path.Append(SPHttpUtility.UrlPathDecode(sourceUri.Segments[i].Replace('/', '\\'), false));
            }

            this.identity = new Microsoft.BusinessData.Runtime.Identity(path.ToString());
        }