Archive for the 'Technology' Category

TFS 2012 with Update 2 – Done

At SSW, we make sure we keep ourselves up to date with the latest version of everything, we were one of the first to upgrade our TFS 2010 instance to TFS 2012 RC, then to the RTM when that became available, and finally to Update 1 earlier this year.  Today, I’m happy to announce we have upgraded to TFS 2012.2 (or TFS 2012 Update 2).

Summary

One of the major changes with this version is the installation story.  Microsoft has done a lot of work to help ease your upgrade path, so you’ll notice the upgrade is much more straightforward than previous ones.

This update remembered the vast majority of our settings, so there was less need to reconfigure everything after the install.  I like to err on the side of safety though, so I followed our standard steps:

  1. Screenshot our existing configuration
  2. Back up the databases and snapshot the servers
  3. Stop the TFS services
  4. Install TFS 2012 Update 2
  5. Configure TFS 2012 Update 2
  6. Test, test, test!

Before you start

Just as we did last time, the first step was to send an email letting everyone know there would be a TFS outage.  See our Rules to Better Networking for an example of how to do it.

If you’re doing the upgrade, you’ll also need administrator access to the servers. Just as last time, I got promoted temporarily so I could do my work.

Preparation Steps – save your existing configuration

The release notes for TFS 2012.2 claim that all your settings will persist, but just in case, I opened the TFS Administration Console and took a screenshot of each summary page and ended up with 4 images.  This ensures I don’t forget any of the settings if I need them.

Once I’d saved everything I need, I could get going on the install.

Preparation Steps – stopping the servers and backing up

  1. Review the Rules to Better TFS 2012 Migration to make sure what you need to do.  In line with these rules, I took the TFS server offline.
    This is important because we don’t want any checkins or work item changes to come through while we’re halfway through the process.  They may miss the upgrade!

    1. Use TFSServiceControl quiesce to stop all the agents.
      Note: Once again  I got a number of exceptions, but the process automatically retries and succeeds.  The important parts are highlighted in yellow.
      TFS Quiesce
    2. Stop the relevant network services
      TFS Net Stop WAS
    3. Verify that you can’t connect to the TFS server by trying to connect in Visual Studio
      TFS unavailable in VS
      And that you can’t visit TFS Web Access
      TFS Web - 404
  2. As per our rules,  it’s a good idea to run the DogFood Stats queries from Grant Holliday. Document the numbers so you can compare them after the upgrade to make sure you haven’t lost anything.  If you have more than one Project Collection, make sure you do this over every Project Collection you care about.
  3. Back up the TFS and Reporting Server databases as per our rules.
    We have a few relevant databases because we have a number of Project Collections.
    TFS Backup Collections

Installing TFS 2012.2

  1. Because we’re installing from an ISO rather than a physical CD, we mount the ISO using SlySoft’s Virtual CloneDrive (or your favourite alternative).
  2. Run tfs_server.exe from the installation disk or ISO.
  3. Accept the license terms and click Install Now.
    TFS 2012.2 Install
  4. Watch the progress with excitement and trepidation (and coffee)
    TFS 2012.2 Installingssw-coffee

Configuring TFS 2012.2

  1. The Upgrade Wizard should start automatically this time (previously you had to choose it) and it will collect your settings for you!
    Upgrade Wizard collecting settings
  2. When it’s done, you can click Next.
  3. We’re now asked to upgrade an existing database.  Because of the work done with upgrades, the tool should have these details already filled out.
    Upgrading the Database
  4. Confirm you have a current backup, then click Next.
  5. Next, we’re asked for the service account for our Application Tier.  Again, this should already be filled out. Once you’ve provided the password again, check it by clicking Test, then click Next.
    Application Tier settings
  6. Next up, we’re asked if we want to configure SQL Reporting Services.  Make sure the checkbox is checked, then click Next.
  7. Again checking your screenshots, make sure the instance and URLs for your Reporting Services instance are correct (they should be), and click Next.
    TFS Reporting Services config
  8. Next up is the TFS Warehouse database.
  9. The wizard should have already filled this out for you.  If everything is correct, click Next.
    Warehouse Database settings
  10. Next, you’re asked for your Analysis Services instance.  Check the instance name before clicking Next.
  11. Next, we’re asked to provide an account that the Reports will run as.  Again, this should already be filled out by the wizard, but you’ll have to provide a password. Do so, then click Next.
  12. Next we’re asked if we want to configure SharePoint for TFS, we do, so we’ll make sure the checkbox is checked and click Next.
  13. Once again, the wizard should have kept all our existing settings.  We’ll check they’re correct by clicking Test, then click Next.
    SharePoint settings
  14. On the next screen, we’ll get a summary of all the options we’ve chosen.
  15. Go through them carefully to make sure everything is correct, and click Verify to check.
    TFS config confirmation
  16. Your Verify step may highlight issues such as restarts required.  I once again got this issue and had to reboot the server before continuing.
    As per our upgrade to the RTM, I got stuck in a reboot loop and had to follow Steve Wiseman’s advice to break out of it.
    Once fixed, I had to click Configure Installed Features on the Application Tier node then choose Upgrade to start the wizard again.
  17. Once the readiness checks pass, click Configure
    Readiness Checks
  18. Wait patiently (again with coffee) while the upgrade goes through its steps.  When finished, click Next.
    Final Configuration
  19. Once the TFS upgrade has finished, the Upgrade Wizard will upgrade each of the Project Collections. Be patient while it does this.
    Project Collection Upgrades
    ssw-coffee
  20. At this point I ran the Dog Food Stats again (as per step 9) and checked that nothing had changed too much.  This time, all the numbers were exactly the same which is reassuring

Additional steps

  1. I also upgraded Team Foundation Server on our Build Servers by installing the upgrade and checking the settings were the same.
  2. I had to reconfigure our Build Agent to get it working again – it was running under the wrong account.

Testing

After the final steps were completed, we went through the following tests to make sure everything was up and running again.

  1. Open Visual Studio and connect to TFS
  2. Do a Get Latest
  3. Make a change and check in
  4. Trigger a build and wait for it to succeed
  5. Check TFS Web Access is working by navigating to the TFS URL
  6. Check the Reporting Services are still working by navigating to the reporting URL

All the tests passed without a problem, so we’re up and live on TFS 2012 Update 2!

There is a lot of goodness in this update for everyone – have a look at the blo

Enterprise MVC Apps course – redux

Last year, Adam Stephensen and I ran a number of “Enterprise MVC” courses.  These courses were hugely popular, not only selling out in Brisbane, Melbourne, and Sydney, but receiving positive feedback from each session nationwide.

Well, due to popular demand, they’re back, but in a slightly different format – it’s gone from a 2 part course to a course of 4 relatively independent days.  Day 1 will be useful if you’re new to MVC, while the other three days will take your skills to the next level by teaching how to make enterprise-quality MVC applications.

There are a few reasons for the change, all of which based on feedback from the participants.

The volume of important content was the primary reason for the change.  Adam and I really wanted to spend more time on important topics like Inversion of Control, Dependency Injection, logging, and testing.  With a 4 day course, we can really give these topics the attention they deserve.

We also think that getting your hands dirty is really important for understanding a lot of concepts.  By extending the course to 4 days, we can ensure there’s plenty of time for participants to try things rather than just hearing about them.

Finally, we found that attendees came to the course with differing levels of MVC experience.  For some, the introductory subjects were invaluable, but not for everyone.  By adding an extra day for MVC Foundations, we can confidently start at a higher level for the subsequent days.

If you’re writing MVC applications (or want to start) and you want to go beyond the demos so you can write enterprise-quality, maintainable, scalable, and robust applications in MVC, I’d highly recommend attending our new and improved courses.

For more details:

P.S. Telerik has once again jumped on board offering licenses for some of their awesome products when you register.  Check out the course pages for more info!

TFS 2012 with Update 1 – Done

Not long ago, we upgraded our TFS 2010 instance to TFS 2012 RC, and then followed it up with an update to the RTM when that became available.  It has been running great since the upgrade.

Today, I’m happy to announce we updated our TFS 2012 server with Update 1 last week.  This update adds a lot to TFS, but many of the changes are behind the scenes.

Once again, SSW is the first company I know of to make the move to TFS 2012 Update 1!

Summary

It took a few more steps than I thought would be needed.   I’ll be going through the steps we took to upgrade our TFS in this blog post – if you follow this guide, it will be a snap.

Warning: Even though this is called an “update”, it represents a complete new version and therefore you’ll need to configure everything again!

The steps I took were:

  1. Screenshot our existing configuration
  2. Back up the databases and snapshot the servers
  3. Stop the TFS services
  4. Install TFS 2012 Update 1
  5. Configure TFS 2012 Update 1
  6. Test, test, test!

Before you start

Just as we did last time, the first step was to send an email letting everyone know there would be a TFS outage.  See our Rules to Better Networking for an example of how to do it.

If you’re doing the upgrade, you’ll also need administrator access to the servers. Just as last time, I got promoted temporarily so I could do my work.

Preparation Steps – save your existing configuration

Once again, this is an incremental release so we can expect the configuration to be more or less identical.  To make life easier for me, I opened the TFS Administration Console and took a screenshot of each setting.  This ensures I don’t forget any of the settings.  I referred back to these settings in step 5.

Once I’ve saved everything I need, we can get going on the install.

Preparation Steps – stopping the servers and backing up

  1. Review the Rules to Better TFS 2012 Migration to make sure what you need to do.  In line with rule 4, I took the TFS server offline.
    This is important because we don’t want any checkins or work item changes to come through while we’re halfway through the process.  They may miss the upgrade!

    1. Use TFSServiceControl quiesce to stop all the agents.
      Note: Once again  I got a number of exceptions, but it seems after a retry it worked fine.  The important parts are highlighted in yellow.
      TFS Quiesce
    2. Stop the relevant network services
      TFS Net Stop WAS
    3. Verify that you can’t connect to the TFS server by trying to connect in Visual Studio
      TFS unavailable in VS
      And that you can’t visit the TFS Web Access
      TFS Web - 404
  2. As per rule 5,  it’s a good idea to run the DogFood Stats queries from Grant Holliday.  Document the numbers so you can compare them after the upgrade to make sure you haven’t lost anything.  If you have more than one Project Collection, make sure you do this over every Project Collection you care about.
  3. Back up the TFS and Reporting Server databases as per rule number 6.
    We have a few relevant databases because we have a number of Project Collections.
    TFS Backup Collections

Installing TFS 2012 Update 1

  1. Because we’re installing from an ISO rather than a physical CD, we mount the ISO using SlySoft’s Virtual CloneDrive (or your favourite alternative).
  2. Run tfs_server.exe from the installation disk or ISO.
  3. Accept the license terms and click Install Now.
    Update 1 Installation
  4. Watch the progress with excitement and trepidation (and coffee)
    Update 1 Install Progress

Configuring TFS 2012 Update 1

  1. Choose Upgrade from the left-hand menu and click Start Wizard.
    TFS upgrade
  2. Click Next on the first screen presented.
  3. We’re now asked to upgrade an existing database.  Type in your SQL Server instance name and then click List Available Databases.  The tool should find your TFS Configuration database.
    TFS database upgrade
  4. Confirm you have a current backup, then click Next.
  5. Next, we’re asked for the service account for our Application Tier.  To make sure this is consistent, check the screenshots you created right at the start in your Preparation Steps. Click Next.
    TFS Application Tier settings
  6. Next up, we’re asked if we want to configure reporting services.  Make sure the checkbox is checked, then click Next.
  7. Again checking your screenshots, make sure the instance and URLs for your Reporting Services instance are correct, and click Next.
    TFS Reporting Services config
  8. Next up is the TFS Warehouse database.
  9. Enter the correct SQL Server instance (if it’s not already correct), then test the connection by clicking on Test, then click List All Available Databases. The wizard will find the Tfs_Warehouse database automatically.  If everything is correct, click Next.
    TFS warehouse config
  10. Next, you’re asked for your Analysis Services instance.  Again, check your screenshots and enter the correct information before clicking Next.
  11. Next, we’re asked to provide an account that the Reports will run as.  Check your screenshots and click Next.
  12. Next we’re asked if we want to configure SharePoint for TFS, we do, so we’ll make sure the checkbox is checked and click Next.
  13. Important: Even if you have a different SharePoint setup, it’s advisable to simply use the current SharePoint settings at this point.  If you enter new details, the final step will have trouble verifying the installation as it will think you have two SharePoint instances.  Don’t worry, you can change it later.
    TFS SharePoint config
  14. On the next screen, we’ll get a summary of all the options we’ve chosen.
  15. Go through them carefully to make sure everything is correct, and click Verify to check.
    TFS config confirmation
    Note that we had some issues at this point with Analysis Services.  It appeared Analysis Services was corrupt and was preventing us from continuing.  Thanks to this blog post by Oshry Horn, we were able to fix the issue and continue with our configuration.
    Matt has also mentioned in the comments that the WWW Publishing service needs to be started at this point.  You can do this by typing “net start was” in a command line console (as Administrator). 
  16. Once the readiness checks pass, click Configure
    Readiness Checks
  17. Wait patiently (again with coffee) while the upgrade goes through its steps.  When finished, click Next.
    Upgrade Done
  18. Once the TFS upgrade has finished, the Upgrade Wizard will upgrade each of the Project Collections. Be patient while it does this.
    Project Collection Upgrades
  19. At this point I ran the Dog Food Stats again (as per step 9) and checked that nothing had changed too much.

Additional steps

  1. I also upgraded Team Foundation Server on our Build Servers by installing the upgrade and checking the settings were the same.
  2. I also uninstalled the TFS Extensions on the SharePoint server and installed the new ones.
    To get this working again, I had to repair the connection in the Configuration Manager on the TFS server to get them talking to each other again.
    Repair Sharepoint Connections
  3. We also had to reconfigure our Build Controller to get it working again.

Testing

After the final steps were completed, we went through the following tests to make sure everything was up and running again.

  1. Open Visual Studio and connect to TFS
  2. Do a Get Latest
  3. Make a change and check in
  4. Trigger a build and wait for it to succeed
  5. Check TFS Web Access is working by navigating to the TFS URL
  6. Check the Reporting Services are still working by navigating to the reporting URL

I’m happy to say all these tests passed without a problem.

We’re up and live on TFS 2012 Update 1!

Die, Native Apps, Die!

Recently, I’ve been telling anyone who will listen that you should consider writing an HTML5 web app rather than a native mobile app.  The advantages are many and the list of things you can’t do grows smaller by the day.

I spoke on the topic at DDD Sydney earlier in the year, and more recently at Web Directions “What Do You Know” in Brisbane.  If you’d like the slides, they’re available at http://www.damianbrady.com.au/dyrnaa and http://www.devnewsreader.com/about.html respectively; complete with demos.  Check them out – I’d love your comments.

Why choose web apps over native apps?

There are a lot of reasons, and most are obvious.

  1. Users are always on the latest version – no support of old versions
  2. You only have to implement it once, in one language (counting HTML, CSS, and JS as one language of course)
  3. You can choose what to charge and how to charge it
  4. Done properly, web apps work on all devices – even those that don’t exist yet

But they’re slow!

Well no, not necessarily.  I blame Facebook for this misconception.

Facebook famously released an HTML5-based app for iOS and then ditched it in favour of a native app to squeeze more performance out. After all the reporting, the emergent mainstream view was that HTML5 apps simply couldn’t perform.  In reality, the new release was a refresh using a technology closer to the metal as a reaction to consumers screaming out for performance above all else.  Let’s face it, Facebook is not a trivial app in terms of bandwidth and content. There’s a fair bit going on with photos, chat, notifications, etc.

Could Facebook have made the app faster while still using HTML5? Almost certainly, and if they’d leveraged newer HTML5 capabilities as they became available, there definitely would have been improvements.

But would it have appeased the masses? Maybe, but we’ll never really know.

But web apps can’t do X!

Quite possibly not, no.

Well… unless you’re talking about using touch events, orientation, geolocation, hardware-accelerated graphics, local data storage, offline operation, home-screen icons, audio and video, sending emails or making phone calls. So probably yes… yes they can.

Sure, there’s gaps in there. A web app can’t use your phone contacts, it can’t play your music, and it can’t (quite) use the camera.

…Yet

Yet?

There’s a very definite trend in the world of HTML and browsers.  Each new browser or mobile OS version slowly chips away a bit more at the list of things a web app can’t do.  Surprisingly, Apple seems to be leading the way to a degree in the mobile space; enabling more and more HTML5 features in Safari with each release.

I say “surprisingly” because Apple has a very captive market in terms of native apps. True or not, the perception exists that neither Android nor Windows Phone have the same quality of apps available in their stores. Certainly they don’t have the quantity. Why then would Apple implement functions in Safari that pave the way for native-quality web apps?  It’s a good question, and I’m not sure I have the answer. Maybe it’s just the constant drive to stay in front.

Grooveshark

Very recently, Grooveshark rolled out a fully-functional HTML5 version of their site that works beautifully on mobile devices.  They’ve been plagued by problems getting native apps into the official app stores, and this option allows them to bypass the problem altogether.

It’s a truly impressive piece of engineering. If you have a … well… anything… I strongly suggest you go and try it out.  There are some amazing features. For example, (On iOS at least) you don’t even have to keep the browser window open for the music to keep playing.

One small thing… I’d love to see them implement some of the meta and link tags that Apple has made available for iOS devices.  For an example, try adding http://www.devnewsreader.com to your home screen on an iPhone or iPad (warning, it’s quick-demo quality).

Despite being a company that focuses on something not traditionally offered via a web page (streaming music), Grooveshark has chosen HTML5 as the right way to go.  Before sinking time and money into developing native apps for multiple platforms, it’s worth considering whether your app might be a good candidate for a web app as well.

Grooveshark may not be the first high-profile name to try to escape the walled-garden of native apps, but moves like this definitely show the blood in the water (pun totally intended and awesome).

Upgrading from TFS 2012 RC to TFS 2012 RTM – Done

On Saturday 11th August, we moved from the Release Candidate of TFS 2012 to the RTM version.

The move to TFS 2012 RC was fairly straightforward, however there was some work to be done after the move to repair broken builds and our Projects SharePoint site.  The move from RC to RTM represents less of an upheaval, but as this is SSW’s most important server, we can’t take shortcuts!

Once again, SSW is the first company I know of to make the move to TFS 2012 RTM!

Summary

I’ll be going through the steps we took to migrate from RC to RTM below. It’s not quite as detailed as the move from 2010 to RC, but it’s still fairly comprehensive.

Rather than move hardware again, we did an in-place upgrade.  This was our preferred option considering it was a fairly basic incremental upgrade and our environment was upgraded last time so it was still quite new.

The plan was:

  1. Screenshot our existing configuration
  2. Back up the databases and snapshot the servers
  3. Uninstall TFS 2012 RC
  4. Install TFS 2012 RTM
  5. Configure TFS 2012 RTM (including Reporting Services and Build Servers)

Before you start

Just as we did last time, the first step was to send an email letting everyone know there would be a TFS over the weekend.  See our Rules to Better Networking for an example of how to do it.

If you’re doing the upgrade, you’ll also need administrator access to the servers. Just as last time, I got promoted for the weekend.

Unlike last time, we’ll be using the same environment as our existing servers so there’s no need to build new machines.  It’s important for your rollback plan to get a snapshot of the servers before you start, so make sure you do that before making any changes.

We’d suggest an environment that looks like ours:

  • Windows 2008 R2 server: TFS 2012 RC and a local SharePoint instance
  • Windows 2008 R2 server: SQL Server 2012

Preparation Steps – save your existing configuration

Unlike moving from TFS 2010, this is an incremental release (RC to RTM) and we can expect the configuration to be more or less identical.  To make life easier for me, I opened the TFS Administration Console and took a screenshot of each setting.  This ensures I don’t forget any of the settings.

Once I’ve saved everything I need, we can get going on the install.

Preparation Steps – stopping the servers and backing up

  1. Take the TFS 2012 server offline.
    This is important because we don’t want any checkins or work item changes to come through while we’re halfway through the process.  They may miss the upgrade!

    1. Use TFSServiceControl quiesce to stop all the agents
      Note: This time I got a number of exceptions, but it seems after a retry it worked fine.  The important parts are highlighted in yellow.
      TFS Quiesce
    2. Stop the relevant network services
      TFS Net Stop WAS
  2. Verify that you can’t connect to the TFS server by trying to connect in Visual Studio
    TFS unavailable in VS
    And that you can’t visit the TFS Web Access
    TFS Web - 404
  3.  At this stage, it’s a good idea to run the DogFood Stats queries from Grant Holliday.  Document the numbers so you can compare them after the upgrade to make sure you haven’t lost anything.  If you have more than one Project Collection, make sure you do this over every Project Collection you care about.
  4. Back up the TFS and Reporting Server databases
    We have a few relevant databases because we have a number of Project Collections.
    TFS Backup Collections
  5. Back up the Reporting Services Encryption Keys.
    We’ll need these later to reconfigure Reporting Services against the restored databases.
    To back up the encryption key, follow the steps on the MSDN page.

Note: We originally had some discussions about whether to detach the Project Collections before uninstalling.  Grant Holliday advised us it would be better to leave them attached.

Uninstalling TFS 2012 RC

  1. Go to the Programs and Features tool on your TFS Server
  2. Select Microsoft Team Foundation Server 2012 RC and click Uninstall
    Uninstall TFS
  3.  Click the big Uninstall Now button, and click Yes when asked to confirm.
    Uninstall TFS now

Installing TFS 2012 RTM

  1. Because we’re installing from an ISO rather than a physical CD, we mount the ISO using SlySoft’s Virtual CloneDrive (or your favourite alternative).
  2. Run tfs_server.exe from the installation disk or ISO.
  3. Accept the license terms and click Install Now.
    TFS Install now
  4. Watch the progress with excitement and trepidation (and coffee)
    TFS installing progress
    You may get a message asking you to reboot the machine.  If it does appear… restart the machine.
    TFS Install Restart
  5. When installation finishes, enter your product key (or install a trial license) and click Activate.
    TFS Product Key
  6. Choose Upgrade from the left-hand menu and click Start Wizard.
    TFS upgrade
  7. Clck Next on the first screen presented.
  8. We’re now asked to upgrade an existing database.  Type in your SQL Server instance name and then click List Available Databases.  The tool should find your TFS Configuration database.
    TFS database upgrade
    Confirm you have a current backup, then click Next.
  9. Next, we’re asked for the service account for our Application Tier.  To make sure this is consistent, check the screenshots you created right at the start in your Preparation Steps. Click Next.
    TFS Application Tier settings
  10. Next up, we’re asked if we want to configure reporting services.  Make sure the checkbox is checked, then click Next.
  11. Again checking your screenshots, make sure the instance and URLs for your Reporting Services instance are correct, and click Next.
    TFS Reporting Services config
  12. Next up is the TFS Warehouse database.
    Enter the correct SQL Server instance (if it’s not already correct), then test the connection by clicking on Test, then click List All Available Databases. The wizard will find the Tfs_Warehouse database automatically.  If everything is correct, click Next.
    TFS warehouse config
  13. Next, you’re asked for your Analysis Services instance.  Again, check your screenshots and enter the correct information before clicking Next.
  14. Next, we’re asked to provide an account that the Reports will run as.  Check your screenshots and click Next.
  15. Next we’re asked if we want to configure SharePoint for TFS, we do, so we’ll make sure the checkbox is checked and click Next.
  16. Important: Even if you have a different SharePoint setup, it’s advisable to simply use the current SharePoint settings at this point.  If you enter new details, the final step will have trouble verifying the installation as it will think you have two SharePoint instances.  Don’t worry, you can change it later.
    TFS SharePoint config
  17. On the next screen, we’ll get a summary of all the options we’ve chosen.
    Go through them carefully to make sure everything is correct, and click Verify to check.
    TFS config confirmation
    Once again I got errors at this point and was told I had to restart the server.
    After restarting 3 times with no success, I got suspicious and searched for a solution.
    Thankfully, a blog post by Steve Wiseman helped me out and I finally got through.
  18.  Once the readiness checks pass, click Configure.
    TFS Readiness
    Note: You can see I have some warnings here. The first is because we’re using a non-standard port. I’ll be able to change that later. The second is letting me know I’m using a single TFS Account for two purposes. We’ve analysed this and are happy to take that risk.
  19. Configuration will start now and may take some time.  Maybe grab a coffee and have a chat with your neighbour. When it’s finished, make sure you have all green ticks and then click Next.
    TFS configuration success
  20. Now, each of the Project Collections will be updated.  If you’re moving from RC, this should take no time at all.
    TFS Upgrade Collections
    Once you get a big green tick, click Next.
    Note: The Lab management warning told us it couldn’t tear down any labs.  As we didn’t have any set up, this wasn’t an issue.
  21. Finally, you’ll get a success message and the upgrade is complete!
    TFS upgrade success
  22. You should now run the DogFood Stats queries from Grant Holliday again to make sure there are no big changes.  If you’ve upgraded from RC, the numbers should be identical.

Configuring the new installation

There are some additional steps you may need to take to get everything back up and running.

  1. I used the Build Service Configuration Wizard to re-setup our Build servers.  If you’re using a separate Build Server from your TFS Server, you’ll need to go through the steps to uninstall and reinstall TFS 2012 RTM on the Build Server before completing the below steps on the Build Server.
  2. On the Build Configuration tab, click Configure Installed Features to start the wizard.
    TFS Configure
  3. The tool detected our previous settings, so setting up was straightforward.
    TFS Build setup
  4. After choosing your Project Collection, you’re asked for your build service credentials.  It’s a good idea to have a separate account for builds, so I entered those details.
    TFS Build credentials
  5. Check the settings in the confirmation screen and click Verify to confirm.
    TFS Build confirmation
    Note: Again, you might need to reboot your machine before being able to get past the Verify screen.  If this doesn’t work, refer to Steve Wiseman’s post again.
  6. Once you get all green ticks, click Configure.
    TFS Build confirmed
  7. You should get a big, green Success tick as your reward.
    TFS Build success
  8. You’ll also need to upgrade Team Foundation Server on any Build Servers you have.

Testing

After the final steps were completed, we went through the following tests to make sure everything was up and running again.

  1. Open Visual Studio and connect to TFS
  2. Do a Get Latest
  3. Make a change and check in
  4. Trigger a build and wait for it to succeed
  5. Check TFS Web Access is working by navigating to the TFS URL
  6. Check the Reporting Services are still working by navigating to the reporting URL

I’m happy to say all these tests passed without a problem.

We’re up and live on TFS 2012 RTM!

A Generic Repository and Unit of Work Implementation for Entity Framework

You may be familiar with my previous posts describing the implementation of design patterns for Entity Framework.  It started with using generics for lookup tables, and followed with a generic CRUD repository.  This strategy follows along with our SSW rule, Do you use the Repository Pattern for data access.

In the lead up to SSW’s recent Enterprise MVC course, I had lots of discussions with Adam Stephensen and Eric Phan about whether we could do a better job with this pattern.  We’ve come up with what we think is a great solution that includes the Unit of Work pattern as well.

We felt it was really important to separate the domain models, the repositories, and the context; a separation that’s not made by Entity Framework. Doing so gave us some really important benefits.  Testing is made much easier.  For one, we can mock our context enabling us to test our repositories without going back to the database.  We can also mock the repositories to test the code that calls it.

A quick shout-out to Adrian Clark who suggested this separation in the comments last time.

We also used Inversion of Control to inject a context into the repository.  We could have had a reference to each of our repositories in our context, but inverting this relationship meant that we only needed to instantiate those repositories we were actually using.  It means less overhead and a looser coupling between the context and each repository.

First, we create our IUnitOfWork and our IGenericRepository.

public interface IUnitOfWork : IDisposable
{
    DbSet<TEntity> Set<TEntity>() where TEntity : class;

    int SaveChanges();
}
public interface IGenericRepository<TEntity>
  where TEntity : class
{
    IQueryable<TEntity> Select();

    IEnumerable<TEntity> GetAll();

    IEnumerable<TEntity> Where(Func<TEntity, bool> predicate);

    TEntity GetSingle(Func<TEntity, bool> predicate);

    TEntity GetFirst(Func<TEntity, bool> predicate);

    void Add(TEntity entity);

    void Delete(TEntity entity);

    void Attach(TEntity entity);

    void Dispose(bool disposing);

    void Dispose();
}

Then, we create an interface for our specific context. In this example, we have a context with a set of customers. This context is essentially a unit of work, so we’ll inherit that interface.

public interface ICustomerContext : IUnitOfWork
{
    DbSet<Customer> Customers { get; set; }
}

Next, we’ll create a concrete GenericRepository instance. This is very similar to the version in my previous post, but take note of the repository that takes a context. We use this to inject our Unit of Work.

public class GenericRepository<TContext, TEntity> : IGenericRepository<TEntity>
    where TContext : IUnitOfWork
    where TEntity : class
{
    protected TContext _context;
    /// <summary>
    /// Constructor that takes a context
    /// </summary>
    /// <param name="context">An established data context</param>
    public GenericRepository(TContext context)
    {
        _context = context;
    }

    public IQueryable<TEntity> Select()
    {
        return _context.Set<TEntity>().AsQueryable();
    }

    public IEnumerable<TEntity> GetAll()
    {
        return _context.Set<TEntity>().AsEnumerable();
    }

    public IEnumerable<TEntity> Where(Func<TEntity, bool> predicate)
    {
        return _context.Set<TEntity>().Where(predicate);
    }

    public TEntity GetSingle(Func<TEntity, bool> predicate)
    {
        return _context.Set<TEntity>().Single(predicate);
    }

    public TEntity GetFirst(Func<TEntity, bool> predicate)
    {
        return _context.Set<TEntity>().First(predicate);
    }

    public void Add(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentException("Cannot add a null entity");

        _context.Set<TEntity>().Add(entity);
    }

    public void Delete(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentException("Cannot delete a null entity");

        _context.Set<TEntity>().Remove(entity);
    }

    public void Attach(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentException("Cannot attach a null entity");

        _context.Set<TEntity>().Attach(entity);
    }

    #region IDisposable implementation
    private bool disposedValue;

    public void Dispose(bool disposing)
    {
        if (!this.disposedValue)
        {
            if (disposing)
            {
                // dispose managed state here if required
            }
            // dispose unmanaged objects and set large fields to null
        }
        this.disposedValue = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}

Next, we’ll create a concretion for our context using Entity Framework. We’ll inherit DbContext as well as implementing ICustomerContext, and we’ll create both an empty constructor and one that takes a connection string so we can connect to a specific database.

public class CustomerContext : System.Data.Entity.DbContext, ICustomerContext
{
    public CustomerContext() { }

    public CustomerContext(string connectionString) : base(connectionString) { }
}

And that’s all we really need to do.

When we use it, we have to make sure we refer only to our interfaces so we can replace them later if need be.

private ICustomerContext _context;
private IGenericRepository<Customer> _customerRepository;

Ideally, we’d be using Dependency Injection to inject our concretions at runtime, but here’s an example of how you would do it.

_context = new CustomerContext();
_customerRepository = new GenericRepository<ICustomerContext,Customer>(_context);

From there, we can do whatever we need to do with the objects in our repository, and just call SaveChanges() on our context when we’re done. For example:

public ResetCustomerLastLoginDate(int customerId) {
    var customer = _customerRepository.GetSingle(c => c.CustomerId == customerId);
    customer.LastLoginDate = DateTime.Now;
    _context.SaveChanges();
}

Buying a new laptop

With a new financial year comes new gadgets. For me, this means a new laptop to replace the slowly-dying dinosaur weighing down my backpack.

Tech has come a long way since I last made a laptop purchase. I paid a princely sum for the 64 bits and 6GB of RAM Dell I’m carrying around today. Worth it? I think so. It’s given me a good couple of years, despite a dropping a hard drive and a 2GB RAM stick. It still chugs along, but it’s time for a change.

So what to get?

Here are my requirements:

  • Thin and light – call it an ultrabook if you want, but I just want something I can carry without back-pain.
  • At least 8GB RAM – I’ll want to be able to run Visual Studio, SQL Server, and maybe even a VM or two. 8GB is my acceptable minimum.
  • An SSD hard disk – surely I don’t need to spell this out.
  • USB 3.0 – This will let me compliment the SSD with decent storage with decent speeds.
  • Fairly good screen resolution – at least 900px high I think. My current 768px really annoys me.
  • Either 13″ or 15″ – this is my preferred size for a workable laptop.

So what’s on offer?

Well, it turns out not much. The only laptop that really fits the bill in every respect appears to be the new 13″ MacBook Air.

Now I’m clearly not a Mac user so I’d love to hear an alternative if you have one. However, rest assured that if you point me at a Windows machine that nearly meets those specs – I’ve almost certainly seen and dismissed it.

So why would I pay the “Apple-Tax” if I’m not a Mac user? It’s a good question, so here are my current justifications:

  1. What’s the alternative? – Honestly, I haven’t seen any Windows laptop that meets every one of the requirements above. Should I just compromise somewhere? Just to avoid getting a Mac? I’m not that anti-Apple. And sure, I could always wait for the next version of X, but that’s a never-ending game.
  2. Macs can boot into Windows just fine – So if I’m going to boot into Windows, why buy a Mac? Firstly, for reason #1 above. Secondly, maybe I’ll want to wrap an HTML5 app in PhoneGap and deploy to the app store… Who knows :)
  3. Recommendations from friends – many people I know use a MacBook as their primary device and spend most of their time either in Windows (using BootCamp) or using Windows software (using Parallels or VMWare Fusion). Without exception, they’re full of glowing praise. Not, “yeah, it’s pretty good”, but usually, “it’s the best laptop I’ve ever had by a mile”.

Ultimately it comes down to one question for me: If, after 6 months, I never boot into OSX, have I made the wrong decision? Based on the three points above, I’m fairly confident the answer is no.

I know some people feel pretty strongly about this so I’d love your comments. If you think I’m about to make a mistake, let me know why! Seriously. I might even listen.

Upgrading TFS 2010 to TFS 2012 RC – Done

Over the weekend, we decided to take the plunge and upgrade the SSW TFS 2010 instance to the shiny new TFS 2012 release candidate.

Update: for the latest rules for migration, see http://rules.ssw.com.au/TFS/RulesToBetterTFS2012Migration/Pages/default.aspx

From Adam Cogan‘s Blog:

Initially, there was some debate as to whether we should upgrade what is the busiest server in our environment.  One call to Grant Holliday made all the difference and we quickly reached a consensus.  The upgrade was going ahead and Damian Brady was the guy in the hot seat!

There are three main upgrade paths:

  1. Upgrade from a Basic or Express version of TFS
  2. Upgrade in place
  3. Upgrade and move to new hardware (recommended)

We chose option 3 for a few reasons.  We used the opportunity to move to a SQL Server 2012 instance and change our hardware configuration a bit, but more importantly option 3 gave us the simplest rollback path; simply turn off the new server and bring the old one back up, then change any DNS settings back.

It was a very straightforward process (with a few coffee breaks):

  • Before you start – getting the VMs ready
  • Preparation steps – stopping the servers and backing up
  • Installing and upgrading TFS 2012
  • Configuring Reporting Services

The initial feedback from the test developers is extremely positive. They can’t wait to start using it!

I want to mention a couple of great blog posts.  There was a series of blog posts from Tim Elhajj, and of course we could leverage off our Rules to Better TFS 2010 Migration and the related blog posts (firstsecondthird) from Martin Hinshelwood for ideas.

Well done to the TFS team, they’ve really done a great job in this version.

SSW may have a possible claim to fame here – we might be the first company to deploy TFS 2012 RC to live.  I have not seen any blog posts about other companies migrating their live environment yet.  I’m a TFS MVP and nobody on that list has posted about their migration yet.  I’m expecting the punctilious Martin Hinshelwood to send us a nice scotch whisky!

The below is a bit of an epic, but if you’re keen to see how we did it, read on!

More Information

Our existing environment was:

  • Windows 2008 server: TFS 2010, SQL Server 2008
  • Windows 2008 server: SharePoint holding our projects

The new environment is:

  • Windows 2008 R2 server: TFS 2012 RC and a local SharePoint instance
  • Windows 2008 R2 server: SQL Server 2012

Before you start – getting the VMs ready

Thankfully, one of our sysadmins – Daragh – had already set up the servers I’d need, so we had an existing Windows 2008 R2 Server with SQL Server 2012, and a brand new Windows 2008 R2 Server for TFS.  Daragh had also already installed (but not configured) SQL Server Reporting Services and Analysis Services on the TFS box.  TFS no longer supports 32 bit, so it was important we were running 64 bit servers.

Make sure you have administrator access to all the machines you’re going to touch.  It makes it much easier if you’re a domain administrator (I got promoted for the weekend!).

Preparation Steps – stopping the servers and backing up

  1. The first step is obviously to let everyone know that TFS will be offline.
    Have a look at the Rules to Better Networks for guidance on an outage email.
  2. Take the TFS 2010 server offline.
    This is important because we’ll be upgrading from a backup, so any checkins that occur during the process won’t come across!

    1. Use TFSServiceControl quiesce to stop all the agents
    2. Stop relevant network services:
  3. Just to be safe, I also stopped the TFS Application Pools in IIS
  4. Verify that you can’t connect to the TFS server by trying to connect in Visual Studio
  5. At this stage, it’s a good idea to run the awesome DogFood Stats queries from Grant Holliday to get some statistics on your current projects.  Make sure you document these for comparison later.
  6. Backup the TFS and Reporting Server databases.
    We had quite a few relevant databases because there were a few project collections.
  7.  Back up the Reporting Services Encryption Keys.
    We’ll need to use these later to configure our new Reporting Services against the restored databases.
    To back up the encryption key, follow the steps on the MSDN page.
    Note: Make sure you remember the password you use to protect it with – you’ll need it later!
  8. Configure SQL Server Analysis Services to recover on failure.
    On your new TFS Server box:

    1. Go to Start | Administrative Tools | Services
    2. Right-click  SQL Server Analysis Services and choose Properties
    3. Go to the Recovery tab and choose “Restart the Service” for each of the failures.
  9. Move all my database backups  to the new SQL Server 2012 instance.
    This was as simple as copying each of the database backups to the new SQL 2012 server.

Installing and upgrading TFS 2012

  1. Because we’re installing from an ISO rather than a physical CD, we mount the ISO using SlySoft’s Virtual CloneDrive (or your favourite alternative).
  2. Run tfs_server.exe from the installation disk or ISO.
  3. Accept the license terms and click Install Now (because this is an admin operation, you may be given a UAC prompt – obviously, you can accept this)
  4. Watch the progress with excitement and trepidation (and coffee)

    You may get a message asking you to reboot the machine.  If it does appear… restart the machine.

    This made me a little nervous because we were using a virtual machine and a mounted ISO, but everything came back up perfectly and continued from where it left off.
  5. After installing, the Configuration Center will be shown.
    We want to Upgrade from an existing server
  6. We need to restore our TFS databases, so we’ll use the Database Restore Tool presented on the next screen.
  7. Because we’re not using a local database, we’ll change the target server instance so we can connect to our SQL 2012 server.
  8. In the Restore SQL Database screen, choose the folder where you saved your backups.  Note that this will be on your SQL Server if that’s where you put them.
    The tool will find all TFS databases automatically.
    Note: In our case, we want to restore our Reporting Server databases too, so make sure they’re ticked.

    Ensure this is correct, then click Restore.  The tool will restore each of the databases in turn.  When finished, click Close.
  9. The next step asks you to specify a configuration database to upgrade.
    First, we choose our SQL Server 2012 instance, then click List Available Databases
    The tool should find our Tfs_Configuration database automatically.
    We’ll confirm we have a backup, then click Next.
  10. We’re next asked for the service account for our Application Tier
    Network Service is fine for this, so just click Next.
  11. Next up, we’re asked if we want to configure reporting services.  Make sure the checkbox is checked, then click Next.
  12. Make sure the instance and the URLs are correct, and click Next.
    We have a local instance and we kept all the default URLs, so there was nothing to change.
  13. Next up is the TFS Warehouse database
    Because our SQL Server is in a different location, we had to change the instance.  To find the correct database, I tested the connection then listed all available databases. After that, the wizard found the Tfs_Warehouse database automatically.  If everything is correct, click Next.
  14. The Analysis Services are set up on the local TFS machine as well, so nothing needs to change on this screen. It’s a good idea to test using the Test link, however.
    If all is well, click Next.
  15. Next, we’re asked to provide an account that the Reports will run as.  We have a TFSSERVICE account for this specific purpose, so I supplied the credentials and tested successfully, then clicked Next.
  16. Next we’re asked if we want to configure SharePoint for TFS, we do, so we’ll make sure the checkbox is checked and click Next
  17. We want to use our existing SharePoint (installed with TFS), so we’ll leave the default settings and click Next.
  18. On the next screen, we get a summary of all the options we’ve chosen.
    Go through them carefully to make sure everything is as expected, and click Verify to check.

    Note: At this point I got a System Verification error at this point telling me I’d need to reboot before continuing.
    After rebooting… I had to start the wizard again!
    My initial thoughts were:

    But I persisted.
    I had to reboot twice to get past this error, but after that it all went smoothly.
  19. Now we’ve got all green ticks, we can click Configure.

    Configuration will take a little while, but when it’s finished, make sure you get all green ticks then click Next.
  20. Now each of the Project Collections will be updated.  This includes a lot of stuff, so it may take some time.
    Grab a coffee. Maybe go for a jog.

    Once you get a big green tick, click Next.
    Note: The Lab management warning told us it couldn’t tear down any labs.  As we didn’t have any set up, this wasn’t an issue.
  21. At this point, you should run Grant Holliday’s DogFoodStats scripts over the new databases to make sure there are no unexpected numbers.
    Don’t be concerned if the numbers aren’t identical; what you’re looking for is big discrepancies (for example zero checkins).
    All of our stats were either identical to the previous value, or were extremely close.

Configuring Reporting Services

  1. Finally, let’s configure our Reporting Services to work with our restored Reporting Server databases.
    On the TFS server, Go to Start | All Programs | Microsoft SQL Server 2012 | Configuration Tools | Reporting Services Configuration Manager
  2. We’ll change the Server Name to our SQL 2012 instance, click Find, then Connect
  3. Navigate to Database on the left-hand menu, then choose Change Database

  4. Select “Choose an existing report server database” then click Next
  5. Make sure we’re pointing at the correct SQL Server instance, and that testing the connection succeeds, then click Next

  6. Choose the Report Server database you restored in step 8, then click Next
  7. Leave the Credentials page with default settings, then click Next
  8. Review the information on the Summary page, then click Next
    When done, click Finish to complete the process
  9. Now we’ll restore our saved encryption key.
    Navigate to the Encryption Keys section, and choose Restore

  10. Locate the encryption key you backed up earlier, enter the password, then click OK.
    Make sure you get a green tick in the Results section
  11. Click on the Web Service URL section and Apply the default settings

    Make sure the Results section shows green ticks.

    Note: If you’re unable to click Apply, you’ve probably already completed this step. Just skip this step.
  12. Click on the Report Manager URL and Apply the default settings here as well.
    Again, check you get green ticks.
    Note: If you’re unable to click Apply, you’ve probably already completed this step. Just skip this step.
  13. Try out your new URLs by clicking on the hyperlinks in the Web Service URL and Report Manager URL sections.
    If all is well, you can Exit from the Reporting Service Configuration Manager.Aside: I had an issue here where when I navigated to the ReportServer URL, I was given an error saying “The report server installation is not initialized”.
    My solution was:
  1. Navigate back to the Encryption Keys section, Delete all Encrypted content, then restore the Encryption key again.
  2. Navigate to the Web Service URL, make a change to the URL (and change it back), then reapply the settings.
  3. Do the same to the Report Manager URL.

 After that it started working.

Final Steps

A couple more steps were required before we were up and running.  I worked with our trusty SysAdmin Daniel Hyles to get these items sorted out.

  1. Make a DNS change so tfs.ssw.com.au now points to this server’s IP address.
  2. Make changes to the firewall to allow traffic through to this server
  3. In our environment, we had TFS listening on a few different ports (including 443 for SSL).  This meant a bit more configuration in IIS, and some installation of certificates.

Testing

After the final steps were completed, testing went as smoothly as you could imagine.  Visual Studio accepted the new server without a hitch, and all our test developers could Get Latest and Check In without an issue.

To Do

There are a few loose ends that we hope to clear up over the next few days.

  1. In TFS Web Access, it appears that there are no members for any of the projects.  Obviously this isn’t causing an issue, and permission to access the Projects and Project Collections must have come across with the data migration (we made sure it wasn’t a free-for-all), but it seems a bit unusual.
  2. We still need to finish setting up the SharePoint instance that will store all our project documents.
  3. Our Build Servers have not yet been upgraded.  This should be a fairly quick task, however until it’s done, none of our builds will work.
    In particular, this affects our gated checkins.  Because they make sure the project can be built before  a checkin is accepted, they’re stopping us from checking in!
    We’ve turned these off for the moment.

Summary

The upgrade process was fairly straightforward, however there are a few suggestions I’ll give you.

If you’re doing it, I highly recommend you have a trusty SysAdmin involved for the final few steps.  A person like Daniel comes into his own on these occasions and knows exactly what changes to make and how to make them efficiently.  You don’t want a programmer doing that work if you can help it.

One thing we noted was that the URLs that were used to access the old TFS server were carried over in the configuration during the upgrade.  While this was fine for us as we were changing DNS entries to keep everything consistent, I can imagine a common final step would be to change these URLs.  It would have been nice for the wizard to prompt us for settings like that.

The feedback has been given to Brian Harry‘s TFS team so they can add some spit and polish for the RTM version.

Nokia Lumia 800 – Initial Impressions

Nokia Lumia 800 - Front

Nokia Lumia 800 - Front

Yesterday, I visited a Telstra store to pick up a shiny new Nokia Lumia 800. After the OS on my trusty HTC Desire once again catastrophically failed, causing me to wipe it and reflash, it was time for a change.

In the past, I’ve had several Nokia phones running Symbian, a Sony Ericsson or two, one iPhone 3G, and most recently my Android running Froyo then Gingerbread. I’ve never had a Windows phone, and I’ve heard great things about Windows Phone 7.5, so I thought it was time to give it a try.

I’ve had the phone for about 24 hours now, and my impressions have been good for the most part. There are some incredibly impressive aspects to the phone and OS, but there are also a couple of fairly significant flaws with the blame shared between Nokia, Microsoft, and Telstra.

The Good

My first impression upon opening the box was, “This is a very good looking phone.”  It’s sleek and black and feels incredibly well put-together.  Of particular note is the “Clear Black” AMOLED screen.  When on, the blacks are so impressively black that it’s impossible to tell where the screen ends and the black surround starts.  It really helps bind the OS and the device together. Rather than feeling like a hand-held display with software on it, it feels like an integrated device.

Nokia Lumia 800 - Back

Nokia Lumia 800 - Back

The speed of the device is a welcome change as well.  My HTC Desire took minutes from power-button-push to a usable phone; the Lumia takes less than 25 seconds.  Screen transitions and apps are very responsive and there’s no perceivable lag with touches or swipes.  Network connectivity seemed faster as well (even on the same network as the Android), probably due to some combination of the operating system and the hardware.  By the time I walked the device out of the store, I’d already connected the phone to my Google, Facebook, and Twitter accounts, and all my contacts were on the phone.  I had big issues connecting to my work’s Exchange server, but more on that later.

I was initially skeptical of the integrated “People” function on the phone that combines a contact’s details into a single “Person” complete with their Facebook, Twitter, and other accounts.  I had a similar function on my Android and I found it useful, but a bit clunky to operate.

Impressively, the phone identified and correctly linked about 90% of the contacts I had from Google, Facebook, and Twitter.  Almost all contacts had automatically been merged and the decisions around what were the primary details were very sensible.  Each person had an up-to-date profile picture from Facebook as well as all their contact details. In all cases, the correct name was shown (no “John Smith1″ or “johnsmith”).  Linking the few contacts that weren’t automatically merged was extremely fast. By the time I’d done three, I was taking less than 5 seconds to join two contacts together.  This short learning-curve was something that was visible throughout the first 24 hours and reflects very well on the WP7 operating system.

GPS location was impressively fast.  I had been used to a minimum 10 second delay on my android, but the Lumia found me on Bing Maps in a fraction of that time.

Nokia Lumia 800 - Lock Screen

Nokia Lumia 800 - Lock Screen

I was also particularly impressed when I bought an app from the marketplace.  After agreeing to purchase, a message popped up telling me it’d be on my Telstra bill.  This is hands down the most convenient way to purchase an app. No need for another party to be involved when I’m purchasing things for my phone.

The Bad

Exchange.  This one baffles me.  I simply could not connect to our workplace Exchange Server (2010 SP1).  Not for lack of trying, either.  I scoured the web for solutions, spoke at length to our SysAdmins, and installed certificates left, right, and centre.  All to no avail.  I’ve never had this problem in the past; my Android spoke to Exchange like they were best buddies.  I find it inexplicable that Microsoft made the only device that can’t talk to our Microsoft mail server.  It’s a ridiculous situation.

Before you put pen to paper, yes, if you have a Windows Phone 7 (including the Lumia 800), there’s a good chance you have successfully connected to your Exchange server.  I have heard a number of people say they had no problem.  It seems hosted Exchange servers (e.g. Office 365) work fine, and there are workarounds for self-signed certificates.  Our server, however, uses a certificate from a CA (which should be trusted out of the box) and the phone just doesn’t seem to like that.  I’ll keep searching for a solution, but for the moment I’m assuming I just won’t be able to sync with my Exchange account.

Data on the phone has caused me some consternation as well.  While the speeds seem fine, the phone only reports 3G as its maximum network speed.  My Android happily showed an “H” symbol about 90% of the time at home, so I know I’m in an area with HSDPA service, but the Lumia refuses to recognise that it can run anything but 3G or Edge.  I’ve been passed between Telstra and Nokia support quite a few times at this point and nobody can give me an answer.  The phone is definitely the correct variant for Telstra, and the Lumia is capable of showing an “H”, so HSDPA speeds should be possible.

Tethering, while it has been supported by WP 7.5 for some time, has not been enabled on this phone.  Telstra offers nothing but a, “sorry, maybe soon” and no indication of an ETA.  This is a big deal for me. When travelling, my phone is my primary Internet device.  I’ve never bothered with a USB mobile device before and I don’t want to start now.  Telstra have other Windows phones that support tethering, so there’s obviously no technical reason it has to be disabled. They need to sort this out quickly.

Nokia Lumia 800 - Home Screen

Nokia Lumia 800 - Home Screen

The Too Early to Tell

The UI is something I’m still getting used to, but I don’t think it’ll take long before it’s natural.  As I mentioned, the learning curve for performing operations seems short and the OS is consistent throughout.  It’s already growing on me.

I haven’t installed too many apps at this point, but the ones I have installed seem pretty good.  In particular, AU Weather Pro and AFL Season 2012 are fantastic apps.  I haven’t had the opportunity to use Nokia Drive yet, but I’m looking forward to it.

The pre-installed Foxtel Guide app required an update before it would show me any information, and I had to actively search for that update.  I assume other apps will let me know when there is a new version, but it was a bit off-putting.

The battery life seems OK.  It was at about 25% when I unboxed it, so I kept it on charge for most of the day.  At 5pm it was at about 80% and by 10pm it was giving me low battery warnings which seems like a bad sign until you consider I was playing with it almost non-stop.  It’ll be interesting to see how it performs when I lapse into normal use.

Summary

In short, it’s a great phone.  It’s beautiful, fast, and has many impressive features.  Nokia has a fantastic device here, and Microsoft has obviously put a lot of thought and good engineering into WP7.

However the combination of no Exchange and no Tethering is very disappointing.  To be honest, if I’d known about these two issues before I got the phone, I probably would have waited.  Either for them to be resolved, or even for the Lumia 900.

A Generic CRUD Repository for Entity Framework

Update: After a bit more work and discussions with other SSW guys, we’ve put together an updated version of this implementation. Have a read here.

I wrote a post a while ago about using Generics for lookup tables in Entity Framework and I suggested that the idea could be extended to include all objects and CRUD operations.

Well, I’ve put together a generic Repository that can be used in your project to give you a consistent base class for all your repositories. It’s quite long, so sorry about that.

This implementation follows our SSW Rule, Do you use the repository pattern for data access.

public class DataRepository<TContext> : IDataRepository<TContext> where TContext : ObjectContext
{
    // Cached ObjectSets so changes persist
    protected Dictionary<string, object> CachedObjects = new Dictionary<string, object>();
    protected ObjectSet<TEntity> GetObjectSet<TEntity>() where TEntity : EntityObject
    {
        var fulltypename = typeof (TEntity).AssemblyQualifiedName;
        if (fulltypename == null)
            throw new ArgumentException("Invalid Type passed to GetObjectSet!");
        if (!CachedObjects.ContainsKey(fulltypename))
        {
            var objectset = _context.CreateObjectSet<TEntity>();
            CachedObjects.Add(fulltypename, objectset);
        }
        return CachedObjects[fulltypename] as ObjectSet<TEntity>;
    }

    protected TContext _context;
    /// <summary>
    /// Constructor that takes a context
    /// </summary>
    /// <param name="context">An established data context</param>
    public DataRepository(TContext context)
    {
        _context = context;
    }

    /// <summary>
    /// Constructor that takes a connection string and an EDMX name
    /// </summary>
    /// <param name="connectionString">The connection string</param>
    /// <param name="edmxName">The name of the EDMX so we can build an Entity Connection string</param>
    public DataRepository(string connectionString, string edmxName)
    {
        var entityConnection =
            String.Format(
                "metadata=res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl;provider=System.Data.SqlClient;provider connection string=",
                edmxName);

        // append the database connection string and save
        entityConnection = entityConnection + "\"" + connectionString + "\"";
        var targetType = typeof (TContext);
        var ctx = Activator.CreateInstance(targetType, entityConnection);
        _context = (TContext) ctx;
    }

    public IQueryable<TEntity> Fetch<TEntity>() where TEntity : EntityObject
    {
        return GetObjectSet<TEntity>();
    }

    public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : EntityObject
    {

        return GetObjectSet<TEntity>().AsEnumerable();
    }

    public IEnumerable<TEntity> Find<TEntity>(Func<TEntity, bool> predicate) where TEntity : EntityObject
    {
        return GetObjectSet<TEntity>().Where(predicate);
    }

    public TEntity GetSingle<TEntity>(Func<TEntity, bool> predicate) where TEntity : EntityObject
    {
        return GetObjectSet<TEntity>().Single(predicate);
    }

    public TEntity GetFirst<TEntity>(Func<TEntity, bool> predicate) where TEntity : EntityObject
    {
        return GetObjectSet<TEntity>().First(predicate);
    }

    public IEnumerable<TEntity> GetLookup<TEntity>() where TEntity : EntityObject
    {
        return GetObjectSet<TEntity>().ToList();
    }

    public void Add<TEntity>(TEntity entity) where TEntity : EntityObject
    {
        if (entity == null)
            throw new ArgumentException("Cannot add a null entity");

        GetObjectSet<TEntity>().AddObject(entity);
    }

    public void Delete<TEntity>(TEntity entity) where TEntity : EntityObject
    {
        if (entity == null)
            throw new ArgumentException("Cannot delete a null entity");

        GetObjectSet<TEntity>().DeleteObject(entity);
    }

    public void Attach<TEntity>(TEntity entity) where TEntity : EntityObject
    {
        if (entity == null)
            throw new ArgumentException("Cannot attach a null entity");

        GetObjectSet<TEntity>().Attach(entity);
    }

    public void SaveChanges()
    {
        SaveChanges(SaveOptions.None);
    }

    public void SaveChanges(SaveOptions options)
    {
        _context.SaveChanges(options);
    }

    public void Refresh<TEntity>(TEntity entity) where TEntity : EntityObject
    {
        _context.Refresh(RefreshMode.StoreWins, entity);
    }

    public void Refresh<TEntity>(IEnumerable<TEntity> entities) where TEntity : EntityObject
    {
        _context.Refresh(RefreshMode.StoreWins, entities);
    }

    #region IDisposable implementation
    private bool disposedValue;
    protected void Dispose(bool disposing)
    {
        if (!this.disposedValue)
        {
            if (disposing)
            {
                // dispose managed state here if required
            }
            // dispose unmanaged objects and set large fields to null
        }
        this.disposedValue = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}

A lot of code to be sure, but you only need one of these. After that, whenever you create a new EDMX, you can create a Repository that inherits from this base repository.

Let’s look at using it for the same AdventureWorks repository I used last time:

An Adventure Works Entity Model

An Adventure Works Entity Model

Here’s how you might implement a repository for this data model:

public class AdventureWorksRepository : DataRepository
{
    public AdventureWorksRepository(string connectionString) : base(connectionString, "AdventureWorksEntities") { }
}

Yep, seriously. That’s it. Now you have access to all your common CRUD operations (as well as Linq queries) and can do things like this:

var repository = new AdventureWorksRepository(MyConnectionString);

// return all states and provinces
var states = repository.GetAll<StateProvince>();

// get states and provinces with a three letter code
var threeLetterStates = repository.Fetch<StateProvince>()
                                  .Where(s => s.StateProvinceCode.Length == 3)

// get a customer
var cust = repository.GetSingle<Customer>(c => c.CustomerID == 1);

// delete that customer
repository.Delete(cust);

// get a contact
var contact = repository.GetSingle<Contact>(c => c.ContactID == 1);

// edit some properties
contact.Title = "Mr";
contact.Phone = "61 411 111 111";

// save all the changes (this will save the customer deletion and the updated contact)
repository.SaveChanges();

So just by inheriting a base repository class, you can get some really powerful behaviour which is specific to your data model.

I’d be interested to hear your thoughts on this technique, particularly if you try it in your own project.

Next Page »