Ayende @ Rahien

Unnatural acts on source code

Development only code

Occasionally I need to do development stuff things that are potentially destructive.

The ResetDatabase action will blow away the database, which I need to do for tests and when I am making big changes. But what I absolutely does not want is to have in production.

image

My method is to require three different things to be true to enable this:

  • You must issue a local request (so you are physically on the machine where the system is sitting).
  • You are logged on as a user and as an administrator (that is the superAdmin part).
  • You are running on a debug build.

Hopefully, I won’t blow the production database.

Comments

Set
11/03/2009 10:13 AM by
Set

I would never dare to do such considering our current process ( label/tag / documents up to date, yet the integration team didn't use the right files...).

Seth Petry-Johnson
11/03/2009 12:59 PM by
Seth Petry-Johnson

I like the idea here, although I'm a bit confused as to why you're using a controller action to drop and recreate the db. Normally I would do that via some sort of script... I guess doing it your way adds some extra protection against dropping the production db, but at the cost of less scriptable dev and qa deployments.

Regardless, I like the idea of checking for a debug build before doing certain tasks.

Jason Y
11/03/2009 01:09 PM by
Jason Y

Like unit tests, I like to keep this sort of thing in a module that is never deployed to production.

David Thibault
11/03/2009 01:37 PM by
David Thibault

We do something similar so that our automated (selenium) tests can reset the database to a known state at will. The code that does the reset is hosted in a separate assembly that is not deployed to production.

Fabio Maulo
11/03/2009 02:00 PM by
Fabio Maulo

I never do that because I don't deploy the test project where such kind of things happens.

configurator
11/03/2009 06:06 PM by
configurator

I'd usually keep the Drop Database/Drop tables as a commented out script so in order to do it I need to open the file, uncomment, and run it. That way it's completely impossible to accidentally do that in production.

Of course, the commands to fix the database once it's dropped can be in a controller, assuming they're non-destructive. I usually work in WinForms now, so I'd make it a command that only works fixes an invalid state - I'd cause the invalid state manually for super protection.

Rafal
11/03/2009 06:41 PM by
Rafal

Some time ago I've been doing some experimental changes to a test database before deploying it to production server. And I had two remote desktops open - one for test server and one for production. While overwriting some data I realized I'm in the wrong desktop, accidentally I have run some update on production. Spent rest of the night and half of next day cleaning up the mess. From that time all production server desktops have red background and test server desktops have green background (and I don't usually log on to test & production at the same time)

Chris Smith
11/03/2009 07:53 PM by
Chris Smith

I do this using a "provisioning page", neatly titled provision.aspx. It exports the schema using NH and sticks default data in. I use a GUID to unlock the page, which much match the one in the web.config. There is a big ugly button which says "export schema" and a big label which displays the host name of the machine.

The main benefit is that when it has been provisioned, the provision.aspx file can be removed and there is no way to run the code at all.

I rarely update a schema so I haven't found the need to write some upgrade/migration scripts into it all.

This has been used to shift 5 products in the dev environment and in production now without any problems.

alwin
11/03/2009 08:24 PM by
alwin

@configurator

What if you forget to comment it back?

Steve Py
11/03/2009 09:31 PM by
Steve Py

Assuming one additional assertion:

That your development environment is physically unable to be connected to a production database.

Stuff like that has stung me in the past where to analyse a production system we could hook the dev environment in to production data. (Small company, no $ to set up more than bare-bones test environments.) If you can configure a connection string from a dev/testing environment to the production database then you'll probably want to consider that. Not that anyone would purposefully run that if testing against production, but what about when they forget to set it back.

I'd consider also asserting the connection settings against known test environment addresses/hosts.

Chad
11/03/2009 11:03 PM by
Chad

Hopefully, I won’t blow the production database.

Ha, I did that once, that wasn't a fun day....

And I had all those same constraints on that controller. Never underestimate the power of stupidity.

Micady Elite
11/03/2009 11:19 PM by
Micady Elite

Is there any good link how to test against database? Sample?

No google answer please. I did.

Thanks.

Franz See
11/04/2009 12:15 PM by
Franz See

This is very very very dangerous! My personal advice, remove it ASAP!

First of all, that's a very huge risk for a little convenience. A lot can go wrong. And secondly, even if the development-behavior is not critical, you are basically cheating your behavior by putting it into an ideal state instead of actual scenarios. If you're going to fake something, fake the collaborators/dependencies and not your actual system under test.

I would suggest you move that to a script somewhere. Also, I would highly advice that the db user you're going to be using does not have the permission to run such actions against your production database.

Lastly, I would suggest you do a bit of Unit Testing. Your unit tests would show you your unnecessary dependencies, forcing you to decouple them making it easier for testing (automated or manual).

Franz See
11/04/2009 12:23 PM by
Franz See

There are several ways:

First, if you can decouple your code from the database - do so. It will make your testing easier & faster...not to mention you will have distinct separation of concerns (i.e. from business logic to datasource acess).

Secondly, if you're working on your actual database unit, there are several options you can choose from in terms of your setup-teardown:

Where to do setup-teardown:

a.) Before and after each tests,

b.) Before and after each group of tests (i.e. unit test suite, integration test modules, etc)

How to teardown

a.) You drop table/database and recreate (making sure that all data are deleted) with initial fixtures (safe but slow),

b.) You delete data that was inserted (this is hard to track. faster than a but less safe)

c.) Rollback (fastest way to teardown but hinders you from testing db units which does commits)

Also, if you're going to be doing database testing that inserts/updates data, I highly recommend you do it against a database you own / control. Doing it on a shared database (i.e. in your intra ) runs the risk of corrupting other people's data.

Chris Wright
11/04/2009 02:00 PM by
Chris Wright

@Franz

A project I work on has unittests where the setup method drops and recreates the database. They run pretty quickly: 364 tests in 22 seconds. For most people, there's no need to worry about speeding up tests.

Chris C
11/04/2009 08:03 PM by
Chris C

I personally prefer to use permissions, standard developer accounts cannot write to the production database.

The production web service doesn't have permission to alter the database structure, only manipulate the data in it.

Obviously this is an extra line of defense as I've found it to be better to not try and drop the production database in the first place.

Comments have been closed on this topic.