Tuesday, October 28, 2008

Create SharePoint BDC connector for AdventureWorks database with F# Script

I have been exploring how to create Business Data Catalog in the SharePoint environment. It seems the best way to create BDC application definition file is via a tool called BDC Meta Man, which provides a graphical environment to create the definition file. For my own understanding, I tried to script the creation of the BDC application definition file. In the F# script below, I created the BDC to the HR data in the sample AdventureWorks SQL Server database. This script loosely follows Chapter 4 of Patrick Tisseghem's book Inside Microsoft Office SharePoint Server 2007.



#light
#I @"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI"
#r @"Microsoft.SharePoint.dll"
#r @"Microsoft.SharePoint.Portal.dll"
#r @"Microsoft.Office.Server.dll"

open Microsoft.Office.Server.ApplicationRegistry.Administration
open Microsoft.Office.Server.ApplicationRegistry.Infrastructure
open Microsoft.Office.Server.ApplicationRegistry.SystemSpecific.Db
open List
open System.Data

SqlSessionProvider.Instance().SetSharedResourceProviderToUse("SharedServices1")

// Create LOB System
let lobsystem =
("Adventure Works Human Resources Data",
false,
"Microsoft.Office.Server.ApplicationRegistry.SystemSpecific.Db.DbSystemUtility",
"Microsoft.Office.Server.ApplicationRegistry.SystemSpecific.Db.DbConnectionManager",
"Microsoft.Office.Server.ApplicationRegistry.SystemSpecific.Db.DbEntityInstance")
|> ApplicationRegistry.Instance.LobSystems.Create


// Add property defining the character % will be replacing the * wildcar entered by users
("WildcardCharacter","%") |> lobsystem.Properties.Add
lobsystem.Update()


// Create LOB System instance
let sysInstance = lobsystem.LobSystemInstances.Create("HR data",true)

("AuthenticationMode",DbAuthenticationMode.RevertToSelf) |> sysInstance.Properties.Add
("DatabaseAccessProvider", DbAccessProvider.SqlServer) |> sysInstance.Properties.Add

[("RdbConnection Data Source", "MOSS");
("RdbConnection Initial Catalog","AdventureWorks");
("RdbConnection Integrated Security", "SSPI")]
|> iter (fun (k,v) -> sysInstance.Properties.Add (k,v))

sysInstance.Update()

// Create Employee Entity
let entity = lobsystem.Entities.Create("Employee",true)
let identifier = entity.Identifiers.Create("[EmployeeID]",true,"System.Int32")
let mthd = entity.Methods.Create("GetEmployees",true,true)

("RdbCommandText",
@"Select [EmployeeID],[Title],[FirstName],[MiddleName],[LastName],[Suffix],[JobTitle],[Phone],[EmailAddress],[EmailPromotion],[AddressLine1],[AddressLine2],[City],[StateProvinceName],[PostalCode],[CountryRegionName],[AdditionalContactInfo] From HumanResources.[vEmployee]"
) |> mthd.Properties.Add

("RdbCommandType",CommandType.Text) |> mthd.Properties.Add



let createParameter (thismethod:Method) name direction =
(name,true,direction,
"Microsoft.Office.Server.ApplicationRegistry.Infrastructure.DotNetTypeReflector")
|> thismethod.Parameters.Create


let parEmployees = createParameter mthd "Employees" Microsoft.Office.Server.ApplicationRegistry.MetadataModel.DirectionType.Return

let tdEmployees =
let root =
("EmployeeDataReader",true,
"System.Data.IDataReader, System.Data, Version=2.0.3600.0,Culture=neutral, PublicKeyToken=b77a5c561934e089",
null,null,true)
|> parEmployees.CreateRootTypeDescriptor
let node =
("EmployeeDataRecord",true,
"System.Data.IDataRecord, System.Data, Version=2.0.3600.0,Culture=neutral, PublicKeyToken=b77a5c561934e089",
null,null,false)
|> root.ChildTypeDescriptors.Create

(("EmployeeID", true, "System.Int32", identifier, null, false)
|> node.ChildTypeDescriptors.Create).LocalizedDisplayName <- "Employee ID"

let firstname =
("FirstName", true, "System.String", null, null, false)
|> node.ChildTypeDescriptors.Create
firstname.LocalizedDisplayName <- "First Name"
firstname.Update()

let lastname =
("LastName", true, "System.String", null, null, false)
|> node.ChildTypeDescriptors.Create
lastname.LocalizedDisplayName <- "Last Name"
lastname.Update()

[("JobTitle","System.String","Job Title");
("Phone","System.String","Phone");
("EmailAddress","System.String","Email");
("AddressLine1","System.String","Address");
("City","System.String","City");
("StateProvinceName","System.String","State");
("PostalCode","System.String","Zip");
] |> iter (fun (label,typename,display) ->
((label, true, typename, null, null, false)
|> node.ChildTypeDescriptors.Create).LocalizedDisplayName <- display)
root


// Create method instances
let getEmployees =
("EmployeeFinderInstance",true,tdEmployees,Microsoft.Office.Server.ApplicationRegistry.MetadataModel.MethodInstanceType.Finder)
|> mthd.MethodInstances.Create










1 comment:

digital signatures said...

Very informative post. I sometimes do presentations on SharePoint and was wondering if I could use your Print List example in my presentations and refer my audience to your website for further info.