EF Code First and WPF with the Chinook database. Part 1b – the provider

I like to isolate my data access code to a single point so that my client does not have to worry about creating contexts or anything of the sort.  This makes it simpler to change the way the data is delivered to the client as it is abstracted away.

In thinking about what methods I would need for this I discovered that for the first phase I would only need two:

  • GetArtists() – Returns all artists.
  • SearchArtists(string searchTerm) – Searches for artists and returns any matches.

I don’t need any methods at the moment to fetch albums or tracks because I have virtual lazy loading properties set up to deal with them.  I will be adding more methods to this provider as the series grows (such as adding, deleting…etc).

Lets go ahead and test those lazy properties:

class Program
{
    static Chinook db = new Chinook();

    static void Main(string[] args)
    {
        // Using ToList() executes the command so the datareader is closed.
        var artists = db.Artist.ToList();
        foreach (var a in artists)
        {
            Console.WriteLine(a.Name);
            PrintAlbums(a.Albums);
        }

        Console.ReadLine();
    }

    static void PrintAlbums(ICollection<Album> albums)
    {
        foreach (var a in albums)
        {
            Console.WriteLine("\t" + a.Title);
            PrintTracks(a.Tracks);
        }
    }

    static void PrintTracks(ICollection<Track> tracks)
    {
        foreach (var t in tracks)
        {
            Console.WriteLine("\t\t" + t.Name);
        }
    }
}

image

Whoops – seems we have an invalid column name “ArtistArtistId”.

This is due to the way Code First decides on what the foreign key columns are called if we don’t explicitly include them – the default is “{TypeName}{TypeName}Id” which we obviously don’t have in the database.

We need to add the foreign key properties to our objects so EF picks up the correct names (this needs to be done for both Album and Track – note the new ArtistId and AlbumId respectively):

public class Album
{
    public int AlbumId { get; set; }

    public string Title { get; set; }

    public int ArtistId { get; set; }

    public virtual Artist Artist { get; set; }

    public virtual ICollection<Track> Tracks { get; set; }
}

public class Track
{
    public int TrackId { get; set; }

    public string Name { get; set; }

    public int AlbumId { get; set; }

    public virtual Album Album { get; set; }

    public string Composer { get; set; }
}

We can now run our demo and get a correct output:

image

We are now in a position to implement our simple data provider.

I am going to put the data provider behind an interface to allow for easy extension and dependency injection should we want to go that way.

public interface IDataProvider
{
    List<Artist> GetArtists();

    List<Artist> SearchArtists(string searchTerm);
}

This is then implemented as follows for the code first model:

public class EFCodeFirstDataProvider : IDataProvider
{
    private Chinook db = new Chinook();

    public List<Artist> GetArtists()
    {
        return this.db.Artist.ToList();
    }

    public List<Artist> SearchArtists(string searchTerm)
    {
        return this.db.Artist.Where(a => a.Name.Contains(searchTerm)).ToList();
    }
}

We have a private instance of the Chinook data context that controls all of the fetching of data.  When the Artist requests its albums then this context is used.  This is the same with the tracks.

The intention here is to allow the client to call simple methods to interact with the data and we are able to swap out for another provider if we so wish easily.

The only thing we now need to change is the little test app so that it uses the new data provider (we will hard code the type here but will be using dependency injection in our WPF app).

static IDataProvider dp = new EFCodeFirstDataProvider();

static void Main(string[] args)
{
    var artists = dp.GetArtists();
    foreach (var a in artists)
    {
        Console.WriteLine(a.Name);
        PrintAlbums(a.Albums);
    }

    Console.ReadLine();
}

And that’s all there is to it – we now have a separate data provider to work with our entity framework objects.

The next part of this series (1c) is going to involve writing unit tests for the data provider.  This is easier said than done and involves much mocking of the EF classes.

About these ads

About Leom Burke
Working for a healthcare company in the UK with a focus on C#/WPF/WCF/EF. Personally I also enjoy working with ASP.NET (MVC), ruby and investigating best practice using methods like TDD and bettering the quality of code. This is personal blog and as such has no relationship to the thoughts, views and feelings of the company I happen to be working for.

One Response to EF Code First and WPF with the Chinook database. Part 1b – the provider

  1. Pingback: EF Code First and WPF with the Chinook database. Part 1c – the unit tests « Random Ramblings

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: