Skip to content
JaCraig edited this page Dec 10, 2014 · 1 revision

On top of everything else, CUL has a built in ORM. It's still a work in progress and only supports SQL Server and LDAP currently. However the system has been reworked in such a way that adding different databases or other items, such as AD or WMI, will be possible. Also note that if you were using SQLHelper before, this has been removed. Instead a QueryProvider static class has been added. This class contains a function called Batch. This returns an IBatch type that is used to make combining multiple queries together into one much simpler than before:

IList<IList<dynamic>> Results = Utilities.ORM.QueryProvider.Batch("ConnectionString")
                                                 .AddCommand(null, null, CommandType.Text, "SELECT * FROM Table")
                                                 .AddCommand(null, null, "SELECT * FROM Table WHERE ID=@0", CommandType.Text, 10)
                                                 .Execute();

Results in the above code is a list that contains the results from both queries. Each of these results is a list of Dynamo objects which can then be converted to whatever type you need. The Batch command takes either the connection string itself or the name of a connection string from the config file for the application. There are more familiar features in other ORMs:

  • Automatic migration of database structure at run time
  • Cascading saves, deletes, etc.
  • Lazy loading of properties

In order to use these features you need to define a couple of things:

  • Database configuration
  • Model
  • Model mapping

The database configuration is fairly straightforward:

/// <summary>
/// Example database config
/// </summary>
public class DatabaseConfig : IDatabase
{
    /// <summary>
    /// Should audit tables be set up for the database
    /// </summary>
    public bool Audit { get { return true; } }

    /// <summary>
    /// Name of the connection string (from the web.config or app.config file) to use
    /// </summary>
    public string Name { get { return "Default"; } }

    /// <summary>
    /// Order to initialize the database in
    /// </summary>
    public int Order { get { return 1; } }

    /// <summary>
    /// Is this a readable source?
    /// </summary>
    public bool Readable { get { return true; } }

    /// <summary>
    /// Should the database structure be updated at run time?
    /// </summary>
    public bool Update { get { return true; } }

    /// <summary>
    /// Is this a writable source?
    /// </summary>
    public bool Writable { get { return true; } }
}

The next item is the model. These are simple POCO objects for the most part. If you want lazy loading to work though, all properties that point to other models or list of models need to be virtual. Otherwise it's just a POCO. The last item is the model mapping class:

/// <summary>
/// Example company mapping
/// Note that the base class is MappingBaseClass and you specify the Company model
/// and you tell it to use the DatabaseConfig that we specified earlier.
/// </summary>
public class CompanyMapping : MappingBaseClass<Company, DatabaseConfig>
{
    /// <summary>
    /// Constructor (where all the actual mapping occurs)
    /// </summary>
    public CompanyMapping()
        : base()
    {
        // Does a many to one mapping and is set to cascade on save/delete
        ManyToOne(x => x.Addresses).SetCascade();
        // Does a many to many mapping
        ManyToMany(x => x.Employees);
        // Does a many to one mapping and is set to cascade on save/delete
        ManyToOne(x => x.Images).SetCascade();
        //Sets up a reference (all basic types like strings) with a max length of 64 and it can not be null
        Reference(x => x.Name).SetMaxLength(64).SetNotNull();
        // Does a many to one mapping and is set to cascade on save/delete
        ManyToOne(x => x.Notes).SetCascade();
        // Does a map mapping which is basically a one way one to one mapping.
        Map(x => x.Status);
        // Does a map mapping which is basically a one way one to one mapping.
        Map(x => x.Type);
        // Does a many to one mapping.
        ManyToOne(x => x.Subsidiaries);
        // Does a many to one mapping.
        ManyToOne(x => x.ParentCompany);
    }
}

There are a number of things that you can specify such as indexes, if a column should be unique, etc. And that's it. With those three items the ORM is set up. Note that multiple mappings can be specified for a model and will be used to compose the model. So for instance you can specify two databases and it will load information from both into the same model.

Clone this wiki locally