SharePoint: Understanding BusinessData Column (BDC Field)
This is the logical continuation of the article SharePoint: Brief introduction to Business Data Catalog (BDC)
Business Data Catalog (BDC) provides SharePoint with an ability to display, choose and store data from such external data sources as Web services and DataBases. Data item from external data source (either a record from a database or an object returned by a Web service) might be called BDC Entity Instance. BDC Column (or BDC Field, they are synonyms) is a column of ‘Business Data’ type. Once BDC Column is added to a list, users will be able to choose a BDC Entity Instance from the BDC to store as the value of the BDC Column.
BDC Column can be considered as a complex field, because technically it’s a group of several logically related SP fields. Adding one ‘Business Data’ column to the list, at least two fields will be added to the list in fact. The first is intended to contain a display value that will be shown to the user, while the second is intended to store an encoded identifier of the chosen BDC Entity Instance.
Let’s take a look at an example. Let’s assume that we have a Business Data Catalog that provides us with the Product object with the following structure:
Product { ID, Name, Price, Producer }
If we create a new ‘Business Data’ column on a list as it shown in the picture below,
the list schema exposes the following new fields:
<Field Type="BusinessData" DisplayName="Product" Required="FALSE" ID="{bc203358-6113-470f-9b08-f6100cc034f2}" StaticName="Product" BaseRenderingType="Text" Name="Product" SystemInstance="ExternalProductDB_Instance" Entity="Products" BdcField="Name" Profile="" HasActions="False" SecondaryFieldBdcNames="Price:Producer" RelatedField="Products_ID" SecondaryFieldWssNames="Product_x003a__x0020_Price:Product_x003a__x0020_Producer" RelatedFieldBDCField="" RelatedFieldWssStaticName="Products_ID" SecondaryFieldsWssStaticNames="Product_x003a__x0020_Price:Product_x003a__x0020_Producer" /> <Field Type="Note" DisplayName="Products_ID" Hidden="TRUE" ReadOnly="TRUE" BdcField="Products_ID" ID="{0d37c424-0e57-4429-8f92-0b8faec5a5bd}" StaticName="Products_ID" Name="Products_ID" /> <Field Type="Note" DisplayName="Product: Price" ReadOnly="TRUE" BdcField="Price" ID="{c56d7123-cb3f-46f4-8f45-874ac5cee13d}" StaticName="Product_x003a__x0020_Price" Name="Product_x003a__x0020_Price" /> <Field Type="Note" DisplayName="Product: Producer" ReadOnly="TRUE" BdcField="Producer" ID="{df740ff6-2998-46e1-ac40-974d66ba7dc7}" StaticName="Product_x003a__x0020_Producer" Name="Product_x003a__x0020_Producer" />
*Note: some redundant attributes of fields are skipped
We have four added SP Fields that are logically related. As I mentioned before, the first field (Name=”Product”) is intended to store a value, which is displayed to the user. Besides, the field contains a number of attributes that refer to all of the rest of logically related fields. We’ll study these attributes a bit later. The second field (Name=”Products_ID”) is a hidden field, which is intended to store an encoded identifier of the BDC Entity Instance. The encoded identifier usually looks like “__dk410035008400140025005400k410…”. It’s permissible if more than one BDC Entity fields compose the identifier.
Other two additional fields (Name=”Product_x003a__x0020_Price” and Name=”Product_x003a__x0020_Producer”) are to store and show such properties of the chosen BDC Entity Instance as Price and Producer. These additional fields are optional, you might be unwilling to have any extra information in the list.
Ok, let’s examine closer the first field (Name=”Product”). It includes the attributes that describe what properties of the chosen BDC Entity Instance will be captured and what additional SP fields they will be stored in. The most important attributes are shown below:
- SystemInstance – the name of the Lob System Instance or Business Data Catalog Application Instance, which BDC Column is bound to;
- Entity – the type name of returned business data object, which BDC Column is bound to;
- BdcField – the name of BDC Entity field, the value of which will be stored in this SharePoint field. For the Product field specifically, the stored value will be displayed to the user;
- RelatedField – the internal name of a hidden SharePoint field, which is to store an encoded identifier of the chosen BDC Entity Instance;
- RelatedFieldBDCField – usually an empty string, probably, it’s reserved for future usage, or it’s a legacy attribute;
- RelatedFieldWssStaticName – the static name of a hidden SharePoint field, which stores an encoded identifier of the chosen BDC Entity Instance;
- SecondaryFieldBdcNames – the colon-separated names of the fields within BDC Entity, the values of those fields are to be stored in the additional SharePoint fields. The attribute contains the same number of names as the SecondaryFieldWssNames attribute;
- SecondaryFieldWssNames – the colon-separated internal names of the additional SharePoint fields, that are to store additional values from the chosen BDC Entity Instance. The attribute contains the same number of names as the SecondaryFieldBdcNames attribute;
- SecondaryFieldsWssStaticNames – the colon-separated static names of the additional SharePoint fields, that are to store additional values from the chosen BDC Entity Instance. The attribute contains the same number of names as the SecondaryFieldBdcNames and SecondaryFieldWssNames attributes;
All of the rest of fields have BdcField-attributes as well. The attribute contains the name of BDC Entity field, the value of which will be stored in corresponding SharePoint field. But I’ve found an exception. This exception is the hidden field, which is intended to store an encoded identifier. In the given case it’s the Products_ID field. The BDCField-attribute of such fields always contains an invalid value, which equals to the name of the field itself. In our case is BdcField=”Products_ID”, and there is no BDC Entity field with the name Products_ID defined either in DataBase or Application Definition File. And the same situation is with all BusinessDate SharePoint fields I investigated.
Below is a summary schema that exposes what BusinessData column attributes refer to
To work with BusinessData field programmatically we can cast SPField-object to BusinessDataField type defined in the Microsoft.SharePoint.Portal.WebControls namespace:
using Microsoft.SharePoint.Portal.WebControls; ... SPList spList = ... SPField spField = spList.Fields["display name of some field"]; BusinessDataField bizDataField = (BusinessDataField)spField;
To get values of attributes and to get all logically related SharePoint fields we can use the following code:
... string systemInstance = bizDataField.SystemInstanceName; string entity = bizDataField.EntityName; string bdcField = bizDataField.BdcFieldName; // get info about related field, which is to store the encoded identifier of BDC Entity Instance string relatedField = bizDataField.RelatedField; string relatedFieldBDCField = bizDataField.GetProperty("RelatedFieldBDCField"); string relatedFieldWssStaticName = bizDataField.GetProperty("RelatedFieldWssStaticName"); // get info about additional fields, that are to store additional values from BDC Entity Instance string[] secondaryFieldBdcNames = bizDataField.GetSecondaryFieldsNames(); string[] separators = new string[] { ":" }; string secondaryFieldWssNamesVal = bizDataField.GetProperty("SecondaryFieldWssNames"); string[] secondaryFieldWssNames = string.IsNullOrEmpty(secondaryFieldWssNamesVal) ? new string[0] : secondaryFieldWssNamesVal.Split(separators, StringSplitOptions.RemoveEmptyEntries); string secondaryFieldsWssStaticNamesVal = bizDataField.GetProperty("SecondaryFieldsWssStaticNames"); string[] secondaryFieldsWssStaticNames = string.IsNullOrEmpty(secondaryFieldsWssStaticNamesVal) ? new string[0] : secondaryFieldsWssStaticNamesVal.Split(separators, StringSplitOptions.RemoveEmptyEntries); // get all logically related sp fields SPField relatedSPField = spList.Fields.GetFieldByInternalName(relatedField); List<SPField> secondarySPFields = new List<SPField>(secondaryFieldWssNames.Length); foreach (string secondaryFieldName in secondaryFieldWssNames) secondarySPFields.Add(spList.Fields.GetFieldByInternalName(secondaryFieldName));