UPDATE: The code for the first three posts in this series is now on GitHub.
In Part 1 and Part 2 we skipped the database part of the HOL to concentrate on web deployment. Now it's time to complete the lab by hooking up SQL Azure with Entity Framework. The main difference in doing this with F# is that we'll need to write our own EF code, as the Visual Studio Controller Wizard doesn't know how to do it for us in F#. But our project template has built in EF support, and F#'s concise syntax reduces what we need to write.
Our first step is to use EF to build a Contacts repository. I'd like the file for this code to go in a project folder named Repositories, but Visual Studio Solution Explorer can't create folders in F# projects. So we'll cheat a little. First we go to the File - New - File menu and create an F# source file (don't add it in Solution Explorer). We save this file with the name ContactsRepository.fs in a newly-created folder called \Repositories under the F# project.
Now we close the solution from the Visual Studio File menu, then open the GuestBookWebAppSpa.fsproj by selecting it from File -- Open -- File menu. Interestingly, Visual Studio opens an .fsproject file with the text editor instead of Solution Explorer.
We find the line
<Compile Include="Models\Contact.fs" />
and immediately afterward add the line
<Compile Include="Repositories\ContactsRepository.fs" />
F#'s compiler notoriously relies on us to figure out the file compilation sequence, which must be in order of increasing dependence. Happily, the presence of subfolders doesn't affect the compilation sequence.
Now we can re-open the solution in Visual Studio, and we see our new file in its folder in Solution Explorer.
Next the F# project needs a reference to Entity Framework. Since the project template already put the EF assembly in the \packages folder, we can add the reference by browsing to it.
Finally it's time to write some code! We add the following to ContactsRepository.fs.
We define two classes here. The first is a subclass of EF's DbContext that is specialized to work with our Contact entity type. It will look for its configuration settings under the name "ContactEntities". The other class is a start at the Repository pattern, though this example is so simple that it just provides a little sugar.
Then we replace everything in ContactsController.fs.
Those new to F# may need a moment to see how the private ContactsRepository gets injected through the constructor. This is typical of F#'s tight syntax in OO class definitions.
Next, we need to add a few EF attributes to the Contact class in our \Models folder. Since the project template doesn't force us to use EF, it did not automatically decorate the class with these attributes. At a minimum, the class needs a property with the KeyAttribute, and we'll add one that auto-generates a guid for it. We'll also add some RequiredAttributes.
The last place to add code is the C# project's web.config file. We go to the <connectionStrings> section, make a copy of the entry already there, and alter the copy as follows:
- Change the name attribute to "ContactEntities"
- If we don't want to use SQL Server Express, we change the file extension at the end of the connection string from ".mdf" to ".sdf".
Here is an example.
<add name="ContactEntities" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-ContactsWebSpa-20130527120316;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-ContactsWebSpa-20130527120316.sdf" />
Once these changes are made and the solution compiles, we can run the app. Entity Framework will create the database, and we can save new Contacts in it.
At this point it's a good idea to check our changes into source control. We set up our solution to use git in Part 2, but if we're using Visual Studio Tools for Git we have a small issue because we created a couple files behind Visual Studio's back. If we go down to the Untracked Files node in Team Explorer we see ContactsRepository.fs, and we definitely need that in the repository. On the other hand, there's no reason to repo the database file, so we'll leave it untracked.
All we need to do is drag the Repositories folder with the mouse from the Untracked Files node and drop it in the Included Changes node under the ContactsWebAppSpa folder. Now we can commit our changes.
We're now ready to go back to the lab manual and finish the HOL. We'll see that our use of F# makes no difference from here on out. Turning back to Exercise 1 we do Task 2, which we previously skipped, to create a SQL Azure server. Then we redo Task 3, this time setting up the database connection string. We can follow the lab manual's instructions exactly, and the app should work perfectly with our new Azure database. Then we redo Exercise 2, Task 3, again following the manual's instructions for setting our SQL Azure connection string, and again the site should work perfectly with the database.
We have thus completed the first WATK HOL writing all .NET code in F#. In Part 1 we saw that publishing web sites to Azure with Visual Studio was no different than if we'd written the code in C#. In Part 2 we saw that publishing with git was a bit trickier, but you don't expect git to be easy, do you? In Part 3 we had to write Entity Framework code instead of letting Visual Studio generate it, but F# helped us make the code concise. So there seems to be no reason why a programmer can't build and deploy Azure web sites as well with F# as with C#.