Thursday, 29 March 2012

SqlServer CE and EF 4.1 DB first.... its been emotional

Just wanting to spread the love here as there has been swearing, bouts of nervous laughter and stroking a firearm whilst muttering "the day of reckoning is upon us" but I have finally got a unit testing environment working with SQLServer CE, Entity Framework 4 and a DB first model.

Would just like to mention Nick Mayne who introduced me to SQLServer CE.  check his blog out http://themayneissue.com/ he also works on the great orchard CMS project for MVC which is definitely worth taking a look at http://www.orchardproject.net/

If you're interested, read on ....

We are using the northwind database and the POCO templates for the entity framework so if you haven't already done so, you will need to download the northwind samples and the POCO templates which can be found at :

http://visualstudiogallery.msdn.microsoft.com/23df0450-5677-4926-96cc-173d02752313

Then open Visual Studio.

Create the data class library

In your solution add a new class library project.  Then add a new a new item and select Entity Data Model like so:


This then prompts you to generate from db or empty, i'm choosing empty..



I now have the following solution structure:


Now select your Edmx and right click in the pane and select Update Model From Database


and then set the connection string and add a couple of tables.  My edmx now looks like this (i've added the northwind-employees table)


To add the POCO generation, right click in the edmx white pane and select "Add Code Generation Item" and select the POCO template:



This then creates your context and tt files required for generating the entities code.  Save you EDMX and close then select the model.context.tt and right click and select "Run Custom Tool" as you can see I now have the employees entities generated in the project :


Ok, so now we have a model to test ! next lets use SQL SERVER CE to test it.  What we are essentially going to do wrap the object context in a db context in order for us to be able to test our repositories.  So lets get started.

Create a new unit test project, you have guessed by now I am using the new hideous VS 11 IDE...


We then need to add 3 packages, EntityFramework, the SQLServer CE installation and the entity framework package.  Firstly, with your new test project selected, select Manage NuGet Packages and select the online option and search for entity framework.


Then hit install, this will add the libraries to the test project, next select manage nuget packages again and search for SqlServerCompact and install:



Finally, you will need the entity framework sql package:


And we are good to go.  

First we need to add a new class that effectively "Wraps" the object context.  So I will add a new class called ObjectContextWrapper.cs

We start by fleshing out the code and accepting the object context in the constructor along with a dbconnection (you will need to add references to your data project, system.data, system.data.common and entity) 

We basically wrap the context and the entities available in the normal object context.  We override CreateDatabaseScript and pass this to the object context and then provide the same method in the object context to get the employees.  Our code for the wrapper looks like so:

    public class ObjectContextWrapper : DbContext
    {
        Model1Container _objectContext;

        public ObjectContextWrapper(Model1Container objectContext, DbConnection connection) : base(connection, true)
        {
            _objectContext = objectContext;
            _objectContext.ContextOptions.LazyLoadingEnabled = false;
        }

        public string CreateDatabaseScript()
        {
            return _objectContext.CreateDatabaseScript();
        }

        public IDbSet<Employee> Employees
        {
            get { return this.Set<Employee>(); }
        }
    }


Finally, you add the unit test, sorry I have put all the setup in the test, this would ideally go in TestInitialize 

        [TestMethod]
        public void TestMethod1()
        {
            MetadataWorkspace workspace = new MetadataWorkspace(new string[] { "res://*/" }, new Assembly[] { Assembly.GetAssembly(typeof(Model1Container)) });

            Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
            //Database.SetInitializer(new  ObjectContextInitialiser  ());

            DbConnection connection = new      SqlCeConnectionFactory("System.Data.SqlServerCe.4.0").CreateConnection("SqlServerCEDB");
            EntityConnection entityConnection = new EntityConnection(workspace, connection);


            ObjectContextWrapper context = new ObjectContextWrapper(
                new Model1Container(entityConnection), connection
            );

            Employee emp = new Employee() { EmployeeID = 1, FirstName = "Andrew", LastName = "Smith" };
            context.Employees.Add(emp);
            context.SaveChanges();

            Employee newemp = (
                from d in context.Employees
                where d.EmployeeID == 1
                select d
            ).Single();


            Assert.AreEqual(newemp.EmployeeID, emp.EmployeeID);

            Database.Delete(connection);
        }



Bit of explanation needed here.  Firstly, I tried a few different ways to work with the context but wanted to pass our object context an entityconnection as it seems the easiest thing to do.  

To create an EntityConnection, we need a db connection and a metadata workspace, so we create the metadataworkspace using the assembly where the object context can be found and a simple resource string.

We call the SQLCE connection factory to get a dbconnection and then create the Entity connection using these two items.

we pass our wrapper the connection and the model container (ok I pass the connection twice, we can tidy that up I guess but its late) 

We then create an employee and add it to tour wrapper class (remember we have an employees property)

we  then save the changes.

to test, we get the employee back and perform an assert

if you comment out the Database.Delete and check the test bin directory, you will find the sdf database file. and hey presto ! unit test with SQLServerCE

Initialising with some data

We can initialise the data with the setInitializer method on the database object, we first write the initializer:

  public class ObjectContextInitialiser : DropCreateDatabaseAlways<ObjectContextWrapper>
    {
        ObjectContextWrapper _objectContextWrapper;

        protected override void Seed(ObjectContextWrapper context)
        {
            _objectContextWrapper = context;

            var Employees = new List<Employee> {
                new Employee() { EmployeeID = 500, FirstName = "test", LastName="name" }
            };

            Employees.ForEach(d => _objectContextWrapper.Employees.Add(d));
        }

        public IEnumerable<Employee> Employees
        {
            get
            {
                return _objectContextWrapper.Employees;
            }
        }
    }


This simply creates a seed method to populate the context with an employee and a convienience method to get the employees from the context so we can compare in the unittest.

We can then uncomment the line :

//Database.SetInitializer(new  ObjectContextInitialiser  ());

and the db is populated.

If you find this useful, drop us a line 














Friday, 24 February 2012

MVC and IEnumerable Razor woes

Quick one we come across and I have come across before so should be beaten with a large stick for forgetting it. If you have an IEnumerable model type i.e. your declaration looks like :

@model IEnumerable<Spatula>

then you try and loop through this:

@foreach (Spatula s in Model) 

you get an error regarding the model not being the correct type (cannot get IEnumerator from object type)
remember to cast the Model to an IEnumerable like so :

@foreach (Spatula s in (Model as IEnumerable<Spatula>)) 


Presto.  just a little thing if you forget.



Thursday, 16 February 2012

VS2010 cannot add reference

If you have seen the all too infamous "Cannot add reference" in visual studio and gone down the usual route of making sure you have added the project to the solution, added necessary files, shaking the P.C. and performing a druid ceremony and it still doesn't work, I may have another one for you that I encountered today whilst at work.

At our place, we have a job service solution which is a windows service and a large number of projects which are the individual jobs.  All the settings for configuration are naturally on the service solution e.g. we have a configuration in the job service solution of dev, preprod, release, SIT and UAT.  The job service solution has all the projects for each job and the tests so its pretty large.

We also have solutions which have groups of jobs so we can work on the smaller projects and tests without having to recompile the whole service unless we are deploying the whole thing.  We did a bit of a tidy up so the service solution had the configrations but our other solutions only had debug and release as we didn't need them.

I didn't check the jobservice solutions selected configuration and tried to add an exisitng project and received the all too familiar "cannot add reference" due to the project that was being added having no matching configurtion.

Even worse if you try and add a reference to an existing project that is in the solution which was there before you deleted the configurations you cannot add that either even though its sitting there. What followed was a great deal of head scratching and WTF moments.

If all else fails and you are getting this issue or other bizarre behaviour, check the configurations that each project has against the main solution and you may find there is a bit of a mismatch.

Friday, 18 November 2011

TFS - The working folder is already in use by the workspace on computer

Imagine my dismay, our logins changed on the build server and now i start getting this little beauty on automated builds.... sigh. Solution is to find the offending work spaces and remove em.

Finding the workspaces in the first place :
tf workspaces /collection:[Collection name] 


you can find the collection name when you go to the team explorer under vs2010, the root node is the collection name.  Once you have the namespace, you can remove it using the following :


tf workspace /delete [workspace name]
the workspace name is usually in the format of x_x_buildserver


hope that helps !

Thursday, 20 October 2011

Clean Code - the most valuable bits

Half way through clean code by uncle bob and for those that are pretty lazy and don't want to read the book (although it is pretty damn good tbh) I just wanted to offer a quick guide on some of the more important points the book touched on.  I learnt a good bit from this book and would heartily recommend it to anyone wanting to perfect their craft...

1. Audience Perception
One of things that is touched on a number of times is the view of somebody else reading your code and how they interpret it.  A little like the consumer of a class view of when we write our unit tests, we should take the view of an outsider reading this code.  Probably one of the most important concepts in the book.

2. Think about the function names
he means, really think about your function names.  Whilst most of us think that a function name will do, the book forces us to take a little more time and effort into really conveying what the name of the function should be.  I am as guilty as anyone else regarding this one and have now adapted my thinking when ever I create a function to see if it really does describe the intent of the function.

3. Order of code
If your like me and started coding just after the dinosaurs came, then you will find you are fixed into defining functions before they were used.  Don't have to do that these days.  Basically, Bob states that a unit of code should read like a book with the detail appearing after the more abstract code at the top, you should be able to read from the top of the code and then go down the page to get extra detail if required.  good point.

4. Functions should be small !
Smaller functions are easier to understand and comprehend straight away, there is nothing worse than ploughing through 200 lines of code to try and understand what is going on.  The book insists of smaller functions with better naming.  Smaller functions are easier to refactor, understand and reuse.

One of the side effects of using smaller functions can be larger solutions and I hear the argument about large solutions with lots of projects are confusing, personally, I don't agree.  If the projects are named correctly then their intent is obvious and again, a great deal easier to reuse, swap out etc.

Ok, will update this again later but a few really valuable points to start with.  Check out here later for more.
Happy coding !

Ever wanted config transformations for all your project types in VS2010???

Hi Everyone,

in case you didn't know, when they released VS2010 and config transforms were actually built into web projects
myself for one needed a new change of underwear due to excitement... hey I'm married, have kids so I get excited about toy cars, the night garden and new VS2010 tools built into the IDE.

I then created a windows service project only to have my excitement then turn into questions of WTF??  why web projects and not others...

Well if you didnt know of a cool little project called Slow Cheetah basically a VS package that installs and then lets you trasform not only your app.config and other configs but also any Xml file in your project ! get it here :

http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5

I can go back to watching the night garden again hurah !