BDC .NET Assembly Connector: Tame SharePoint Search to search your .NET BDC Entity

So, now you have built your BDC .NET Assembly Connector and even added write operations to it. The next big thing you would think is – Can I tell SharePoint to search this BDC model?

Of course, you can! But there are few things you need to do in your BDC model in order for SharePoint to crawl your BDC model.

The BDC model exposes operations or methods through which SharePoint is going to interact with the external data sources. In our previous example, we had 3 operations:

  1. ReadItem – Read Operation returning a single entity
  2. ReadList – Read operation returning a collection of entities
  3. Update – Write operation updating a single entity

So, when you want SharePoint to crawl the BDC model, we need to tell SharePoint which operation to use in order to gather the data.

The RootFinder Method

With the BDC models, we can set properties on operations, entities, LOB instances etc., that let SharePoint identify certain extra capabilities. If a finder method has its RootFinder property set, then SharePoint will know that it has to enumerate the entities to crawl.

In our sample, the ReadList method is going to return all the entities and thus we can set the RootFinder property on this method.

Switch to your BDC Explorer, and click on ReadList. In the properties, click on Custom Properties button and add the RootFinder property as in the screenshot below:

NameRootFinder

Type – Select System.String from the dropdown

Valuex

RootFinder

Switch to the designer pane and click on the ReadList method:

BookEntity

In the BDC Method Details pane below, click on ReadList instance under Instances under ReadList method:

ReadList Instance

In the properties, click on Custom Properties button and add the RootFinder property as in the screenshot below:

NameRootFinder

Type – Select System.String from the dropdown

Valuex

RootFinder

Remember, since we want the ReadList method to be the RootFinder, we are doing this. If you have any other method, you can set this property for that method instead of the ReadList method.

Setting the ShowInSearchUI Property for the Lob System Instance

Not only we need to set the RootFinder property for the specific finder method, we also need to set the ShowInSearchUI property on the LobSystemInstance to true. This will tell SharePoint that this particular LobSystemInstance should be used in Search UI. Unfortunately, currently this can only be done via code. Below is the code to set this property on the BooksListBdcModelInstance. Just create a simple console application and execute the following code. You need to add the BDC Admin Object Model references which are as follows:

NOTE: The following is only applicable for the current Beta 2 release which is publically available. Things might change in the later builds.

  1. Microsoft.BusinessData from C:\Windows\assembly\GAC_MSIL\Microsoft.BusinessData\14.0.0.0__71e9bce111e9429c\
  2. Microsoft.SharePoint.BusinessData.Administration.Client from C:\Windows\assembly\GAC_64\Microsoft.SharePoint.BusinessData.Administration.Client\14.0.0.0__71e9bce111e9429c\
  3. microsoft.office.sharepoint.clientextensions.intl from C:\Windows\assembly\GAC_MSIL\microsoft.office.sharepoint.clientextensions.intl\14.0.0.0__71e9bce111e9429c\
static void Main(string[] args)
{
AdministrationMetadataCatalog catalog =
AdministrationMetadataCatalog.GetCatalog("http://demo2010a");
Model bdcModel=catalog.GetModel("BooksListBdcModel");
LobSystemCollection lobs = bdcModel.AllReferencedLobSystems;

LobSystem flatFileBDCModel = (from l in lobs
where l.Name == "BooksListBdcModel"
select l).FirstOrDefault();
if (flatFileBDCModel != null)
{
LobSystemInstance flatFileBDCModelInstance
= (from ls in flatFileBDCModel.LobSystemInstances
where ls.Name == "BooksListBdcModelInstance"
select ls).FirstOrDefault();

if (flatFileBDCModelInstance != null)
{
Console.WriteLine("Updating ShowInSearchUI property for " + flatFileBDCModelInstance.Name);
flatFileBDCModelInstance.Properties.Add("ShowInSearchUI", "true");
//flatFileBDCModelInstance.Properties.Remove("ShowInSearchUI");
flatFileBDCModelInstance.Update();

flatFileBDCModel.Update();
}
}

bdcModel.Update();

Console.ReadKey();
}

We are using the BDC Admin Object Model and:

  1. Connect to the SharePoint Site – change the site from http://demo2010a to your SharePoint site
  2. Get the Catalog – which is BooksListBdcModel
  3. Get the Lob System – which is again BooksListBdcModel
  4. Get the Lob System Instance – which is BooksListBdcModelnstance
  5. Set the property to true

BDCModel

Configure SharePoint Search

Creating the BDC Content Source

Go to the Search Administration in Central Admin – Central Administration | Application Management | Manage service applications | Search Service Application and create a new Content Source

Select the Content Source Type as Line of Business Data

Content Source Type Options

Select to crawl selected external data sources and select BooksListBdcModelInstance

External Data Source Options

Select to start a full crawl and click OK. This will start a full crawl of the content source.

Wait till the full crawl is over.

Updating the Scopes

Now go to your scope where you want to include this content source and create a new rule to include this content source:

Scopes

Click OK.

Wait for the scope to be updated. This might from few seconds to few minutes depending on the content (It took 18 minutes for me!) or You could start the update manually from the Search Administration page. Look for Scopes updates status in the System Status.

Perform Search

Once the content source is crawled and scopes updates, perform the search from the site. For our books entity, enter any ISBN number, say for example 0470099410 in the search text box and hit the search button.

You should see the search results showing up!

BDC Search Results

(Clicking on it will not take you to the list item though)

Using KeywordQuery to search in your SharePoint site

There are various ways that you can query the Search Service in your SharePoint site:

1) Using the Search Web Service

2) Using the SharePoint Object Model

There are yet again two ways you can use the Search, using the Object Model:

i) KeywordQuery

ii) FullTextSqlQuery

I think it is a good option to use Object Model when you want to customize the Search (mostly in your WCM websites), and KeywordQuery comes in very handy!

Using KeywordQuery to search is pretty simple! (provided you have set up your Search properly)

KeywordQuery keywordQuery = new KeywordQuery(SPContext.Current.Site);
keywordQuery.ResultTypes = ResultType.RelevantResults | ResultType.SpecialTermResults;
keywordQuery.StartRow = 1;
keywordQuery.RowLimit = 5;
keywordQuery.SortList.Add("Rank", SortDirection.Descending);
keywordQuery.EnableStemming = true;
keywordQuery.TrimDuplicates = true;
keywordQuery.IgnoreAllNoiseQuery = true;
keywordQuery.HiddenConstraints = "scope:" + "\"" + SearchScope + "\"";
keywordQuery.QueryText = SearchText;
ResultTableCollection searchResults = keywordQuery.Execute();

As you can see above, I have combined the result type to be both RelevantResults and SpecialTermResults

Note: In WSS, only RelevantResults will work

One other thing to note in the above code is how we specify the scope using the HiddenConstraints

The search results are returned as a table collection. You can access the search tables as follows:

ResultTable relevantResultsTable = searchResults[ResultType.RelevantResults];
ResultTable specialTermResultsTable = searchResults[ResultType.SpecialTermResults];

If you want to load these into a DataSet with tables RelevantResults and SpecialTermResults respectively, then:

// Relevant Results table
DataTable relevantResults = new DataTable();
relevantResults.TableName = "RelevantResults";
 
// SpecialTerms Results table
DataTable specialTermResults = new DataTable();
specialTermResults.TableName = "SpecialTermResults";
 
// Search Results DataSet
DataSet resultSet = new DataSet();
 
 // Relevant Results
relevantResults.Load(relevantResultsTable, LoadOption.OverwriteChanges);
resultSet.Tables.Add(relevantResults);
 
// SpecialTerms Results
resultSet.Tables.Add(specialTermResults);
specialTermResults.Load(specialResultsTable, LoadOption.OverwriteChanges);

You can now easily databind this DataSet

 

 

If you have worked with the Search Web Service, you will notice that the properties in KeywordQuery and the Search Query XML are similar

<?xml version="1.0" encoding="utf-8" ?>
<QueryPacket xmlns="urn:Microsoft.Search.Query" Revision="1000">
<Query domain="QDomain">
 <SupportedFormats><Format>urn:Microsoft.Search.Response.Document.Document</Format></SupportedFormats>
 <Context>
  <QueryText language="en-US" type="STRING" >  SCOPE:"All Sites"</QueryText>
 </Context>
<SortByProperties><SortByProperty name="Rank" direction="Descending" order="1"/></SortByProperties>
 <Range><StartAt>1</StartAt><Count>5</Count></Range>
 <EnableStemming>true</EnableStemming>
 <TrimDuplicates>true</TrimDuplicates>
 <IgnoreAllNoiseQuery>true</IgnoreAllNoiseQuery>
 <ImplicitAndBehavior>true</ImplicitAndBehavior>
 <IncludeRelevanceResults>true</IncludeRelevanceResults>
 <IncludeSpecialTermResults>true</IncludeSpecialTermResults>
 <IncludeHighConfidenceResults>true</IncludeHighConfidenceResults>
</Query></QueryPacket>

(Above Search Query XML was generated using SharePoint Search Service Tool)


Creative Commons License
Chaks' Corner Blog by Chakkaradeep Chandran is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.
Based on a work at www.chakkaradeep.com.
Permissions beyond the scope of this license may be available at http://www.chakkaradeep.com.