MVC and Linq2Sql – Getting your data in and out of the model

MVC supports a lot of ‘good practice’ such as dependency injection, unit testing and mocking. These things all have their place, but for some small ad-hoc coding all of that isnt’s needed. Additionaly, people crossing over to MVC get confornted in most books and documentation with a ton of good advice that at best obfuscates what is going on in the core. This post is a part of a series of posts for people crossing over from webforms to mvc to give a few starting concepts.

Linq2Sql with MVC

While arguably replaced by the entity framework, Linq2Sql is still a much used technology which largely functions the same from a coding perspective. Here is how to get a linq2sql object into your view, and out of it again after updating.

Getting data out

Consider the following code; it will query a series of linq objects and feed them into your view.

public ActionResult Index()
{
    string db = Properties.Settings.Default.database;
    var dc = new Models.BulkDataClassesDataContext(db);
    var magazijnSet = dc.asterix_Inslag_Magazijnen_Bulk.Select(x => x).ToList();
    return View(magazijnSet);
}

Which means we will need to tell the view it is to use a mreferenced model, and where to find it. Like this:

@using MVCBulkRebooker.Models
@model  IEnumerable<MVCBulkRebooker.Models.asterix_Inslag_Magazijnen_Bulk>

Now we can use the model in a loop, and display or process the data. For example looping through it to create a table:

@foreach (asterix_Inslag_Magazijnen_Bulk bulkItem in (IEnumerable<asterix_Inslag_Magazijnen_Bulk>) ViewData.Model) {
<tr>
    <td>
        @bulkItem.somefield
    </td>

When talking about a single record, things do not realy change, now we will pass a single object (.Single()) to the view, and declare no longer as IENumerable:

@using MVCBulkRebooker.Models
@model MVCBulkRebooker.Models.asterix_Inslag_Magazijnen_Bulk

Getting data back in

So, how do we get data back in ? In the winforms/webforms world this is easy, we declare a datacontext for the class, and reuse it on saving. The linq object is still attached to this datacontext, so all we need to do is call SubmitChanges(). Not so in MVC.

We are now dealing with a stateless system, so we will need to reaquire the object and update it. Luckily we do not need to manualy write all the plumping, and MVC offers a decente method to to this: TryUpdateModel.

When calling TryUpdateModel the system will attempt to update a linq item you pass to it with the data in the model. It will only update fields that are in your model. Additional fields are left unchanged.

var dc = new Models.BulkDataClassesDataContext(Properties.Settings.Default.database);
var item = dc.asterix_Inslag_Magazijnen_Bulk.Where(x => x.id == bulkItem.id).Select(x => x).Single();
if (ModelState.IsValid && TryUpdateModel(item)) {
	dc.SubmitChanges();   
}

Important is to make sure your key field is always present in the model data returning form the view, or there will be no update taking place. To archive that you will need something along this line for your key field:

@Html.HiddenFor(x => x.id)