SharePoint 2007: BDC - Writing Custom Code against the runtime object model

Posted on 4/24/2007 @ 5:18 AM in #SharePoint by | Feedback | 15350 views


SharePoint 2007: BDC - The Business Data Catalog

This post is in continuation to a series of blogposts I put up on BDC - the Business Data Catalog.

Table of Contents:

  • Introduction
  • In-built Webparts
  • Lists with Business data type columns.
  • Search
  • User Profiles
  • Other custom applications targeting a common runtime object model.  <--- You are here.
  • Making it easier to author XML Applications: BDCMetaMan
  • Whew!

    My long series on BDC is coming to an end. What a bitch it has been to type so much LOL. So first of all, if I missed something, please ping me, so I can blog about it.

    In this last post, I am going to target the application we wrote here, using custom code.

    Here is a quick sample application targeting literally any BDC app.

    Sniffing your BDC App.

    static void Main(string[] args)

    {

        string ssp = "SharedServices1" ;

        SqlSessionProvider.Instance().SetSharedResourceProviderToUse(ssp);

        NamedLobSystemDictionary lobSystems =

          ApplicationRegistry.GetLobSystems();

       

        foreach (LobSystem system in lobSystems.Values)

        {

            Console.WriteLine("Application: " + system.Name);

            NamedDataClassDictionary lobClasses = system.GetDataClasses();

            foreach (DataClass dataClass in lobClasses.Values)

            {

                Console.WriteLine("  Entities: " + dataClass.Name);

            }

        }

    }

    If I run the above, I get this output -

    Application: NorthWindApp
      Entities: Order
      Entities: Customer

    If you are wondering, I am using namespaces

        Microsoft.Office.Server.ApplicationRegistry.MetaDataModel
        Microsoft.Office.Server.ApplicationRegistry.Infrastructure.

    The references are

        Microsoft.Office.Server.dll
        Microsoft.SharePoint.dll
        Microsooft.SharePoint.Portal.dll

    Now, Let us slice and dice the above code step by step.

    The first thing you see in the above code is SqlSessionProvider. SqlSessionProvider represents a way to connect to the SSP. It immediately sticks out that the BDC runtime can target only the local farm. So, if you wish to allow BDC access over the network, you will need to write a webservice and deploy it on the farm, and access it via the web service.

    Once you get a hold of an instance using SqlSessionprovider.Instance(), you can then start querying it for various stuff. For instance, the first thing I wanted to find out were all the LobSystems (i.e. applications) registered in the SSP. And once I have the applications found, I can find the individual entities in each one of those classes.

    Once I have the individual entities, I can easily find the methods that entity has using the code below -

    DataClass customers = lobClasses["Customer"];

    NamedMethodDictionary methods = customers.GetMethods();

    foreach (Method meth in methods.Values)

    {

        Console.WriteLine("    Method: " + meth.Name);

    }

    You can continue to sniff around, and you will see that you can find methods, method instances, properties, heck if you snooped around enough, you could literally smell the entire metadata for the BDC app.

    So now that I have information about the BDC app, the next question is "How to use it".

    Using your BDC App.

    In order to actually use your BDC App, you need to first get a hold of the LobSystemInstances. Check the code out below -

    static void Main(string[] args)

    {

    string ssp = "SharedServices1" ;

    SqlSessionProvider.Instance().SetSharedResourceProviderToUse(ssp);

     

    NamedLobSystemDictionary lobSystems = ApplicationRegistry.GetLobSystems();

     

    foreach (LobSystem system in lobSystems.Values)

    {

        Console.WriteLine("Application: " + system.Name);

        NamedLobSystemInstanceDictionary instances =

           system.GetLobSystemInstances();

     

        foreach (LobSystemInstance instance in instances.Values)

        {

            Console.WriteLine(instance.Name);

        }

    }

    }

    You might ask, what is the difference between a LobSystem and a LobSystemInstance? BDC in MOSS 2007 lets you put upto two instances on each LobSystem. This means, you get different authentication settings for the two instances, for the same application. This is incredibly useful, say when you are setting up search on BDC, because you would typically want search to work under different credentials than regular BDC usage by a user.

    Once you have the specific instance, you can then find the entity, the filters, set filter values, and finally execute the Finder method using the following code -

    Entity customerEntity = instance.GetEntities()["Customer"];

     

    FilterCollection filterColl = customerEntity.GetFinderFilters() ;

    (filterColl[0] as WildcardFilter).Value = "London";

     

    IEntityInstanceEnumerator customerEnum =

        customerEntity.FindFiltered(filterColl, instance);

     

    while(customerEnum.MoveNext())

    {

        DataTable dt =

          (customerEnum.Current as DbEntityInstance).EntityAsDataTable;

        PrintDataRow(dt.Rows[0]);

    }

     

    PrintDataRow is simply a method that prints out the values of the DataRow in a single line.

    The full final code looks like this.

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Data;

    using Microsoft.Office.Server.ApplicationRegistry.MetadataModel;

    using Microsoft.Office.Server.ApplicationRegistry.Infrastructure;

    using Microsoft.Office.Server.ApplicationRegistry.Runtime;

    using Microsoft.Office.Server.ApplicationRegistry.SystemSpecific.Db;

     

    namespace SampleBDCApp

    {

        class Program

        {

            static void Main(string[] args)

            {

                string ssp = "SharedServices1";

                SqlSessionProvider.Instance().SetSharedResourceProviderToUse(ssp);

     

                NamedLobSystemDictionary lobSystems = ApplicationRegistry.GetLobSystems();

     

                foreach (LobSystem system in lobSystems.Values)

                {

                    Console.WriteLine("Application: " + system.Name);

                    NamedLobSystemInstanceDictionary instances =

                        system.GetLobSystemInstances();

     

                    foreach (LobSystemInstance instance in instances.Values)

                    {

                        Console.WriteLine(instance.Name);

     

                        Entity customerEntity = instance.GetEntities()["Customer"];

     

                        FilterCollection filterColl = customerEntity.GetFinderFilters() ;

                        (filterColl[0] as WildcardFilter).Value = "London";

     

                        IEntityInstanceEnumerator customerEnum =

                            customerEntity.FindFiltered(filterColl, instance);

     

                        while(customerEnum.MoveNext())

                        {

                            DataTable dt = (customerEnum.Current as DbEntityInstance).EntityAsDataTable;

                            PrintDataRow(dt.Rows[0]);

                        }

                    }

                }

            }

     

            private static void PrintDataRow(DataRow dr)

            {

                foreach (DataColumn dataColumn in dr.Table.Columns)

                {

                    Console.Write(dr[dataColumn] + "\t");

                }

                Console.WriteLine();

            }

        }

    }

    .. and when you execute this, you get the following output -

    Congratulations - you've just written your first application using BDC. You can now implement the above in a web service, and expose any underlying LOB using a consistent BDC API.

    Here is an interesting exercise for you to try - Try using Office SSO + WindowsCredentials, so the end application's identity matters when calling the web service, and that same identity goes all the way to the web service.

    Have fun!

    Sound off but keep it civil:

    Older comments..


    On 8/29/2007 10:17:16 AM Kanthi said ..
    Hi,


    I need some help on how to write a web service which accesses the BDC Search results in MOSS2007 and displays them in a WPF application.


    Can you please help me on how to go about and solve this?


    On 1/7/2008 6:21:13 AM Vijay said ..
    Hi,

    I’m planning to develop a Moss portal which is going to be a business (no data manipulation) views. My portal will be connected to LOB databases and fetch the results based on search criteria and display results in tabular format.

    Below I have given the two types of approach what I’m planning to do.

    Can you please suggest which the best approach?

    Approach 1 – using BDC


    I’m planning to develop the web service (because other non .NET application requires this data) and connecting the web service through BDC for fetching the results.)

    For example once user enters the search criteria then search criteria a will be passed to BDC and BDC in turn will talk to web service to fetch the results.

    Once the results are fetched then it will be displayed in Tabular format (DataGrid).

    We can’t use BDC web parts because we have to some customization like on click of some columns it should take user to some detail page.

    Approach 2 – Using Web service directly


    Directly query the results the web service from web part.

    Inputs on this regard are highly appreciated.

    Thanks and Regards,


    Vijay


    On 3/11/2008 11:23:21 PM Leo said ..
    Hi,

    Great Article. I am wondering if you ever try writing any codes to connect to a database using SSO instance. Instead of using SSO inside BDC. I'm trying to look for some .NET code. If you have any sample, can you let me know? My email is leolu@live.com.sg.

    Thanks alot.


    On 4/16/2008 1:08:51 AM Francois said ..
    first thing... thanks for being the light in the BDC darkness :)


    I have managed to load my list... do searches on it, resolve single item. My question is this.


    When typing in a single item, you can click the check icon, it then goes off and uses the Finder to see if thats single item exists. How do i make it bring up partial items in the menu that pops up when you right click on the item, if exact match was not found. Like when using the user control. please let me know if the question is not clear

    regards


    On 4/3/2009 6:01:47 PM Rahul Desai said ..
    Thank you for a wonderful article . I want to write back data in to Sap through bcd . Any suggestion will be help ful .


    On 6/11/2009 1:36:26 PM Shruti said ..
    How can I provide filtered data to the BusinessDataListWebPart?


    On 5/7/2010 9:18:54 AM Hemil said ..
    This is really a very useful post. I have a query. Is it possible to insert data into any LOB application(SQL Server table) from SharePoint list using BDC?