Setting default values for Complex Properties - Backfilling database

737 views Asked by At

I have an MVC site using code first migrations which contains an Object called "Organisation" as below:

public class Organisation
{

    public int Id { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }
    public virtual ICollection<Contact> Contacts { get; set; }
    public virtual ICollection<Location> Locations { get; set; } 
    public UserPermissions Permissions { get; set; }

}

And I am trying to implement user permissions for each of the areas on my site. As a result the Permissions property has been newly added above and is an object of type UserPermissions:

public class UserPermissions
{
    public PermissionLevel Contacts { get; set; }
    public PermissionLevel Messages { get; set; }
    public PermissionLevel Groups { get; set; }
    public PermissionLevel Data { get; set; }
}

Where PermissionLevels is an enum defined as:

public enum PermissionLevel
{
    Locked = 0,
    View = 1,
    Administrator = 2
}

I feel the structure of this implementation is fine and upon adding the migration EF creates a column in my dbo.Organisations table for each permission type (Permissions_Contacts, Permissions_Messages etc.).

The database however already has many Organisations and I wondered if there was a way of imposing a default. If I updated my database now all Permissions would be 0 (Locked), however I'd like the default to be different for each Permissions category e.g. Administrator rights for Contacts/Messages/Groups and Locked rights for Data because Data will be set up as and when a user requests it.

I will soon add functionality to the Admin tier of the site where the Organisations are created, and make the selection of UserPermissions mandatory for all areas, but I'd prefer not to have to go back through and manually change all permissions of the existing Organisations to be my defaults.

Is there a way of automatically imposing these defaults for the existing organisations within the database?

1

There are 1 answers

3
Kritner On

Could you just set your default permissions in the constructor of your Organisation or UserPermissions object?

Something like:

public UserPermissions()
{
    Contacts = PermissionLevel.Locked;
    // etc
}

or

public Organisation()
{
    this.Permissions = new UserPermissions();

    if (this.Id == 0) // new object not yet persisted
    {
        this.Permissions.Contacts = PermissionLevel.Locked;
        // etc
    }
}

Based on comments:

For filling the existing data that is now out of sync with your model, you'll want to update your migration script to populate the new properties in your "up" script (the "down" script should not need modification I wouldn't think).

Basically in your up script you can either write update sql statements, or iterate through the objects via the context to manipulate their values in a more strongly typed manner.

Here's some information on getting started with migration scripts:

http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/migrations-and-deployment-with-the-entity-framework-in-an-asp-net-mvc-application

I think your Up method could be modified to have something like this near the end:

using (MyContext context = new MyContext)
{
    var orgs = context.Organisation;
    foreach (Organization org in orgs)
    {
        org.Permissions = new UserPermissions()
        {
            Contacts = PermissionLevel.Locked,
            // etc
        }
    }

    context.SaveChanges();
}