// thinkbeforecoding

Lazy loads and persistence ignorance (Part 2)

2009-02-08T12:17:31 / jeremie chassaing

In the previous post, I introduced a class to manage function injection for lazy loads to enable persistence ignorance.

Chris was asking where the builder I was talking about should be used, and I tumbled on a StackOverflow question asking how to make lazy loading without using classes like Lazy<T>...

I'll discuss the second part first.

There is a good way to make lazy loading without using classes like that. You can use proxies.

There are two main ways to make transparent proxies

  • by creating dynamically a derived class using Reflection.Emit
  • by creating a transparent proxy

Still there are some drawbacks with both approaches. For the first one, all your members should be made virtual, for the second your class should inherit from MarshalByRefObject. In all case you should then take care not to mess up between proxies and underlying classes.

The main critic to refuse to use Lazy<T> class is usually that it's not a domain concept, and that it leaks persistence concern in the model.

I reject those critics.

Have you ever seen someone criticize List<T> or Dictionary<,> because it was not a domain concept ? We're writing OO code, and we can use basic tooling to make our models expressive. IEnumerable<T> and Linq to objects are good examples of these useful tools.

And I don't consider that Lazy<T> is a persistence concern. It expresses that the relation between entities is a bit more loose than others. There is nothing in the Lazy<T> signature that ties your entity to any persistence concept. You just provide a way to give the value of the property when needed rather than at construction, but this choice comes from outside of your entity.

And at least it becomes clearer than with derived proxies where the C# keyword virtual is used to express something but tries to hide it in the same time.

 

For Chris question, I use the builder in the repository.

The repository is responsible for retrieving entities from the data store. The reconstruction of objects is a bit different from the construction. This is underlined in Evan's book in the chapter Factories / Reconstituting Stored Objects.

In my data access layer I use a IDataBuilder<T> interface that represents a service that can build an object of type T from a IDataRecord. This is when I work directly with the ADO.Net and stored procedures.

    public interface IDataBuilder<T>

    {

        T Build(IDataRecord record);

    }

 

I also use a class that encapsulate the access to the stored procedures (or queries if you don't want to use stored procedures).

    public class DataAccess

    {

        public UniqueResult<Entity> GetEntity(Guid id);

        {

            //...

        }

 

        public MultipleResult<Entity> GetEntities()

        {

            //...

        }

    }

 

UniqueResult<T> and MultipleResult<T> provides a methods that take a builder to read data records :

    public struct UniqueResult<T>

    {

        public T With(IDataBuilder<T> builder)

        {

            //...           

        }

    }

 

    public struct MultipleResult<T>

    {

        public IEnumerable<T> With(IDataBuilder<T> builder)

        {

            //...           

        }

    }

 

In your repository implementation you can then use all this :

    // The concrete repository interface that belongs to the domain

    public interface IEntityRepository : IEnumerable<Entity>

    {

        Entity this[Guid id] { get;}

        //.. other methods

    }

 

    // the implementation that is not part of the domain

    // an that is pesistance dependant.

    internal class EntityRepository : IEntityRepository

    {

        private DataAccess dataAccess;

        private EntityBuilder builder;

 

        public EntityRepository(DataAccess dataAccess, EntityBuilder builder)

        {

            this.dataAccess = dataAccess;

            this.builder = builder;

        }

 

        public IEnumerator<Entity> GetEnumerator()

        {

            return dataAccess.GetEntities().With(builder);

        }

 

        IEnumerator IEnumerable.GetEnumerator()

        {

            return GetEnumerator();

        }

 

        public Entity this[Guid id]

        {

            get { return dataAccess.GetEntity(id).With(builder); }

        }

    }

 

The last part is in the implementation of the builder.

    internal class EntityBuilder : IDataBuilder<Entity>

    {

        private DataAccess dataAccess;

 

        public EntityBuilder(DataAccess dataAccess)

        {

            this.dataAccess = dataAccess;

        }

 

        public Entity GetEntity(IDataRecord record)

        {

            var id = (Guid)record["Id"];

            return new Entity(

                id,

                Lazy.From(() => dataAccess.GetSubEntity(id)));

        }

    }

 

Of course, the repository implementation, the DataAccess class and the builder are all internal to the data access implementation. It can be in a separate Assembly or internal in a sub namespace of the main assembly depending on you module separation preferences.

When using linq, you simply don't need the DataAccess class because you can query the DataContext directly. But you can use the same pattern.

The main point is still that your Entity object knows strictly nothing about what's going on there.