2009/08/01

ActiveRecord 2.0

Finally it’s final. I just created the ActiveRecord 2.0 zipfile.

It can be downloaded at SourceForge. This release includes the NHLinq 1.0 release.

Have Fun!

2009/07/29

ActiveRecord Fluent Configuration

Earlier this morning I committed a first spike of code to the actual (post 2.0) trunk of ActiveRecord. This fluent configuration shows a lot of features I am planning for 2.x releases.

Let’s take a look at the new syntax. This one is for ActiveRecord itself and mere syntactic sugar:

    1 IActiveRecordConfiguration configuration = Configure.ActiveRecord

    2     .ForWeb()

    3     .Flush(DefaultFlushType.Leave)

    4     .UseThreadScopeInfo<SampleThreadScopeInfo>()

    5     .UseSessionFactoryHolder<SampleSessionFactoryHolder>()

    6     .MakeLazyByDefault()

    7     .VerifyModels()

    8     .RegisterSearch();

The following code is however more interesting. It does not only show how AR is currently configured, but also which features will become available soon:

    1 IStorageConfiguration configuration = Configure.Storage

    2     .For

    3         .AllOtherTypes()

    4         .MappedBy(new XmlNhibernateMapping()

    5             .InAssemblyOf<OneOfMyEntities>())

    6     .As

    7         .ConnectionStringName("a_string")

    8         .Driver<SqlClientDriver>()

    9         .ConnectionProvider<DriverConnectionProvider>()

   10         .Dialect<MsSql2005Dialect>()

   11         .ProxiedBy<ProxyFactoryFactory>()

   12         .ShowSql();

The first thing to note is the interface IStorageConfiguration. Each storage configuration will be used to create a NHibernate SessionFactory.

The storage configuration consists of two parts: The database configuration is syntactic sugar for the current NHibernate configuration strings, which are a pain in the neck especially if you need to declare types.

The more interesting part is the storage type selection. The part begins in line 2 by using the For-property. The storage type selection allows you to specify which types should use the session factory created by the storage configuration and how they are mapped.

The selection above contains all classes that are not explicitly added to another storage configuration (line 3) and it says that these types are mapped using classic NHibernate mapping files (line 4) which should be loaded from a given assembly (line 5).

Line 6 finally switches back to the storage configuration.

Storage Type Selections

The storage type selection shown above is effectively a specification pattern for types. Its existence shows to consequences for future versions of ActiveRecord:

  1. You can distribute your classes among multiple databases without the need of a common abstract baseclass. It will be possible to select the types for a storage by namespace, assembly, supertype, interfaces implemented or simply by enumerating them in the storage type selection.
  2. ActiveRecord attributes will be only one option to map persistent types. Types mapped by HBM files or Fluent NHibernate will become first class citizens of ActiveRecord.

The specification patternfor storage type selection allows more complex combinations than currently shown. Here is another example:

    1 IStorageConfiguration auditConfig = Configure.Storage

    2     .For

    3         .SubtypesOf<AuditType>()

    4         .InNamespaceOf<DefaultAuditorType>() // logical and

    5         .MappedBy(new FluentNHibernateMapping()

    6             .InAssemblyOf<MyMappingClass>())

    7     .And // Logical or - we start the next StorageTypeSelection

    8         .TypesInAssemblyOf<MessagingImpl>()

    9         // No MappedBy defaults to ActiveRecord attributes

   10     .As

   11         .DefaultsFor<MsSqlServer2000Configuration>()

   12         .ConnectionString("server=bla;...");

Multiple selections can be created by using the And-property (line 7). Since the storage configuration holds an arbitrary number of storage type selections, this allows for a logical-or-construct. It also allows mixing different mapping types. In the example the first selection is mapped with Fluent Nhibernate (lines 5-6) and the second one with ActiveRecord attributes (line 9).

It is also possible to narrow down type selections by adding multiple specifications to a single type selection (lines 3 and 4). This means that only types are selected that satisfy all specifications. In the example only types are selected that inherit from AuditType and are in the same namespace as DefaultAuditorType.

Storage Configuration

The storage configuration (where the database is configured) is not yet as clearly defined as the storage type selection.

But it will contain default values for most database systems, a templating mechanism and special subconfigurations for fluently defining behaviour needed only occasionally, such as NHibernate Search configurations.

Does this work yet?

No. I just implemented enough to compile and run some simple tests. The features shown above will go into AR 2.1 and AR 2.2.

This article is mainly a showcase for the planned functionality. Suggestions, critic and patches are always welcome.

2009/07/21

ActiveRecord Release Candidate

 

RC 1 of ActiveRecord 2.0 is now available on SourceForge.

Unless serious bugs are found within, this version will be released as ActiveRecord 2.0 RTM on August, 1st.

2009/07/14

German Blog reactivated

 

My german blog is here.

ActiveRecord Beta 1 released

 

The first beta of ActiveRecord 2.0 has been released last weekend. You can get it from Sourceforge.

Changes

Beta 1 took about two months to complete, mostly due to the number of last minute additions to the 2.0 release. The highlights are:

In-Memory-Testing

It’s now possible to test your schema without hitting a database. Inherit from our base class to specify your favorite framework’s infrastructure and the classes/assemblies to test:

    1 public class TestBase : InMemoryTest

    2 {

    3     public override Type[] GetTypes()

    4     {

    5         return new [] {typeof(Blog), typeof(Post)};

    6     }

    7 

    8     [SetUp]

    9     public override void SetUp()

   10     {

   11         base.SetUp();

   12     }

   13 

   14     [TearDown]

   15     public override void TearDown()

   16     {

   17         base.TearDown();

   18     }

   19 

   20     public override IDictionary<string, string> GetProperties()

   21     {

   22         return new Dictionary<string, string>() { {"show_sql", "true"} };

   23     }

   24 }

You can then simply create tests that don’t need a database:

    1 [TestFixture]

    2 public class CRUDTests : TestBase

    3 {

    4     [Test]

    5     public void Create()

    6     {

    7         var blog = new Blog { Name = "Blog" };

    8         blog.Save();

    9 

   10         var post = new Post { Title = "Post", Blog = blog };

   11         blog.Posts.Add(post);

   12 

   13         blog.Save();

   14     }

   15 }

Note: The tests shown above have no app.config altogether!

Basic LINQ Support

The formerly contrib project Castle.ActiveRecord.Linq has been added to ActiveRecord.

Please note that the underlying NHLinq implementation is not fully implemented. Some features are still missing, i. e. joins between unrelated entities.

NHSearch integration

If you want to search your entities, NHSearch is the right project for you. The current release simplifies usage within ActiveRecord by registering the listeners for you when you add searchable=”true” to your ActiveRecord-configuration.

More on using NHSearch can be found on this wiki page

2009/06/05

Understand ActiveRecord mapping: Collections of simple objects

Recently I had a post in the Castle user’s group about mapping a collection of enums with ActiveRecord. Since I know it’s just as mapping other simple types, I only referred to the documentation of the Element and ElementType properties of the HasMany attribute.

But, it turned out it is not really clear to many how to map a collection of simple values using HasMany. Therefore I decided to prepare an explanatory post, which is what you are reading now.

Mapping Basics

The problem: I want to hold a collection of enum values, say I have a status enum and want a history of that status persisted. Here is my model:

namespace EnumMapping
{
	[ActiveRecord]
	public class Article
	{
		[PrimaryKey]
		public virtual int Id { get; set; }

		[Property]
		public virtual string Author { get; set; }

		[Property]
		public virtual string Title { get; set; }

		[Property]
		public virtual Status CurrentStatus { get;set;}

		[HasMany(...)]
		public virtual IList StatusHistory
		{
			get { return statusHistory; }
			set { statusHistory = value; }
		}
		private IList statusHistory = new List();

	}

	public enum Status
	{
		None, Planned, InWriting, InEditing, Released 
	}
}

The ellipsis in the HasMany attribute is by design. I will work out in this post what you have to put here, so I let it out to make you understand the post, and not just read the code and copy and paste it.

To understand what information ActiveRecord requires to map this collection, we first will take a look into how these collections are saved in the database:

image

As expected, we have to tables. The Article table stores all the simple properties, but it cannot store collections. In a relational model, collections are always modeled by foreign key relations. That means we need a second table that stores both the values and the link to the article in question.

Note: You might have noticed that the StatusHistory table does not have a primary key. This is because of the bag semantics we currently have for this collection. More efficient semantics are shown later.

Looking at the StatusHistory table again, we see what we have to tell ActiveRecord to fetch the values for us and populate our List:

What is the table’s name?

 image

We take that name and put it into the respective property of the HasMany attribute:

[HasMany(Table="StatusHistory",
	...)]
public virtual IList StatusHistory {...}

As you can see from the code, we are not through yet.

Which column refers to the article?

image

[HasMany(Table = "StatusHistory",
	ColumnKey = "article",
	...)]
public virtual IList StatusHistory {...}
Which column holds the value?

image

[HasMany(Table = "StatusHistory",
	ColumnKey = "article",
	Element = "status",
	...)]
public virtual IList StatusHistory {...}

What? There is even more to specify even though we already have all columns included?

Yes. ActiveRecord also needs to know the types of the columns. The foreign key’s column can be inferred from the types primary key, but we need to know what type the value actually has.

[HasMany(Table = "StatusHistory",
	ColumnKey = "article",
	Element = "status",
	ElementType = typeof(Status))]
public virtual IList StatusHistory {...}

That’s it (for now). We now can take that mapping and go for the database.

The Collection Types

I already mentioned the missing primary key on the collection’s table and that the collection uses bag semantics. So what are these semantics? There are a few available in ActiveRecord:

  • Bag: All elements are unordered and may appear multiple. Total chaos.
  • Set: The elements are unordered, but each one can be present only once. This is the typical relational collection.
  • List: Elements are ordered and may be there multiple times.
  • Dictionary: Elements have a key that identifies them.

If the collection type is not specified, ActiveRecord assumes that you want bag semantics. After all, that’s what a collection is. Put things in there and get them out. No one cares for ordering or duplication.

Unfortunately, this is quite inefficient with databases:Items in a bag cannot be updated individually. Recall that there is no primary key in the collection table. Since the value can be in the collection more than once, an update or delete would effect all rows with that value. As a result, every time the collection is updated, it is completely deleted from the DB and inserted again.

To get around this, we could use a set. However, this requires us to use another Collection type, Set<Status> from Iesi.Collections. So instead of a set, I will use a list semantic. This is suitable, because a status history has an implicit ordering.

To use the list semantic, the schema must be changed first, because an index column is needed to store the list’s index.

image

We now don’t have only an additional column, we also have a nice primary key consisting of the combination of the article’s id and the list’s index. So every value in the list can now be updated individually.

Now we must tell ActiveRecord to use list semantics and how to find the index:

[HasMany(Table = "StatusHistory",
	ColumnKey = "article",
	Element = "status",
	ElementType = typeof(Status),
	RelationType = RelationType.List,
	Index = "idx")]
public virtual IList StatusHistory {...}

That’s it.

2009/05/08

ActiveRecord Alpha Release

 

You will have already heard it: It is release season in the Castle’s domain.

The newest release is ActiveRecord 2.0 Alpha 1, recently uploaded to http://groups.google.com/group/castle-project-users/web/ActiveRecord2.0Alpha1.zip

This release includes a lot of breaking changes with regard to the last release, ActiveRecord 1.0 RC3, which is the main reason for going through a new complete release cycle starting with alpha releases.

This release includes a move from NHibernate 1.2 to NHibernate 2.1. Please make sure to read the Changes.txt and start testing early.

Bugs can be posted at donjon and last-minute-features can be suggested at UserVoice.

There is no feature freeze yet: All suggestions on UserVoice that get 15+ votes there until May 17th, will be considered for addition in Alpha 2. If no features take this hurdle, I will move forward to Beta 1.

2009/04/23

Understanding ActiveRecord Sessions 2

This article series deals with the internal session keeping of Castle ActiveRecord. This installment introduces the concept of a scope and how scopes are used within ActiveRecord.

Introducing Scopes

Having a session per database call is suboptimal. There is no chance to use transactions, which is a showstopper for most serious uses. Another issue is lazy loading: Lazy loading prevents NHibernate from loading large collections until they are requested, avoiding to load unnecessary data. Lazy loading is however only possible when done within a single session.

Castle ActiveRecord uses scopes to overcome this. A scope represents a single unit of work. It is not necessarily a single transaction, but may span multiple transactions. Prior to NHibernate 2.0, when transactions were not mandatory, scopes did not even have to support transactions.

The scopes that are part of the ActiveRecord package do always share a single session that is used for all persistance related calls. However, it is possible to implement a scope that uses a new session, but the changed semantic should be clearly communicated in such a case.

Localizing Scopes

In order to access scopes without holding a reference to the object, they stored in thread static stacks. The central interface for this is IThreadScopeInfo, which is implemented by various classes to cover different situations such as web applications. WebThreadScopeInfo for example uses a HttpContext for storing the scopes while the default ThreadScopeInfo implementation uses a thread static field.

In order to acquire the current IThreadScopeInfo implementation, ThreadScopeAccessor can be used. This class is a singleton providing the current ScopeInfo under

public IThreadScopeInfo ScopeInfo

Additionally it acts a proxy to this scope, delegating calls to the scope info in the property above. This allows to access the current scope without keeping a field for it using

ThreadScopeAccessor.Instance.XXX();

where XXX is one of the methods defined in IThreadScopeInfo.

With the IThreadScopeInfo available, the current scope can be requested by SessionFactoryHolder using the following methods:

ISessionScope GetRegisteredScope()
bool HasInitializedScope

Scope Initialization

When a scope is created, it has no sessions stored at first. That is intentional. While the ActiveRecordStarter configures the ISessionFactoryHolder at startup, it cannot configure an arbitrary number of ISessionScope implementations.

Therefore the initialization of scopes is implemented using a simple protocol between ISessionFactoryHolder and ISessionScope:

  1. Upon creation, the ISessionScope registers itself with the current IThreadScopeInfo.

    void IThreadScopeInfo.RegisterScope(ISessionScope scope)
  2. ISessionFactoryHolder fetches the scope the next time it has to deliver a session to the ActiveRecordBase methods.

    bool IThreadScopeInfo.HasInitializedScope
    ISessionScope IThreadScopeInfo.GetRegisteredScope()
  3. The ISessionFactoryHolder asks the ISessionScope whether it already has a suitable session stored. Scopes do not hold only one session. Due to different database connections by root type, they need to hold a dictionary of sessions. The scope doesn't know the key to the sessions because the key is provided by the ISessionFactoryHolder everytime a session is required.

    bool ISessionScope.IsKeyKnown(object key)
  4. If there is a session registered with the scope, the session is requested and the protocol ends.

    ISession ISessionScope.GetSession(object key)
  5. If there is no suitable session available the ISessionFactoryHolder asks the ISessionScope whether it accepts an existing session or if it wants to create its own session.

    bool ISessionScope.WantsToCreateTheSession
  6. Depending on the answer to 5, the ISessionFactoryHolder either opens a session itself or provides a suitable ISessionFactory to the ISessionScope so that the session can be created by the scope itself.

    ISession ISessionScope.OpenSession(ISessionFactory sessionFactory, IInterceptor interceptor)
  7. The session is registered with the ISessionScope by the holder. This is done regardless who in fact created the session.

    void ISessionScope.RegisterSession(object key, ISession session)
  8. The freshly registered session is fetched from the scope.

    ISession ISessionScope.GetSession(object key)

The different Scope Types

Scopes generelly have two attributes that describe there behaviour: by FlushAction and by SessionScopeType. The FlushAction controls whether changes are automatically flushed to the database. The SessionScopeType describes the behaviour of the scope in common, most important whether the scope supports transactions.

If the FlushAction is defined as FlushAction.Never, no writing to the database will occur unless ISessionScope.Flush() is called by the using code. This behaviour gives full control to the using code, but requires it to control flushing. This is important: If the changes are not flushed, queries will still find an older state in the database although the entity has already changed.

FlushAction.Auto instructs the NHibernate session to flush its first-level-cache whenever needed. That means that if the cache contains an unflushed change to an entity, the session will write those changes back before it runs a query against the entity's type.

The SessionScopeType has four values:

SessionScopeType.Undefined
SessionScopeType.Simple
SessionScopeType.Transactional
SessionScopeType.Custom

Undefined should never be used; it is more an error state than a valid scope type. Simple and Transactional define whether the scope supports transactional behaviour. Custom can be used for own implementations that fall in between. An example would be a SessionScope that uses transactions only for specific sessions.

The next part of the series will show how ActiveRecord usage differs when using a scope.

2009/04/21

Understanding ActiveRecord Sessions 1

This article series deals with the internal session keeping of Castle ActiveRecord. It begins in explaining how sessions are managed within ActiveRecord and how the user can influence this behavior.

What happens when Save() is called?

The first part of our journey starts in ActiveRecordBase. Whenever a method is called that requires a NHibernate session, it requests one from the following field:

protected internal static ISessionFactoryHolder holder;

Since that field is marked protected internal static, subclasses of ActiveRecordBase can directly access it to acquire a session. This is done with the following methods:

ISession CreateSession(Type type);
void ReleaseSession(ISession session);
void FailSession(ISession session);

The first method requests a session from the ISessionFactoryHolder, that can be used to issue calls to the session, such as Save(), Load() etc. After the operation was completed, ReleaseSession must be called, preferably in a finally block.

If an exception is raised from NHibernate, the session cannot be used anymore. The ISessionFactoryHolder must be notified through the FailSession-method.

To further understand the inner workings of ActiveRecord, we need to look at the default implementation of ISessionFactoryHolder, which is simply called SessionFactoryHolder.

The SessionFactoryHolder keeps a dictionary which maps the configured ActiveRecord root types to ISessionFactory instances. Whenever CreateSession is called, it fetches the ISessionFactory for that type and creates an ISession.

When ReleaseSession is called the session is flushed and disposed, closing any open connections. If you use the holder to acquire sessions directly, keep in mind that it is necessary to release them or you will get a resource leak. Database sessions are among the most critical resources with regard to leaks.

If an exception is raised, the FailSession method will clear the session so that it doesn't throw again when the session is released.

When ActiveRecord is used without any scopes, all of this happens on a single call of any of the data retrieval or persistence methods (Save(), FindAll() etc.):

  1. ActiveRecordBase gets an ISession from the SessionFactoryHolder. ActiveRecordMediator simpy calls a static method on ActiveRecordBase, so there are no differences with respect to session handling.
  2. ActiveRecordBase performs the desired database operation.
  3. If there is no exception, ReleaseSession is called by ActiveRecordBase. In case of an exception, FailSession is called instead and the exception is rethrown.
  4. SessionFactoryHolder closes the ISession instance. Upon the next call, a new session is created.

But what if we need to have a single session span multiple commands? This will be handled in the following articles when we talk about scopes.

2009/01/27

Active Record and DDD

One of the most fatal mistakes one can conduct when beginning with Domain-Driven Design is doubling Active Record types as domain entities. This does not include Castle ActiveRecord, but all frameworks that map classes and tables one-to-one, and to some extend even more flexible solutions like NHibernate.

How does it start?

This trap is usually hit by developing a data-driven applications using ActiveRecord as an ORM. There is nothing bad with the approach per se, and I'm actually using it myself a lot. Let's see the following code taken from the Castle ActiveRecord GettingStarted section:

[ActiveRecord]
public class Blog : ActiveRecordBase<Blog>
{
	private int id;
	private String name;
	private String author;
	private IList<Post> posts = new List<Post>();

	public Blog()
	{
	}

	public Blog(String name)
	{
		this.name = name;
	}

	[PrimaryKey]
	public int Id
	{
		get { return id; }
		set { id = value; }
	}

	[Property]
	public String Name
	{
		get { return name; }
		set { name = value; }
	}

	[Property]
	public String Author
	{
		get { return author; }
		set { author = value; }
	}

	[HasMany(
		Table="Posts", ColumnKey="blogid", 
		Inverse=true, Cascade= ManyRelationCascadeEnum.AllDeleteOrphan)]
	public IList<Post> Posts
	{
		get { return posts; }
		set { posts = value; }
	}
}

This is straight forward data-driven code and there is nothing bad about it. Note that no business logic is embedded in the class. In the simple GettingStarted example, the logic is buried in the GUI, but in a real application you would perhaps use Transaction Scripts to encapsulate logic in objects.

Setting the trap

The programmer eventually reads Eric Evans great book or hears from a mailing list about DDD. He might remember that Castle ActiveRecord does not require a base class and removes it, using ActiveRecordMediator for database access.

Now that there are only POCOs, our unwary programmer starts adding business logic to the ActiveRecord types. By that, he tries to encapsulate complexity within the "domain model".

But what has happened:

  • Most important, he violates the Single Responsibility Principle (SRP); the class is now responsible for multiple aspects:
    • Storing data
    • Executing business logic
  • In the first few iterations, business logic that was previously packed in one method is now cluttered over multiple classes. DDD's supple design promises to mitigate that but a design usually only becomes supple by a lot of refactoring.

The immediate result is big step backwards in maintainability. Over the long term, DDD will have a better maintainability, but you will need a lot of work to reach this state. By that time, the trap has already sprung...

The trap fires

For a while, all will be well. The programmer get accustomed to the code and does some changes. The code gets more complex and a bit unwieldy. Finally, the programmer needs a "break-through"; a big refactoring takes place to make the code more supple.

Now, violating the SRP fires back: It is not possible to refactor the design without writing complex migration scripts for the database. Integration suddenly becomes an issue. However, the redesign is utterly needed because of the business logic embedded in the design.

The typical outcome is that the redesign is put off until "there is more time", or shorter: "never". In the meanwhile, the code base is growing and getting more and more fragile.

How to recover?

The most important task in recovering from such a dilemma is deciding which approach will be used for the application. You can choose a data-driven approach or a domain-driven approach, but not both.

Using DDD

If the complexity of the domain mandates DDD, it is necessary to do it right. This means using the ActiveRecord types as a DAO/DTO layer and building a model upon it that contains the business logic. The model is then decoupled from the data structure. If the model is redesigned, the mapping code requires to adapt, not the structure of the data storage. If the storage structure changes, the mapping code changes and not the model.

This is also the reason why it is possible to use NHibernate directly on a domain model: The NHibernate mapping files are mapping code, written in an XML-based DSL (and soon with a fluent API)

So this is the other way out of the trap when using DDD. If you use Castle ActiveRecord, take the hbm-files created when using the debug switch and use NHibernate directly instead.

Using data-driven design

It is also possible to make a full turn. A domain of modest complexity that defines most of the business cases as sequential workflows and processes, will benefit from using a data-driven approach.

The processes defined in the business domain can be modeled using the Transaction Script pattern and the Active Record model is exactly that: a pattern for accessing an underlying database.

On the "Anemic Model"

Many of the solutions above use a model that is disregarded as anemic by many. But whether a model is anemic, depends on responsibilities rather than on LOC.

Thus an ActiveRecord-model is not anemic because it is responsible for accessing the data store. A DAO/DTO is part of the persistence layer and its responsibility is passing data around. By coincidence, it doesn't need any methods for this task, but it is not anemic.

After all, violating the SRP is always worse than having an anemic model.

Disclaimer

The poor programmer who unwarily builds a trap who fired at himself was of course me.