You can author BCS
external content types using SharePoint designer. These external
content types can be used in various scenarios as you just saw, but if
you truly want to go beyond those limits, BCS in SharePoint 2010 also
has a very compelling Visual Studio story. Let's begin by writing and
using simple BCS external content type in Visual Studio.
Start Visual Studio 2010 and create a new project
based on the "Business Data Connectivity Model" project template, and
call it "BDCDemo". This project is going to generate a collection of
BCS external content types. An out of the box entity is created for
you, which gives you an identifier and two methods. This entity
represents the bare minimum definition that you need to create to be
able to create an external list from. Once you have created a project
based on this project template you will notice three different sections
in your Visual Studio project. On the left you will see a graphical
representation of your entity. If you have multiple entities with
associations between them they will appeal over here as well. On the
right under BDC explorer you will see the definition of the model with
the different entities sorted as a tree view. This can be seen in Figure 1.
And at the very bottom you should see a pane called
BDC method details. In this pane you will see the various methods and
other details that help you design this entity. You will probably end
up spending a lot of time in this pane. You would also note that all
these three panes are connected with each other. Editing one will
reflect the changes in the other two panes. Behind the scenes you're
really editing an xml file. The xml file in this case is the
BdcModel1.bdcm file. You could edit the xml file directly as well, but
this is a huge improvement over SharePoint 2007, where you didn't have
good tools to edit your xml file that defined the application
definition. So chances are that I won't be editing the xml file
manually too much. Also behind each entity there's a code behind that
is being maintained for you. To view the code-behind select the Entity1
and press the F7 button. You would note in the code-behind that there
are methods created for you for both read item and read list. The
ReadItem is the equivalent of the specific finder method; it returns a
single instance of an entity. ReadList on the other hand returns a
number of instances of the entity. The generated code can be seen in Listing 1.
Example 1. The out of the box code for ReadList
public static IEnumerable<Entity1> ReadList() { // TODO: This is just a sample. Replace this simple sample with valid code. Entity1[] entityList = newEntity1[1]; Entity1 entity1 = newEntity1(); entity1.Identifier1 = "0"; entity1.Message = "Hello World"; entityList[0] = entity1; return entityList; }
|
As you can see from Listing 1
I'm returning an IEnumerable<Entity1>. Also the out of the box
code is creating a single instance of the entity, and stuffing it into
the return value. Thus if you were to deploy this external content type
and create an external list based on that, that external list will
contain a single list item, with two columns, named Identifier1, and
Message, with values 0, and "Hello World" as shown in Figure 2.
Also note that by pressing F5 on your project to run
your project, Visual Studio will package up the BDC entity as a .wsp,
deploy it, and since this is a farm solution modify the web.config to
enable debugging, and even allow you to step through breakpoints in
your code behind.
Thus now if you wanted to offer something more
powerful, example entity instances been generated on the fly based on
some intelligent logic, you would simply have to modify that
code-behind! That's all.
And when I say, modify the code-behind that really involves two steps,
The
first step is to define the structure of Entity1, maybe perhaps give
Entity1 a decent meaningful name. This is done by describing something
called as a TypeDescriptor.
The second step obviously is to define the details of the ReadList method, so that it fills your custom entity structure.
So turning my HelloWorld example into a more real
world example, let's say that I intend to create an external content
type, which when dropped into an external list, will always return the
calendar for the current month. This calendar will have three columns:
the identifier, the day, and the date. So let's make this happen!
As I mentioned the first step is to define the
structure of Entity1, which I am going to rename to "MonthDay". Also, I
will rename Identifier1 to DayNumber, and in the properties, I will
change its type to System.Int32. At this point, my graphical view of my
BDC Model looks like as shown in Figure 3.
So far so good, now, click on the ReadItem method.
In the bottom pane, you would see the Method Details. Look for the
ReadItem method, and see what parameters it accepts, and what
parameters it returns! It seems to accept "id", direction "In", and its
Type Descriptor to be "Identifier1". Well that's obviously incorrect!
First of all, what is a Type Descriptor? As the name
suggests, it describes a type! A type that is independent of WCF, SQL
Server, or .NET connector data types - it is a type that is defined
purely in BCS terms, so it is reusable across all those sources. Thus
instead of Identifier1, change the input parameter to DayNumber. Also
ensure that its data type is now a System.Int32.
Now look at the second parameter called
"returnParameter". Its direction is "Return", but its Type Descriptor
is "Entity1". Again this is incorrect, and you need to ensure that the
return type is represented by a Type Descriptor that represents the
structure of the information you wish to return. Thus go ahead and set
up TypeDescriptor as your return parameter as shown in Figure 4.
In this figure, Date is of type System.DateTime, Day is System.String, and DayNumber is System.Int32.
This basically sets up the ReadItem method
structure, you still need to provide details of the code-behind! I'll
get to that in a minute, but first let's also set up the structure for
ReadList. For ReadList, create a return type descriptor called
"MontyDayEntries", and copy paste the "MonthDayEntry" type descriptor
under it. Your BDC Explorer should look like as shown in Figure 5.
Finally, you need to create a class that represents
the structure of MonthDayEntry. I am going to rename Entity1.cs, to
MonthDayEntry.cs, and put code in as shown in Listing 1.
Example 1. Structure for MonthDayEntry
public partial class MonthDayEntry { public int DayNumber { get; set; } public string Day { get; set; } public DateTime Date { get; set; } }
|
Great, now all that's left is to populate the
code-behind's of ReadItem and ReadList methods, and you will be ready
to use this entity within SharePoint. You can find the new code-behind
in Listing 2.
Example 2. Your custom ReadList and ReadItem methods.
public class MonthDayService { public static MonthDayEntry ReadItem(int id) { MonthDayEntry oneDay = newMonthDayEntry(); DateTime oneMonthFromNow = DateTime.Now.AddMonths(1) ; int maxDaysInCurrentMonth = (newDateTime(oneMonthFromNow.Year, oneMonthFromNow.Month, 1)).AddDays(-1).Day; if (id > maxDaysInCurrentMonth) id = maxDaysInCurrentMonth; oneDay.Date = newDateTime(DateTime.Now.Year, DateTime.Now.Month, id); return oneDay; }
public static IEnumerable<MonthDayEntry> ReadList() { int currentMonth = DateTime.Now.Month; int currentYear = DateTime.Now.Year; DateTime oneMonthFromNow = DateTime.Now.AddMonths(1) ; int maxDaysInCurrentMonth = (new DateTime(oneMonthFromNow.Year, oneMonthFromNow.Month, 1)).AddDays(-1).Day; MonthDayEntry[] entityList = newMonthDayEntry[maxDaysInCurrentMonth];
for (int i = 1; i <= maxDaysInCurrentMonth ; i++) { MonthDayEntry oneDay = newMonthDayEntry(); oneDay.Date = newDateTime(currentYear, currentMonth, i); oneDay.Day = oneDay.Date.DayOfWeek.ToString(); oneDay.DayNumber = i; entityList[i - 1] = oneDay; } return entityList; } }
|
Now, go ahead and build and deploy your project.
Then, create an External List called "Days", and use the above created
external content type as the source external content type for this
list. Also, through central administration, give yourself access to
this BCS external content type. You should see the list created as
shown in Figure 6.
You would also note that since you have not created
all the Methods on this external content type, the user interface is
appropriately trimmed. You would note that the "New Item", "Edit Item",
and "Delete Item" buttons are grayed out.
At this time, for your own practice. go ahead and
create some other interesting external content types using Visual
Studio 2010. If there is a sample challenge for you, why don't you
create an external content type that returns NorthWind customers that
were returned using plain ADO.NET. Once you have written and deployed
this external content type, create a list just like before, and try to
connect that list to Outlook! SharePoint will give you an error as
shown in Figure 7.
This error is to be expected, and this is
one of those errors that gives you a good description of exactly what
you need to do, to get rid of this error.