views:

1288

answers:

2

I am trying to use the stored procedure mapping feature in Entity Framework to perform the insert update and delete functions.

For whatever reason the procedures are not being called. They are correctly mapped, and supposedly all I have to do is call SaveChanges(); in my controller for them to execute.

Using this tutorial as a reference, what would I change about the Edit portion of the controller to have it utilize the stored procedure?

Tutorial Code:

//
// GET: /Home/Edit/5

public ActionResult Edit(int id)
{
    var contactToEdit = (from c in _entities.ContactSet
                         where c.Id == id
                         select c).FirstOrDefault();

    return View(contactToEdit);
}

//
// POST: /Home/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Contact contactToEdit)
{
    if (!ModelState.IsValid)
        return View();

    try
    {
        var originalContact = (from c in _entities.ContactSet
                             where c.Id == contactToEdit.Id
                             select c).FirstOrDefault();
        _entities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetName, contactToEdit);
        _entities.SaveChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}
}

I thought that just by calling SaveChanges(); the update sproc would update so I just removed the call to ApplyPropertyChanges(); like so:

//
// POST: /Home/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Contact contactToEdit)
{
    if (!ModelState.IsValid)
        return View();

    try
    {
        _entities.SaveChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}
}

The update stored procedure doesn't execute though, I have sql profiler running to make sure.

The Programming Entity Framework book tutorials are quoted as saying:

Now that the stored procedures have been mapped, it is not necessary to call them directly in code. Any time SaveChanges is called, Entity Framework will use your mapped stored procedures for any required inserts, updates and deletes.

So, I figure I'm missing something fairly obvious here.

Edit, here is the exact version I'm working with now, the names are different:

//
    // GET: /Candidate/Edit/5

    public ActionResult Edit(int id)
    {
        var candidateToEdit = (from c in Internship.CompleteCandidate
                                where c.UserID == id
                                select c).FirstOrDefault();
        //ViewData["EducationID"] = new SelectList(Internship.education.ToList(), "ID", "Category", candidateToEdit.EducationID);
        return View(candidateToEdit);
    }

    //
    // POST: /Candidate/Edit/5 

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(CompleteCandidate candidateToEdit)
    {
        if (!ModelState.IsValid)
            return View();

        try
        {
            var originalCandidate = (from c in Internship.CompleteCandidate
                                     where c.UserID == candidateToEdit.UserID
                                     select c).FirstOrDefault();
            Internship.ApplyPropertyChanges(originalCandidate.EntityKey.EntitySetName, candidateToEdit);
            Internship.SaveChanges();
            return RedirectToAction("Index");
        }
        catch(Exception e)

        {
            Response.Write("Error: " + e);
            //return View();
            return null;
        }

    }

}
}

It looks almost identical to the tutorial code in structure but throws a NullReference exception at runtime.

A: 

It may be that the update stored procedure is not executing because there are no changes to persist.

Shiraz Bhaiji
+1  A: 

The problem in your example is that the Contact entity received as the parameter isn't associated with the data context. Thus when SaveChanges is called, there is nothing to update. Typically on update, I use the id provided and obtain the original entity from the database and apply the changes to it. When you do that, SaveChanges should invoke your stored procedure on the entity with it's changes.

Put back in the code to retrieve the original entity and apply the changes to it.

tvanfosson
Thanks for the reply, I've updated the code above with the exact version I'm using currently based off of the aforementioned tutorial.When I put the <code>ApplyPropertyChanges();</code> call in I get a NullReference Exception.
Graham
Have you verified that it is, in fact, getting the original entity from the database. FirstOrDefault can return null. You might want to change it to Single() if there can only be one. That would force an exception if either none was found or more than one was found.
tvanfosson
Ah yes, that was the problem. I forgot to pass the ID back so it was returning null. Thank you very much for your help.
Graham
Perhaps I spoke too soon, This suggestion definitely fixes what was wrong with part of it, but the framework still attempts to update the model normally without the stored procedure, as I am getting errors pertaining to null fields that are in the model but, are not arguments in the stored procedure.
Graham
Did you make sure that the stored procedure is mapped to the Update method on the model?
tvanfosson
Yes, I mapped it through the designer view, selecting stored procedure mapping for the entity in question, and assigning the proper stored procedures. The values were all assigned correctly by default.
Graham
Where are the errors being generated? In the validation logic (model) or from SQL?
tvanfosson
It's in the validation logic, that's why I figured it was once again just bypassing the stored procedure. Here is the error:Error: System.Data.ConstraintException: The 'Education' property on 'CompleteCandidate' could not be set to a 'null' value. You must set this property to a non-null value of type 'String'.It's being thrown during ApplyPropertyChanges.
Graham
I'm all out of ideas, I went through the model file today to check and see if everything was in order there, which it seemed to be. To be honest everything is working as expected, the previous error is just because the stored procedure is not being used and it's trying to update the complete model.
Graham
Well, I solved the problem with the error, but the stored procedure still isn't firing, just the normal update method. Thanks for all your help, this one remains a mystery.
Graham