Introduction
Database and
Administrator are static classes, and since we don't generate code, you usually save, retrieve and query objects with a certain level of ignorance of how the database looks (
Schema), or where it is physically located (connection string).
Not having to pass the connectionString and the
Schema as a parameter all the time doesn't mean that you don't have the flexibility to change it when you think it is convenient. In order to change the connection in a region of your code just use ConnectionScope.
Connection class
You can think in a Connection class like the container that has all the information to access a specific database in a database server:
- The connectionString.
- The Schema.
Internally, Connection class is also the only gateway to access the database, it's not intended to be used by client code.
Executor static class is what should be used if you want low-level ADO.Net access through the current connection.
There's really a small inheritances hierarchy involving connections:
- BaseConnection: Abstract class that contains the Schema.
- MockConnection: A very simple connection that just stores all the executed commands in
ExecutedCommands property, returning 0 or null as the result of any call. Useful for testing without a database or generating scripts. - Connection: The only Connection that actually is able to connect to the database. It needs a connection string and has other properties that will be used as default settings for the connection:
- CommandTimeout: Default timeout for the SqlCommands sent to the database when no CommandTimeoutScope is taking effect.
- IsolationLevel: Default IsolationLevel for the connection when no Transaction has overridden this value.
Snapshot is a really cool isolation level, but you have to
turn it on to use it, so is not the default.
Also, BaseConnection defines the ThreadStatic field (and property) CurrentLog. The logger is just a TextWriter, so you can plug Console.Out into it to easily see what's being sent to the database.
Connection.CurrentLog = Console.Out;
ConnectionScope class
ConnectionScope is the class that switches the current connection in an region of your code using the
Scope pattern.
There's a
ConnectionScope.Default {get; set;} static property (
not ThreadStatic) that serves as a fall-back value when no connection scope is found.
Usually you only have Signum Engine using one Connection in an application, so this Default property will be the only thing you are going to use in ConnectionScope class
Finally, the
ConnectionScope.Current{get;} property is the one used when any database-related operation is done in the framework.
Use this to access the current database.
Example
Let's make some easy examples first:
SchemaBuilder sb = new SchemaBuilder();
sb.Include<BugDN>();
sb.Include<TypeDN>();
ConnectionScope.Default = new Connection("Data Source=localhost;Initial Catalog=BugTracking;Integrated Security=True", sb.Schema);
BugDN bug = Database.Retrieve<BugDN>(3);
A more complex case will have an alternative database, with a different connection string and schema:
public static class GlobalResources
{
static Connection ZooDatabase;
}
SchemaBuilder sb = new SchemaBuilder();
sb.Include<BugDN>();
sb.Include<TypeDN>();
ConnectionScope.Default = new Connection("Data Source=localhost;Initial Catalog=BugTracking;Integrated Security=True", sb.Schema);
SchemaBuilder sb2 = new SchemaBuilder();
sb2.Include<AnimalDN>();
sb2.Include<TypeDN>();
GlobalResources.ZooDatabase = new Connection("Data Source=zooServer;Initial Catalog=ZooManagement;Integrated Security=True", sb2.Schema);
BugDN bug = Database.Retrieve<BugDN>(3);
using (new ConnectionScope(GlobalResources.ZooDatabase))
{
Database.Retrieve<LionDN>(23);
}