Using Stored Procedures with the ADO.NET Entity Framework
Any proper enterprise environment will have a DBA or a set of DBAs who guard and watch over their databases in the same way that a mother bear watches over her cub. If you inappropriately step between the DBAs and the DBOs, you will get mauled. This means that even with the ADO.NET Entity Framework, they will still want to retain ownership of the database and the objects in it. The ADO.NET Entity Framework allows you to use most of the application code as you did before, but with stored procedures that you or they may have written in the most 'optimal' way.
It'll take a bit of work to get this set up and running, but the effort pays off in the end. You are going to work on using stored procedures with the Article entities on a new form, first starting with a few tasks that you're already familiar with, and then get on to the good stuff.
- Creating the SELECT stored procedure(s)
- Layout of the ArticleView form
- Importing the stored procedure
- Using the stored procedure to get entities in our code
- Another stored procedure, and using it
- Navigation and update code
- Ta-daa!
Obviously, the first step is to create the SELECT stored procedure.
sql Code:
CREATE PROCEDURE GetArticle
@ArticleID INT
AS
BEGIN
SET NOCOUNT ON;
SELECT ArticleID, Title, Body, AuthorID
FROM Article
WHERE ArticleID = @ArticleID
END
GO
Next, you need to import this newly created stored procedure into your EDM. There are two ways to do this: You can regenerate the EDM and import it via the designer, or you can go directly into the XML and edit it there. You will cover the visual method in this tutorial.
- Right-click anywhere in the Entity Designer view and click "Update Model from Database".
- Choose Tables and Stored procedures from the dialog box and click Finish.
- Next, open the Model Browser tab and search for the newly created stored procedure, GetArticle.
- Right-click on it and choose "Create Function Import".
- Set the return type as the Article Entities.


Stored procedures within the EDM are imported as functions, and a function that you import always returns a collection of entities. In future releases, this may change to allow a stored procedure to return a single entity. The result of a stored procedure goes into an ObjectResult<>, similar to how publishContext.Author's return type was ObjectQuery<>.
To see it working, quickly create an ArticleView form. Add a new form to the solution, ArticleView, with these controls.

A little simple for now, but you'll expand it as you go along. In the code,
Top of the class:
vb Code:
Dim publishContext As New PublishingCompanyEntities
Dim articleLIst As List(Of Article)
In the form's load event:
vb Code:
Private Sub ArticleView_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim articleQuery As ObjectResult(Of Article) = publishContext.GetArticle(1)
currentArticle = articleQuery.ToList().First()
PopulateFields()
End Sub
And your old friend:
vb Code:
Private Sub PopulateFields()
If (currentArticle.ArticleID > 0) Then
currentArticle.AuthorReference.Load()
End If
articleIDLabel.Text = currentArticle.ArticleID.ToString()
titleText.Text = currentArticle.Title
bodyText.Text = currentArticle.Body
End Sub
This time, you will notice that you make an explicit call to the GetArticle stored procedure, passing it the ArticleID 1. Run the form and you'll see the first article loaded up. And, it's done using your GetArticle stored procedure. This is good because it means that you can optimize complicated queries if you need to and use stored procedures to help you.
However, in this particular case, when you introduce navigation buttons to the ArticleView form, you'll have to make a new stored procedure call for each button click event (for each ID). Avoid that situation and get all of the Articles in one go instead. Create a GetArticles (plural) stored procedure now.
sql Code:
CREATE PROCEDURE GetArticles
AS
BEGIN
SET NOCOUNT ON;
SELECT ArticleID, Title, Body, AuthorID
FROM Article
END
GO
Import the GetArticles function as shown earlier. You then can use an ObjectResult<Article>, convert it ToList(), and assign it to a List<> object.
Top of the class:
vb Code:
Dim publishContext As New PublishingCompanyEntities
Dim articleLIst As List(Of Article)
Dim currentArticleIndex As Integer
Modify the Form Load event now:
vb Code:
Dim articleQuery As IEnumerable(Of Article) = From ar In publishContext.GetArticles() _
Select ar
articleLIst = articleQuery.ToList()
PopulateFields()
I used a LINQ-to-Entities query instead of a method expression, hoping you would notice the flexibility available to you. You can introduce your filters into the expression and it won't affect the SP call. To illustrate, just as a test:
vb Code:
Dim articleQuery As IEnumerable(Of Article) = From ar In publishContext.GetArticles() _
Where ar.ArticleID > 5 _
Select ar
This will perform a GetArticles SP call and then filter the values returned afterwards. However, you're not interested in filtering it right now, so remove the where clause from the LINQ expression.
Again, there is a PopulateFields method in this form that changes slightly.
vb Code:
Private Sub PopulateFields()
Dim currentArticle As Article = articleLIst(currentArticleIndex)
If (currentArticle.ArticleID > 0) Then
currentArticle.AuthorReference.Load()
End If
articleIDLabel.Text = currentArticle.ArticleID.ToString()
titleText.Text = currentArticle.Title
bodyText.Text = currentArticle.Body
End Sub
Run the form and make sure that the first article still shows.
Now, go back to the form designer and add the navigation buttons. Also, add an "Update" button. a "Clear for new" button. an "Add as new article" button. and a "Delete" button. Same principles as before — you navigate through the List<> for the navigation buttons, update an object's properties in the List<> for the Update button, clear the fields for the "Clear for new" button, and add a new object to the publishContext for "Add as new article".

Based on work done in the past few pages, you must have an idea of what the various buttons will do now, so I'll simply list the code for the buttons here, and then you can get down to the main point of this task—using stored procedures for INSERT, UPDATE, and DELETE.
vb Code:
Private Sub firstButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles firstButton.Click
currentArticleIndex = 0
PopulateFields()
End Sub
Private Sub previousButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles previousButton.Click
If currentArticleIndex > 0 Then
currentArticleIndex -= 1
PopulateFields()
Else
MessageBox.Show("No more articles to display")
End If
End Sub
Private Sub nextButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles nextButton.Click
If currentArticleIndex = articleLIst.Count - 1 Then
MessageBox.Show("No more articles to display")
Else
currentArticleIndex += 1
PopulateFields()
End If
End Sub
Private Sub lastButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lastButton.Click
currentArticleIndex = articleLIst.Count - 1
PopulateFields()
End Sub
Private Sub updateButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles updateButton.Click
Dim currentArticle As Article = articleLIst(currentArticleIndex)
currentArticle.Title = titleText.Text
currentArticle.Body = bodyText.Text
End Sub
Private Sub clearForNewButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles clearForNewButton.Click
articleIDLabel.Text = "-1"
titleText.Text = String.Empty
bodyText.Text = String.Empty
End Sub
Private Sub saveAsNew_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles saveAsNew.Click
Dim newArticle As New Article
newArticle.Title = titleText.Text
newArticle.Body = bodyText.Text
newArticle.ArticleID = -1
publishContext.AddToArticle(newArticle)
articleLIst.Add(newArticle)
currentArticleIndex = articleLIst.Count - 1
PopulateFields()
End Sub
Private Sub deleteButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles deleteButton.Click
Dim currentArticle As Article = articleLIst(currentArticleIndex)
publishContext.DeleteObject(currentArticle)
articleLIst.Remove(currentArticle)
currentArticleIndex = 0
PopulateFields()
End Sub
Private Sub submitToDatabase_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles submitToDatabase.Click
publishContext.SaveChanges()
PopulateFields()
End Sub
Note that although the code looks just like it did in the AuthorView form, when you do map your stored procedures, you won't have to change any of the code.
Next, you can (finally!) map the INSERT, UPDATE, and DELETE stored procedures.