Rough Cuts

by Micah 26. January 2010 20:48
First cuts from our studio session last night. Mostly to get song structure ideas. Definitely needs vocal work.

Photograph

Will I Make It Home

Holy One

Tags:

music

Setting Up a Database For Integration Tests

by Micah 6. January 2010 15:03

Warning

There is a lot of code in this post. Nothing too crazy or fancy just a LOT of code. It's too much of a pain to create and upload a project file so I've just pasted in. If for some reason you are having trouble getting the code off the page just shoot me an email and I'll send it to you. Also, I'm using MSTest so if that bothers you then please move along.

Purpose

I've always avoided doing full integration tests because it's always such a pain to get a db setup and in working order each time you need to run the tests. To make things easier I've created a helper class to manage the setup and tear-down of databases for testing. I've included a couple examples of how I'm using it in situations that require either one database for a series of tests or one database per test. Hope this makes life a little bit easier.

On with the show

Note: The biggest assumption I'm making here is that you're using integrated security for your database connection. The nice thing about this solution is that you could easily pass in ".\" for the server name (if you are using the default Sql Server Instance) and it will work on a build server quite easily.

/* The following files will need to referenced to get the Execute script code to work: * Microsoft.SqlServer.ConnectionInfo.dll * Microsoft.SqlServer.Management.Sdk.Sfc.dll * Microsoft.SqlServer.Smo.dll * * The should all be located in the following directory * C:\Program Files\Microsoft SQL Server\90\SDK\Assemblies * * Or in the event you're on 64-bit and running Sql 2008 * C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies */ using Microsoft.SqlServer.Server; using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Smo; public static class DBHelper { public static bool CreateDatabase(string dbName, string serverName) { if (DatabaseExists(dbName, serverName)) DropDatabase(dbName, serverName); var connectionString = BuildConnectionString("master", serverName); using (var connection = new SqlConnection(connectionString)) { connection.Open(); using (var command = connection.CreateCommand()) { command.CommandText = string.Format("CREATE DATABASE {0}", dbName); command.ExecuteNonQuery(); } } return DatabaseExists(dbName, serverName); } public static bool DatabaseExists(string dbName, string serverName) { var masterConnectionString = BuildConnectionString("master", serverName); using (var connection = new SqlConnection(masterConnectionString)) { connection.Open(); using (var command = connection.CreateCommand()) { command.CommandText = string.Format("SELECT name FROM master..sysdatabases WHERE name = '{0}'", dbName); using (var reader = command.ExecuteReader()) { return reader.HasRows; } } } } public static void ExecuteScript(string script, string dbName, string serverName) { if (!DatabaseExists(dbName, serverName)) CreateDatabase(dbName, serverName); var connectionString = BuildConnectionString(dbName, serverName); using (var connection = new SqlConnection(connectionString)) { var server = new Server(new ServerConnection(connection)); server.ConnectionContext.ExecuteNonQuery(script); } } public static void DropDatabase(string dbName, string serverName) { var connectionString = BuildConnectionString("master", serverName); using (var connection = new SqlConnection(connectionString)) { connection.Open(); using (var command = connection.CreateCommand()) { var sb = new StringBuilder(); sb.AppendFormat("ALTER DATABASE {0} SET SINGLE_USER WITH ROLLBACK IMMEDIATE{1}", dbName, Environment.NewLine); sb.AppendFormat("DROP DATABASE {0}", dbName); command.CommandText = sb.ToString(); command.ExecuteNonQuery(); } } } public static string BuildConnectionString(string dbName, string serverName) { var connection = new SqlConnectionStringBuilder(); connection.DataSource = serverName; connection.InitialCatalog = dbName; connection.IntegratedSecurity = true; connection.Pooling = false; return connection.ToString(); } } }

Below are a few tests that demonstrate it's usage. Once thing to note is that I have a .sql file that I generated in Management Studio called "baseline.sql". This script sets up all the tables and initial data I need for running my tests. One thing to note is that at the top of the generated script file is the statement:

USE MyDatabaseName
Since we are generating a database that has a timestamp appended to its name like DBTest060120100000 the sql file will need to be fixed. What I did was simply change the script to
USE %DBName%
and then used the string.Replace method to replace the %DBName% token with the name of the database we're currently using.

[TestClass] public class DBHelperTests { #region Fields private string _dbName; #endregion [TestInitialize] public void TestSetup() { _dbName = string.Format("TestDB{0}", DateTime.Now.ToString("ddMMyyyymmss")); } private string DBName { get { return _dbName; } } [TestCleanup] public void TestCleanup() { if (DBHelper.DatabaseExists(DBName, Settings.Default.DBServerName)) DBHelper.CreateDatabase(DBName, Settings.Default.DBServerName); } [TestMethod] public void WhenADatabaseIsSuccessfullyCreated_ThenReturnsTrue() { var actual = DBHelper.CreateDatabase(DBName, Settings.Default.DBServerName); var expected = true; Assert.AreEqual(expected, actual); Assert.IsTrue(DBHelper.DatabaseExists(DBName, Settings.Default.DBServerName)); } [TestMethod] public void WhenADatabaseAlreadyExists_ThenTheExistingDatabaseIsDroppedAndANewOneIsCreated() { var actual = DBHelper.CreateDatabase(DBName, Settings.Default.DBServerName); Assert.IsTrue(actual); Assert.IsTrue(DBHelper.DatabaseExists(DBName, Settings.Default.DBServerName)); actual = DBHelper.CreateDatabase(DBName, Settings.Default.DBServerName); Assert.IsTrue(actual); } [TestMethod] public void WhenADatabaseIsCreated_ThenReturnsTrue() { var actual = DBHelper.DatabaseExists("Uknown", Settings.Default.DBServerName); var expected = false; Assert.AreEqual(expected, actual); } [TestMethod] public void WhenADatabaseIsDropped_ThenItNoLongerExistsOnTheServer() { DBHelper.CreateDatabase(DBName, Settings.Default.DBServerName); Assert.IsTrue(DBHelper.DatabaseExists(DBName, Settings.Default.DBServerName)); DBHelper.DropDatabase(DBName, Settings.Default.DBServerName); Assert.IsFalse(DBHelper.DatabaseExists(DBName, Settings.Default.DBServerName)); } [TestMethod] public void WhenAScriptIsExecuted_ThenTheTablesAndDataAreInsertedProperly() { var script = Resources.Baseline.Replace("%DBName%", DBName); DBHelper.ExecuteScript(script, DBName, Settings.Default.DBServerName); var connectionString = DBHelper.BuildConnectionString(DBName, Settings.Default.DBServerName); bool actual; using (var connection = new SqlConnection(connectionString)) { connection.Open(); using (var command = connection.CreateCommand()) { command.CommandText = "SELECT * FROM dbo.[User]"; using (var reader = command.ExecuteReader()) { actual = reader.HasRows; } } } Assert.IsTrue(actual); } }

This next example shows how you would setup a set of tests to all use the same database.

[TestClass] public class EntityFrameworkRepositoryTest { #region Fields private static string _dbName; private EntityFrameworkRepository _repository; #endregion private static string DBName { get { return _dbName; } } private EntityFrameworkRepository Repository { get { return _repository; } } [ClassInitialize] public static void InitializeClass(TestContext context) { _dbName = string.Format("TestDB{0}", DateTime.Now.ToString("ddMMyyyymmss")); var script = Resources.Baseline.Replace("%DBName%", DBName); DBHelper.ExecuteScript(script, DBName, Settings.Default.DBServerName); } [ClassCleanup] public static void CleanupClass() { if (DBHelper.DatabaseExists(DBName, Settings.Default.DBServerName)) DBHelper.DropDatabase(DBName, Settings.Default.DBServerName); } [TestInitialize] public void InitializeTest() { var sqlConnectionString = DBHelper.BuildConnectionString(DBName, Settings.Default.DBServerName); var entityFrameworkConnectionString = Utils.GetEntityFrameworkConnectionString("Littlefish.Data", "DataModel", sqlConnectionString); _repository = new EntityFrameworkRepository(entityFrameworkConnectionString); } [TestMethod] public void WhenRetrievingAnEntityThatExistsInTheDatabase_ThenTheEntityIsSuccessfullyRetreived() { var user = Repository.Get().FirstOrDefault(); Assert.IsNotNull(user); } }

I hope this helps make the idea of doing full integration tests or fully testing your data repository much more approachable.

Shout it

Tags:

TDD

95 Live

by Micah 30. December 2009 17:49

Found a few songs we recorded in the studio several years ago for 95 Live on 95.1 WIIL Rock:

BreakAway

Downer

Tags:

Deleting entities in a many to many relatonship with Entity Framework and Ria Services

by Micah 22. December 2009 08:20

Trying to delete a record in a many to many relationship can be a bit tricky. In this scenario I have a person record that can be tied to multiple address records. Here is our database setup:

 

When creating the data model the Entity Framework will hide all the details for us of creating and updating the intermediary "PersonAddress" table.  Here's what's generated by the designer:

When generating our Ria Service, if we select the "Enable Editing" option for our "Address" table it will create all the CRUD methods we need including a "DeleteAddress" method:

public void DeleteAddress(Address address)
{
    if ((address.EntityState == EntityState.Detached))
    {
        this.ObjectContext.Attach(address);
    }
    this.ObjectContext.DeleteObject(address);
}

In order to call this on the client side you call the remove method on the DomainContext

public void DeleteAddress(Address address)
{
    myContext.Addresses.Remove(address);
}

You won't have any luck trying to get this to work straight out of the box. Chances are you'll get some sort of exception thrown that wont make any sense. The issue is that the Entity Framework wont let you delete one end of the many-to-many relationship without the other end being loaded in the ObjectContext. So we need to make sure both the Address and the Person are attached to the ObjectContext before we can delete the Address. The easiest way to this is to load an the address from the database and tell it to include the Person in the object graph. Now both the Person object and the Address object will be loaded and the address can be deleted.

public void DeleteAddress(Address address)
{
    var addressToDelete = ObjectContext.Address
                                       .Include("Person")
                                       .Where(x => x.Id == address.Id)
                                       .First();

    ObjectContext.DeleteObject(addressToDelete);

}

So instead of using the Address object passed in i'm loading it from the database and then deleting it. Yes it's an extra call to the database but I don't think it's a big deal and I really don't see any other workarounds.

Shout it

Tags:

Entity Framework | Ria Services | Silverlight

Resolution of the dependency failed, type = "Microsoft.Practices.Composite.Presentation.Regions.TabControlRegionAdapter"

by Micah 17. December 2009 07:05

I started getting this issue the other day and it has plagued me for the past two evenings. Why all of a sudden is Unity failing to resove the TabControlRegionAdapter in Prism?

Apparently in my bootstrapper I inadvertently removed the call to base.ConfigureContainer. This method is responsible for hooking up all the Prism dependencies. Removing this causes all of my requests to things like Container.Resolve<IRegionManager> to fail.

public class Bootstrapper : UnityBootstrapper
{
    protected override void ConfigureContainer()
    {
        //Not calling this blows everything up
        base.ConfigureContainer();

        Container.RegisterType();
        Container.RegisterType();
    }
}

Tags:

prism | Silverlight | Unity

Music

by Micah 15. December 2009 17:45

Tags:

music

Localization with RIA Services and Silverlight

by Micah 11. December 2009 08:08

Hopefully there will be an easier way of getting localization to work with RIA services soon, but at least it can be done. Here's what you need to do:

  1. In your server side project (the web project) add a resource file in a folder called resources.  

  2. In your client-side (silverlight) project you will also need to add a folder called resources. Right click the new folder and select "Add existing item". Navigate to your web project folder and select both the "Resources.resx" and "Resources.Designer.cs" and choose the "Add as link".

  3. You will notice that your resource file and the designer file are not listed properly in your project. They show up as two separate files instead of the designer file being attached to the .resx file. In order to fix it we need to make a modification to the project file. Right click the silverlight project file and click "Unload Project". Right click the project file again and choose "Edit ". Make sure the resource file is setup as follows:

    <Compile Include="..\Littlefish.Membership.Services\Resources\Resources.Designer.cs">
    <AutoGen>True</AutoGen>
    <DesignTime>True</DesignTime>
    <DependentUpon>Resources.resx</DependentUpon>
    <Link>Resources\Resources.Designer.cs</Link>
    </Compile>

    Now right click your project file again and choose "Reload Project".

  4. Now let's use our resources along with the Data Annotation Attributes to tell our DataForm how to display our data. I've defined a few strings in my resource file that I'm going to use. Here's how we hook everything up:
    [MetadataType(typeof(PersonMetadata))] public partial class Person { internal sealed class PersonMetadata { [Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "PersonFirstNameReq")] [Display(ResourceType = typeof(Resources), Name = "PersonFirstName", Description = "PersonFirstNameDesc")] public string FirstName; } }
  5. Now my DataForm will generate my fields using the information I've provided in the attributes:

Shout it

Tags:

Ria Services | Silverlight

Wikipedia Maze Source Code

by Micah 6. December 2009 01:50

After much debate and consideration I have decided to release the source code to Wikipedia Maze. It's been a great learning experience for me these last few months and has been a lot of fun to put together. I hope that putting it into the public domain will help the project develop and grow much more than it ever could with just me developing it. It still has a long way to go, but I'm hoping that feedback from both the players and the development community will help it become something really cool.

There's lots to be done. Bug fixes, features, scalability issues, and overall playability improvements. If you're not familiar with the game you can check it out at www.wikipediamaze.com. If you want to browse the source code it's located at http://code.google.com/p/wikipediamaze/. If you want to contribute dive right in and send me some patches. If you have any questions about the architecture or getting the environment setup you can reach me at micah@wikipediamaze.com. If you would like to see any outstanding issues or feature requests, or you would like to submit either of those you can do so at at http://wikipediamaze.uservoice.com/pages/15400-general.

I'm looking forward to any and all feedback.

Tags:

Wikipedia Maze

Songs

by Micah 1. December 2009 18:20

Here are some outtakes from our jam session the other night. Just a few of the songs I've been writing.

Disclaimer

The recording is really rough. The vocals are seriously lacking and the lead guitarist had never played the songs before. All in all it's not anywhere near completion, just some rough ideas.

Will I Make It Home

Running(4.50 mb)

Photograph

Fire

Tags:

Including related entities in your domain service calls

by Micah 29. November 2009 21:53

There are two steps you need to perform in order to get back related entities in your object graph when making calls to your domain service using the Entity Framework or Linq to Sql as your DAL.

Let's say we want to retrieve a Person record along with their Address record. The first step is to tell your DAL to return the associated object in your query like this:

Entity Framework

public Person GetPersonById(long Id) { return this.Context.People.Include("Address").Where(p => p.Id == Id).FirstOrDefault(); }

Linq To Sql

//In your DataContext Setup you need to specify the load options: System.Data.Linq.DataLoadOptions options = new System.Data.Linq.DataLoadOptions(); options.LoadWith<Person>(p => p.Address); dataContext.LoadOptions = options; public Person GetPersonById(long Id) { return this.Context.People.Where(x => x.Id == Id).FirstOrDefault(); }

Now we need to tell RIA to include that object in the serialization process. When creating our service using the "Domain Service" project item template it gives you the option to generate a metadata class for each of the entities that are used in the service calls. In our case it creates one for our Person class and we need to specify that we want our Address entity included on the serialization process by using the IncludeAttribute. I wont go into detail here about the specifics of the metadata class but this example should give you a rough idea on how it works:

[MetadataType(typeof(PersonMetadata))] public partial class Person { internal sealed class PersonMetadata { [Include] public Address Address; } }

kick it on DotNetKicks.com

Tags:

Entity Framework | Linq to Sql | Ria Services | Silverlight

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen