Create Model

The application depends on a fairly straight-forward model:

Class Diagram

ExoModel must be made aware of this model.  In order to initalize the framework, the CreateContext event must be handled.  In this event, ExoModel requires that a TypeProvider must be created and passed into the Model Context.  TypeProviders in ExoModel serve the purpose of acting not only as a metadata provider, but enabling eventing for model instances.

In this example, Afterthought is used to modify, or amend, the model classes at build-time to provide hooks for instance creation and property gets/sets.


  1. Create a folder called Models in the root of the TodoApp project:
  2. Add a class called List to the model using the following code snippet:
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using ExoRule.DataAnnotations;
    
    namespace TodoApp.Models
    {
    	public class List
    	{
    		public int Id { get; set; }
    
    		[Required]
    		public string Name { get; set; }
    		
    		[Required]
    		public int Sequence { get; set; }
    
    		public virtual User User { get; set; }
    
    		public virtual ICollection<ListItem> Items { get; set; }
    	}
    }
    
  3. Add a class called ListItem to the model using the following code snippet:
    using System;
    using System.Linq;
    using System.ComponentModel.DataAnnotations;
    using ExoModel;
    using ExoRule;
    using ExoRule.DataAnnotations;
    
    namespace TodoApp.Models
    {
    	public class ListItem
    	{
    		public int Id { get; set; }
    
    		[Required]
    		public string Description { get; set; }
    
    		[Required]
    		public int Sequence { get; set; }	
    			
    		public virtual List List { get; set; }
    
    		[Required]
    		[DisplayFormat(DataFormatString = "d")]
    		public DateTime? DateCreated { get; set; }
    		
    		[DisplayFormat(DataFormatString = "d")]
    		public DateTime? DueDate { get; set; }
    
    		[AllowedValues("Priority.All")]
    		public Priority Priority { get; set; }
    	}
    }
    
  4. Add a class called Priority to the model using the following code snippet:
    using System.Linq;
    using System.ComponentModel.DataAnnotations;
    
    namespace TodoApp.Models
    {
    	public class Priority
    	{
    		public int Id { get; set; }
    
    		[Required]
    		public string Name { get; set; }
    		
    		[Required]
    		public int Sequence { get; set; }
    
    		public static Priority[] All
    		{
    			get
    			{
    				return TodoContext.Current.Priorities.ToArray();
    			}
    		}
    	}
    }
    
  5. Add a class called User to the model using the following code snippet:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ComponentModel.DataAnnotations;
    using ExoRule;
    
    namespace TodoApp.Models
    {
    	public class User
    	{
    		public int Id { get; set; }
    
    		[Required]
    		public string Name { get; set; }
    		
    		public virtual ICollection<List> Lists { get; set; }		
    	}
    }
    
  6. Add a class called TodoContext to the model using the following code snippet:
    using System.Data.Entity;
    using System.Data.Entity.ModelConfiguration.Conventions;
    using ExoModel.EntityFramework;
    using ExoModel;
    using ExoRule;
    using ExoRule.DataAnnotations;
    
    namespace TodoApp.Models
    {
    	public class TodoContext : DbContext
    	{
    		public DbSet<List> Lists { get; set; }
    		public DbSet<User> Users { get; set; }
    		public DbSet<Priority> Priorities { get; set; }
    		public DbSet<ListItem> ListItems { get; set; }
    
    		public static TodoContext Current
    		{
    			get
    			{
    				return (TodoContext) ((EntityFrameworkModelTypeProvider.EntityModelType) ModelContext.Current.GetModelType<List>()).GetObjectContext();
    			}
    		}
    
    		public TodoContext()
    			: base("TodoContext")
    		{
    			Configuration.LazyLoadingEnabled = true;
    		}
    
    		protected override void OnModelCreating(DbModelBuilder modelBuilder)
    		{
    			modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    		}
    	}
    }
    
  7. Add the following snippet to the bottom of the MvcApplication.Application_Start() method in the Global.asax.cs file:
    			Database.SetInitializer<TodoContext>(new DropCreateDatabaseAlways<TodoContext>());
    			new ModelContextProvider().CreateContext += (source, args) =>
    			{
    				Assembly coreAssembly = typeof(MvcApplication).Assembly;
    				args.Context = new ModelContext(new EntityFrameworkModelTypeProvider(() => new TodoContext()));
    
    				ExoRule.Rule.RegisterRules(coreAssembly);
    			};
    
    			if (!TodoContext.Current.Priorities.Any())
    			{
    				var priority = ModelContext.Create<Priority>();
    				priority.Sequence = 1;
    				priority.Name = "High";
    
    				priority = ModelContext.Create<Priority>();
    				priority.Sequence = 2;
    				priority.Name = "Medium";
    
    				priority = ModelContext.Create<Priority>();
    				priority.Sequence = 3;
    				priority.Name = "Low";
    
    				TodoContext.Current.SaveChanges();
    			}
    
  8. Resolve references in the newly added code to include missing using statements.
  9. Add the ASP.NET App_Data folder to the project to store the local database:

  10. Update the web.config file to add a connection string for the application's database:

    <connectionStrings>

       <add name="TodoContext" connectionString="DataSource=|DataDirectory|TodoApp.sdf" providerName="System.Data.SqlServerCe.4.0" />

    </connectionStrings>