Phil Fresle's Developer Blog

ASP.NET MVC3 Using Code First Entity Framework Without Database Generation

So, when is Code First not Code First?

It is possible, even recommended, to use 'code first' techniques even when you are not generating the database from the code. This is hinted at in the Creating an Entity Framework Data Model for an ASP.NET MVC Application article on Microsoft's asp.net web site. The code first technique will mean that you are using POCO classes for the models which are persistence ignorant. You then use code mappings where necessary to get the correct mappings into the database.

An example to show you how this is achieved...

The first step is to create a SQL database called Bank. I used SQL Express for my test. Then within the database create a table called Customer, you can use the following SQL statement to do this:

CREATE TABLE Customer(
 CustomerID int IDENTITY(1,1) NOT NULL,
 FirstName nvarchar(50) NOT NULL,
 LastName nvarchar(50) NOT NULL,
 Title nvarchar(10) NOT NULL,
 HomePhone nvarchar(20) NULL,
 CONSTRAINT PK_Customer PRIMARY KEY CLUSTERED (CustomerID ASC))

Insert a couple of dummy records so we will be able to test we are correctly connected:

INSERT Customer (FirstName, LastName, Title, HomePhone) VALUES ('John', 'Jones', 'Mr', NULL)
INSERT Customer (FirstName, LastName, Title, HomePhone) VALUES ('Steve', 'Smith', 'Mr', '01023123123')

Now create yourself an MVC3 project called Bank in Visual Studio.

Create a class in the Model folder called Customer.cs and change it's contents to the following:

using System.ComponentModel.DataAnnotations;

namespace Bank.Models
{
    [Table("Customer")]
    public class Customer
    {
        public int CustomerID { get; set; }

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Title { get; set; }
        public string HomePhone { get; set; }
    }
}

We have used a data annotation, i.e. [Table("Customer")], to ensure that our class is going to use the Customer table when it connects to the database. Your company may have conventions for table naming that will not fit in with your class naming conventions, the data annotations allow you to massage the names.

Now create yourself a BankContext.cs class, I put this in a folder called DAL but you can leave it in the Models folder if you desire. This class should have the following contents:

using System.Data.Entity;

namespace Bank.Models
{
    public class BankContext : DbContext
    {
        public DbSet<Customer> Customers { get; set; }
    }
}

You then need to setup a connection to your database in your web.config, by using convention and calling it BankContext there will be no other code to add, for example:

<add name="BankContext" connectionString="Data Source=.\SQLExpress;Initial Catalog=Bank;Integrated Security=True" providerName="System.Data.SqlClient" />

Build the project.

To see the results we need to create a controller and views. Right-click on the Controllers folder and choose to add a new controller. Call the controller 'CustomerController', make it use the template 'Controller with read/write actions and views, using Entity Framework', set the model class to 'Customer (Bank.Models)', and set the data context class to 'BankContext (Bank.Models)'.

Now run the application and once it has started add "/customer" to the end of the url (e.g. http://localhost:21032/customer). You should see the customer index page listing the customers you created earlier in the database.

That is all there is to the basics of using code first techniques with an existing database.

UPDATE:

I've not tried ST4bby as suggested in the feedback section, but Jon Galloway in one of his blogs (Generating EF Code First model classes from an existing database) suggests an easy way of generating the POCOs using a Microsoft tool. I have tried this 'Microsoft way' and it works pretty well, although it doesn't add DataAnnotation attributes to the code so you do need to do that manually after.

UPDATE 2:

Adam Nelson in the comments below suggested that by using the "Entity Framework Power Tools" you get the attributes for free. Thanks for that Adam, I had not used those power tools before, I had used the "EF 4.x DbContext Generator" instead.

I'm not sure I like the idea of having to maintain two files for every entity, the POCO class and the mapping class for the attributes, it would be easy for a maintenance programmer coming along later to overlook the extra file.

That said, the generated code does look clean, and after it is generated you could always use it to remind you of all the DataAnnotations needed before removing the mapping file.

UPDATE 3:

Having asked the question at the ADO.Net Team Blog for the EF Power Tools it appears that there are plans to offer the option to use DataAnnotations rather than a mapping file. Furthermore, there are also plans to include the ability to select which database tables are processed rather than processing the entire database. It is already a useful tool worth picking up, but when these two amendments are in place it will be incredibly useful.

 



Extract the first N words from a string with C#

This code will return the first 5 words, change the number in the regular expression as needed:

string testString = "The quick brown fox jumps over the lazy dog."
string firstWords = Regex.Match(testString, @"^(\w+\b.*?){5}").ToString();



Streaming Files for more Secure Downloads in ASP.NET

If you just have a link to a file on your web site then you maybe leaving yourself open to other sites linking to the same files thereby giving their users the benefit of content without any hit on their bandwidth. It will also give clues to your site structure that can only be of benefit to anyone wishing to compromise your site's security.

One workaround to this is to stream the files to your users using a FileStream and the Response object. Here is some C# code that will do that job for you:

/// <summary>
/// Write a secure file out to the response stream. Writes piece-meal in 4K chunks to
/// help prevent problems with large files.
/// <example>
/// <code>WriteFileToResponse(@"secureFolder/mysecurefile.pdf", @"test.pdf",
/// @"application/pdf");</code>
/// </example>
/// <example>
/// <code>WriteFileToResponse(@"secureFolder/mysecurefile.pdf", @"test.pdf");</code>
/// </example>
/// </summary>
/// <param name="secureFilePath">>Relative path to the file to download from our
/// secure folder</param>
/// <param name="userFilename">Name of file the user will see</param>
/// <param name="contentType">MIME type of the file for Response.ContentType,
/// "application/octet-stream" is a good catch all. A list of other possible values
/// can be found at http://msdn.microsoft.com/en-us/library/ms775147.aspx </param>

public void WriteFileToResponse(string secureFilePath, string userFilename,
    string contentType = @"application/octet-stream")
{
    // Process the file in 4K blocks
    byte[] dataBlock = new byte[0x1000];
    long fileSize;
    int bytesRead;
    long totalBytesRead = 0;

    using (var fs = new FileStream(Server.MapPath(secureFilePath),
        FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        fileSize = fs.Length;

        Response.Clear();
        Response.ContentType = contentType;
        Response.AddHeader("Content-Disposition",
            "attachment; filename=" + userFilename);

        while (totalBytesRead < fileSize)
        {
            if (!Response.IsClientConnected)
                break;

            bytesRead = fs.Read(dataBlock, 0, dataBlock.Length);
            Response.OutputStream.Write(dataBlock, 0, bytesRead);
            Response.Flush();
            totalBytesRead += bytesRead;
        }

        Response.Close();
    }
}



New article: Using the Entity Framework and the ObjectDataSource: Custom Paging

A new article is up that extends the Microsoft tutorial on using the Entity Framework with the ObjectDataSource to include custom paging. It can be found by following this link: Using the Entity Framework and the ObjectDataSource: Custom Paging.

 



Using data from Entity Framework 2 to fill a 2010 local SSRS report in ASP.NET

When you design a local SSRS report you are forced to use a Dataset as part of the design process, however, this does not mean that you have to keep the dependancy on a dataset or even retain the dataset in your project once you have completed the design.

Simply use code similar to the C# example that follows to clear the dataset the report is expecting to use and specify the new collection of data it is to use instead:

var context = new AWEntities();

var vendors = from v in context.Vendors
                    where v.CreditRating != 1
                    select v;

ReportViewer1.LocalReport.DataSources.Clear();
ReportDataSource datasource = new ReportDataSource("VendorList", vendors);
ReportViewer1.LocalReport.DataSources.Add(datasource);
ReportViewer1.LocalReport.Refresh();


You can use the same method to substitute data from Linq to SQL or ADO.NET if they are your DAL technology of choice.

 



New article: Setting SSRS Report Parameters from ASP.NET C# Code

A new article is up that discusses how to pass values to SSRS reports at runtime from web forms. Please find it here.



New article regarding the Back Button displaying pages after Logout in ASP.NET

A new article is up that discusses a workaround to the problem of the user pressing the Back button in their browser after they have logged out and an application page being displayed that should require authentication first. Please find it here.



New article on preventing multiple concurrent use in asp.net

I have posted up an article today entitled Preventing a User From Having Multiple Concurrent Sessions