Dave Paquette

Caffeine Driven Development

Introducing Entity Framework Seeder

June 2, 2014

In a previous blog post, we discussed a fairly straight forward mechanism for seeding an Entity Framework database from a CSV file using the CsvHelper package.

Since then, I have created a package that simplifies this process even further.

Install-Package EntityFramework.Seeder.EF6

Seeding Simple Entities

Assume we are working with a very a very simple lookup entity like a  Country:

public class Country
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
}
public class Country
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
}

 

Create a CSV file with a Code and Name column. We do not need an ID column because the ID will be auto-generated by the database.

Code,Name
CA,Canada
USA,United States
etc...
Code,Name
CA,Canada
USA,United States
etc...

 

Include the CSV file as an embedded resource in your C# project. In your seed method call the SeedFromResource extension method on the Countries DbSet, specifying the name of the embedded resource and the property that uniquely identifies a Country. The unique property is required to ensure that the same Country is not added to the database a second time if the Country already exists in the database.

context.Countries.SeedFromResource("MyProject.countries.csv", c => c.Code);
context.Countries.SeedFromResource("MyProject.countries.csv", c => c.Code);

Seeding Entities with Relationships

Let’s extend the model to include the concept of Provinces / States.

public class Country
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
    public virtual IList<ProvinceState> ProvinceStates { get; set; }
}
 
public class ProvinceState
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
 
    public virtual Country Country { get; set; }
}
public class Country
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
    public virtual IList<ProvinceState> ProvinceStates { get; set; }
}

public class ProvinceState
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }

    public virtual Country Country { get; set; }
}

 

Now when we are loading Provinces / States we need to connect them with correct Country. To do this, define a CSV file with a Code and Name column and an additional CountryCode column. The CountryCode column will be used to find the correct Country for the Province / State.

CountryCode,Code,Name
CA,SK,Saskatchewan
CA,AB,Alberta
US,AZ,Arizona
US,AR,Arkansas
US,CA,California
etc...
CountryCode,Code,Name
CA,SK,Saskatchewan
CA,AB,Alberta
US,AZ,Arizona
US,AR,Arkansas
US,CA,California
etc...

 

When Seeding the provinces, specify an additional CsvColumnMapping parameter. This parameter is used to tell Entity Framework Seeder how to find the correct Country based on the CountryCode column.

context.Countries.SeedFromResource("MyProject.countries.csv", c => c.Code);
context.SaveChanges();
context.ProvinceStates.SeedFromResource("MyProject.provincestates.csv", p => p.Code,
        new CsvColumnMapping<ProvinceState>("CountryCode", (state, countryCode) =>
            {
                state.Country = context.Countries.Single(c => c.Code == countryCode);
            })
         );   
context.Countries.SeedFromResource("MyProject.countries.csv", c => c.Code);
context.SaveChanges();
context.ProvinceStates.SeedFromResource("MyProject.provincestates.csv", p => p.Code,
        new CsvColumnMapping<ProvinceState>("CountryCode", (state, countryCode) =>
            {
                state.Country = context.Countries.Single(c => c.Code == countryCode);
            })
         );   

 

Provide Feedback / Contribute

You can find Entity Framework Seeder on GitHub and on Nuget.

CSS Validation with Visual Studio Web Essentials

May 27, 2014

This is a cross post of an article over on the Canadian Developer Connection.

I like when my IDE tells me I’m doing something wrong. I find it mush less embarrassing than when a co-worker or customer tells me I’m doing something wrong. That’s why I love Visual Studio and the Web Essentials extension. Web Essentials has some great CSS Validation features that can help to point out common mistakes. These features also apply to LESS.

There are a number of useful validation rules and best practices that Web Essentials will check. In this post, we will explore those that I found particularly useful and taught me a little more about CSS.

Vendor Prefixes

Vendor prefixes are used by browser vendors to add new CSS features that may not yet been finalized in the official CSS specs. Each browser has it’s own prefix for CSS properties. Chrome and Safari use –webkit, Firefox uses –moz and Internet Explorer uses  -ms.

For example, if you want to use CSS Column layouts, you will need to specify vendor prefixes as follows:

-moz-column-count: 2;
-webkit-column-count: 2;
column-count: 2;

Unless you follow the CSS specs and individual browser implementations closely, it can be very difficult to know when you need to use vendor prefixes. This is where Web Essentials can help.  If I specify the a column-count property without the required browser prefixes, it will be flagged as a warning. Web Essentials shows warnings by underlining items in the CSS editor and by listing them in the Error List (View –> Error List).

image

When I select the Add missing vendor specifics smart tag, Web Essentials will add the required prefixes for me.

image

Now, the CSS specs and browser implementations are always changing. While the –moz and –webkit prefixes are required today, they may not be required tomorrow. A good example of this is border-radius. In the past, vendor prefixes were required to support border-radius. Today, border-radius is officially part of the CSS specs and is supported by all major browsers. Web Essentials will point out that these vendor specifics are not longer necessary.

image

For Web Essentials to warn you of deprecated vendor specifics, you may need to set the Disallow unrecognized vendor-specifics setting to True in the Web Essentials settings. You can find Web Essentials settings under Tools –> Options. In the options dialog, select Web Essentials –> CSS.

image

Choosing your Browsers

Maybe your website is deployed internally and you have no need to support a particular browser. You can tell Web Essentials what browsers you are targeting by right clicking in any CSS or LESS file and selecting Web Essentials –> Select Browsers.

image

In this case, I un-checked FireFox. When I click Ok, Web Essentials adds a file ‘WE-browsers.xml’ to my solution. If you include this file in source control, the settings will be shared across all developers on your team.

image

Now, when I ask Web Essentials to add missing vendor specifics, the –moz prefix is not included.

image

Duplicate Properties and Selectors

As a CSS file grows over time, it can be common for a developer to accidently define the same selector more than once in a CSS file. Web Essentials will scan a the file and warn you if this happens. It will also check to make sure that you have not accidently defined the same property more than once within a selector.

Summary

We only scratched the surface of the validation rules that are available in Web Essentials. If you are interested in a complete list, you can read more on the Web Essentials site.

If you are interested in the implementation details, you can view the source code on GitHub. Remember, Web Essentials is an open source project, so you can contribute too!