NHibernate Tip: Controlling access to persistent collections

by benl

When exposing collections in your NHibernate mapped domain model one thing you should consider doing is restricting access to the collections. NHibernate allows you to specify an access strategy (and a complimentary naming strategy) – this essentially being a policy used by the NH internals to control how a type's members are accessed when it is hydrated/dehydrated by the NH framework.

By specifying an access strategy of nosetter and removing the setter from the property of the mapped collection you can control a client's ability to overwrite the actual collection reference. If you expose your collections (when mapping sets, lists or bags) typed to ICollection you can further enhance the usability of your persistent types. As the ICollection interface doesn't expose the Add, Remove and Clear methods on your collection you must provide your own implementation. This is convenient as it allows you to check for runtime type safety, nullability and any other logic you need to enforce. For example:

public class User
{
	...

public ICollection Roles
	{
		get
		{
			if(this.roles == null)
				this.roles = new ArrayList();

return this.roles;
		}
	}

public int AddRole(Role role)
	{
		if(role == null)
			throw new ArgumentNullException("role");

return ((IList)Roles).Add(role);
	}

public void RemoveRole(Role role)
	{
		if(role == null)
			throw new ArgumentNullException("role");

((IList)Roles).Remove(role);
	}
}

As you can see the AddRole and RemoveRole methods provide safe access to the underlying collection. It should be noted however that these can actually be circumvented by the following cast:

((IList)Roles).Add(theRole);

So while this is a handy concept – it's not 100% foolproof!

About these ads