One of our integration partners prefers to provide their integration points as SQL Server 2008 stored procedures, which is very well supported by BCS. BCS supports both stored procedures and table valued functions, called "routines" in SharePoint Designer (SPD). SharePoint Designer is dependent on being able to extract metadata about the returned table data set when adding External Content Type (ECT) operations or when using the Operations Design View.
Alas, the provided integration sprocs used dynamic SQL statements, and for technical reasons this could not be rewritten to inline SQL select statements. This is as always a problem with tooling such as SPD, as no result set metadata can be discovered. When connecting SPD to the external system, I got no fields in the Data Source Elements panel in the Read List operation's Return Parameter Configuration. Rather I got three errors and a warning.
The workaround is quite simple and requires the use of a SQL Server table variable, which defines the result set and allows SPD to discover the table metadata. Rewrite the stored procedure by declaring a table variable, insert the result of the dynamic SQL statement into the variable, and finally return the result set by reading the table variable. The changes to the sproc is shown in blue in this example:
CREATE PROCEDURE [dbo].[GetFavorites]
SET NOCOUNT ON;
DECLARE @DbName AS NVARCHAR(max) = 'ARISModellering1'
DECLARE @ObjDef AS NVARCHAR(max) = dbo.GetArisTableName(@DbName, 'ObjDef')
DECLARE @Model AS NVARCHAR(max) = dbo.GetArisTableName(@DbName, 'Model')
DECLARE @FavoriteSQL AS NVARCHAR(max) = N'
ARISBPDATA.BOOKMARKS.ID AS FavoriteId
, ARISBPDATA.BOOKMARKS.DESCRIPTION AS FavoriteName
, ModelType.ModelTypeName AS FavoriteType
, LOWER(ARISBPDATA.BOOKMARKS.USERNAME) AS UserName
+ ARISBPDATA.BOOKMARKS.DATAKEY AS FavoriteUrl
INNER JOIN ' + @Model + ' m ON ARISBPDATA.BOOKMARKS.OBJID = m.Id
INNER JOIN ModelType ON m.TypeNum = ModelType.ModelTypeId
DECLARE @userFavs TABLE(FavoriteId int not null, FavoriteName nvarchar(max),
FavoriteType nvarchar(max), UserName nvarchar(max), FavoriteUrl nvarchar(max))
insert @userFavs EXEC sp_executeSQL @FavoriteSQL
select * from @userFavs
Refreshing the external system data connection and then creating the ECT read list operation now works fine, and all the return type errors and warnings are gone.
Note that the classic #temp table workaround won't work with SPD, you have to use a table variable in your stored procedure. The sproc will now use more memory, so the BCS best practice for keeping finder result sets small applies.
The table_variable declaration is also a good place to make sure that the identifier column is "not null" and that it is a supported BCS data type such as "int32". External lists cannot be created from an ECT whose identifier field is unsupported, such as SQL Server "bigint", and I strongly recommend using a supported identifier data type right from the start. Getting the ECT identifier wrong in the BCS model will give you problems later on when using SharePoint Designer.