Deploying and setting permissions on a BCS model via PowerShell
Recently I have been looking at ways that I can go about deploying a BCS (Business Connectivity Services, or the BDC for anyone still in SP2007 land) model via PowerShell as part of a wider deployment script for a project I have been working on, and finding out a good way to do this was not as simple as I would have thought, so I figured I would document what I did here.
The first thing I needed to do was to deploy the model, which there is a simple enough process for, but I needed to customise things like the database server name in the model based on the environment I was deploying to, and I didn’t want to maintain 4 copies of the file just for a couple of lines to be different, so the first step was to bring in the BCDM file (which I created by building the model in SharePoint Designer and then exporting it) to my script, do a couple of find and replace for tokens I put into the file and then saving it to a temp location. The code looks like this:
$PSScriptRoot = Split-Path -Parent -Path (Get-Item -Path $MyInvocation.MyCommand.Path).FullName;
$modelText = Get-Content "$PSScriptRootMyModelFile.bdcm"
$modelText = ($modelText) -replace ("%DatabaseServer%", "DbServerName")
$filename = [System.IO.Path]::GetTempFileName();
$modelText | Out-File $filename
So the settings I was using in the replace had come from an XML file I read for environment specific settings at the start of my deployment script, but they could come from where ever suits your particular example. Once I had my temp file ready to import with the environment specific changes made, and SP2010 makes this one pretty easy with a couple of specific cmdlets. Here is the code for this part:
$metadataStore = Get-SPBusinessDataCatalogMetadataObject -BdcObjectType "Catalog" -ServiceContext "http://MyWebAppUrl"
Import-SPBusinessDataCatalogModel -Path $filename -Identity $metadataStore -Force
Remove-Item $filename
You can see at the end I also remove the temp file as well. Now at this point we have our model imported and ready to use,the last thing we need to do before it is usable is to assign permissions to it so users can query it for data. In my example here I have an admin user and a general users group,here’s the code:
$entity = Get-SPBusinessDataCatalogMetadataObject -BdcObjectType "Entity" -ServiceContext "http://MyWebAppUrl" -Name "My Entity Name" -Namespace "My.Entity.Namespace"
$claimAdmin = New-SPClaimsPrincipal -Identity "EXDBrian" -IdentityType WindowsSamAccountName
Grant-SPBusinessDataCatalogMetadataObject -Identity $entity -Principal $claimAdmin -Right "Execute,SetPermissions,Edit,SelectableInClients"
$claimUsers = New-SPClaimsPrincipal -Identity "EXDDomain Users" -IdentityType WindowsSamAccountName
Grant-SPBusinessDataCatalogMetadataObject -Identity $entity -Principal $claimUsers -Right "Execute,Edit,SelectableInClients"
So here you see me create a claims principal for the specific users (in the admin case a single user, the second one is an AD group but the same process applies), and then I assign them permissions to the object I just created (which I have retrieved first). The Right parameter here is actually an enumeration value, but PowerShell lets us shortcut selection of multiple values by just writing is a comma separated list.
When you put that all together, you now have a deployed model and permissions applied so it is ready to use!
No new comments are allowed on this post.
Comments
Ari Bakker
Brilliant, just what I was after. Pity Visual Studio forces you to hard code the values for the database server and the site url, this is a great alternative.
Ari Bakker
Note you might also need to call $entity.CopyAclAcrossChildren() to propagate the permission changes to all methods of an external content type. I was getting the error "Access denied by Business Data Connectivity" after running the code mentioned above as the read list and read item methods did not have any permissions assigned.
Scot Hillier
Nice work. I'm deploying a LOB system that has a few dozen models, so this was very helpful. I modified your code a little to simply loop through all of the model files in a deployment folder.
$f = "C:\folder" cd $f $models = Get-Children . foreach($model in $models) { }
Scot
Chrissy LeMaire
Hey thanks, I used your script for the basis of this script which changes permissions on all the children too:
$catalog = Get-SPBusinessDataCatalogMetaDataObject -BdcObjectType Catalog -ServiceContext "http://localhost"
$claimAdmin = New-SPClaimsPrincipal -Identity "DOMAIN\Admins" -IdentityType WindowsSamAccountName $claimUsers = New-SPClaimsPrincipal -Identity "DOMAIN\Users" -IdentityType WindowsSamAccountName
Grant-SPBusinessDataCatalogMetadataObject -Identity $catalog -Principal $claimAdmin -Right "Execute,SetPermissions,Edit,SelectableInClients" Grant-SPBusinessDataCatalogMetadataObject -Identity $catalog -Principal $claimUsers -Right "Execute,Edit,SelectableInClients"
Copy-SPBusinessDataCatalogAclToChildren -MetadataObject $catalog