Living in the Tech Avalanche Generation

A practitioner’s introspective on technology

ADSD Course with Udi Dahan in Sydney Australia for November 2010

image Hot on the heels of Udi’s visit to Melbourne this year (in January), comes another chance to make good if you missed out. Plans are underway for Udi to visit us yet again, this time in Sydney. If your interested check out Udi’s post and register your interest using the link for the proposed Sydney event. If you want to know more about the course you can see the course outline here and read my review which contains links to some further reviews from other attendees in Melbourne earlier this year.

Share/Save/Bookmark

No comments

Helping Entity Framework v4.0 play it’s <ROLE> – Part 3.0

In part 1.0 we laid the foundation and part 2.0 unravelled some of the internal details of how NFetchSpec (the libraries that are subject of this discussion) goes about enlisting the benefits that can be derived by using explicit roles in your system by collapsing a swathe of Entity Framework functionality into a somewhat compact approach to dealing with a Domain Model. First a quick recap of the underpinnings.

Figure 1.0

ef_roles_part3_nfetch_in_action_usage_quadrant

Code from Figure 1.0

public void resolves_everything_from_container()
{
    IList<IRunOutDiscountForProducts> products = null;

    var compParams = new Dictionary<string, string>();
    compParams.Add(_conParamName, _connectionStringOnly);

    var repo = FetchSpec.Configure
                            .With(new IoC())
                            .AndBuildSession<IRunOutDiscountForProducts>
                                (compParams)
                            .ForRepository();

    using (var scope = new TransactionScope(TransactionScopeOption.Required,
        new TransactionOptions()
        {
            IsolationLevel =
                SessionBuilder<IRunOutDiscountForProducts>.ScopeIsolation()
        }))
    {
        products = repo.Get<IRunOutDiscountForProducts>();
        foreach (var product in products)
        {
            product.DiscountProductForRunOut();
        }

        scope.Complete();
    }
}

Figure 1.0 demonstrates how all the moving parts in the developer experience are put to use when using the NFetchSpec libraries to query and make changes to a persisted Domain Model. Let’s now examine in detail all the steps that make up the entire developer experience of composing all the discrete pieces needed in addressing the role of IRunOutDiscountForProducts (in our fictitious system).

The Development Scenario

image The first outlined section in figure 1.0 demonstrates the building of an appropriate ObjectContext for the Repository that is instantiated by the fluent interface. From the developer experience perspective, nothing special needs to be done outside of specifying the role to the fluent interface in this manner.

image The second outlined section in figure 1.0 highlights how the role is leveraged to dynamically have NFetchSpec chose the ‘right’ isolation level. Being explicit in this way we can achieve a high degree of separation of concerns with respect to transaction isolation and thus exercise our control over the concurrency and throughput in the database on a role by role basis. In the example, we are discounting products earmarked for a run out sale, consequently changing their unit price, therefore we might like to choose a higher isolation level for that particular operation, depending on the volatility of the data that your dealing with and the normalization or lack thereof in your database schema. For the developer this means creating a concrete implementation of the interface IProvideIsolationLevelFor<T>, to support this automagic behaviour.

public interface IProvideIsolationLevelFor<TRole>
{
    IsolationLevel GetScopeIsolationForRole { get;}
}

public class RunoutDiscountIsolation :
             IProvideIsolationLevelFor<IRunOutDiscountForProducts>
{
    public IsolationLevel GetScopeIsolationForRole
    {
        get { return IsolationLevel.ReadCommitted; }
    }
}

That’s it as far as getting your transaction set for the right Isolation Level within the scope of work for a given role. If we decide at some point that this Isolation Level is not the best fit, we can replace it with a new implementation.

image The Third outlined section in figure 1.0 highlights the use of the Repository to retrieve the Entities that we are interested in. This is where the NFetchSpec machinery goes to work to resolve all the purpose built artefacts that have been implemented for the given role, such as any applicative Fetching Strategy, Specification, Entity and Mapping.

The Loaded Fetching Strategy

public class ProductRunOutFetchingStrategy :
             FetchingStrategy<IRunOutDiscountForProducts>
{
    public ProductRunOutFetchingStrategy()
        : base(false)
    {
        var production_intentions =
            EagerFetchingIntention
            .CreateInstance<IRunOutDiscountForProducts,
                            ISupplier>(p => p.Supplier);

        this.AddIntentions(new IEagerFetchingIntention[]
        {
            production_intentions
        });
    }
}

The intent of the developer in building this Fetching Strategy is to load Products eagerly with their reference Supplier.

The Loaded Specification

public class RunOutProductDiscountSpecification :
             Specification<IRunOutDiscountForProducts>
{
    public RunOutProductDiscountSpecification()
        : base(p => p.UnitPrice > 5M && p.Supplier.Region == "London") { }
}

The Specification is really quite simple and self evident – setting up the applicative Expression that will ultimately be translated into a ‘where’ predicate.

The Loaded Mapping

First up we need to map our Entities and that requires a Mapping<T>.

public class ProductMapping : Mapping<Product>
{
    public ProductMapping(string objectSetName) : base(objectSetName)
    {
        Property(p => p.ProductID).IsIdentity();
        Property(p => p.ProductName).HasMaxLength(50).IsRequired();
        Property(p => p.UnitPrice).Precision = 19;
        Property(p => p.UnitPrice).Scale = 4;
        Relationship(p => p.Supplier).IsOptional();
        Relationship(p => p.Supplier).IsOptional().FromProperty(s => s.Products);
    }
}

And because our example has a reference Entity in the root we require the following Supplier Entity Mapping also.

public class SupplierMapping : Mapping<Supplier>
{
    public SupplierMapping(string objectSetName)
        : base(objectSetName)
    {
        Property(s =>  s.SupplierID).IsIdentity();
        Property(s => s.CompanyName).HasMaxLength(40).IsRequired();
        Property(s => s.Region).HasMaxLength(15);
        Relationship(s => s.Products).IsOptional().FromProperty(p => p.Supplier);
    }
}

The last requirement of the developer with respect to mapping is to create a MappingRole<T>, the purpose of which is to indicate to the infrastructure which mappings are applicable to the Role.

public class RunOutDiscountMappingRole :
             IMappingRole<IRunOutDiscountForProducts>
{
    private IMapping[] _mappings;

    public RunOutDiscountMappingRole()
    {
        _mappings = new IMapping[]
                    {
                        new ProductMapping("Products"),
                        new SupplierMapping("Suppliers")
                    };
    }

    public IMapping[] Mappings
    {
        get { return _mappings; }
    }
}

image The fourth and final outlined section in figure 1.0 is really the essence of what is going on here, it is entirely the reason this code is being invoked – it is the purpose (discounting products) of the system for this role. When developing in this way we need to specify the behaviour of the Role through the stable abstraction of it’s interface, and implement that behaviour in a concrete Entity.

public interface IRunOutDiscountForProducts : IProductData
{
    void DiscountProductForRunOut();
}

The Bang and Crash

So with all that done, we need to deploy our “Role inspired” artefacts to the executing processes assemblies folder and when it’s all said and done the code from Figure 1.0 executes, enlisting the service of NFetchSpec in applying the combined intent and customised behaviours described in all of the deployed pieces.

From the database perspective, SQL Profiler tells us that our intent for this ROLE has been met and the system has behaved precisely as expected.

SELECT
    [Extent1].[ProductID] AS [ProductID],
    [Extent1].[ProductName] AS [ProductName],
    [Extent1].[UnitPrice] AS [UnitPrice],
    [Extent1].[SupplierID] AS [SupplierID]
FROM
    [dbo].[Products] AS [Extent1]
INNER JOIN
    [dbo].[Suppliers] AS [Extent2]
ON
    [Extent1].[SupplierID] = [Extent2].[SupplierID]
WHERE
    ([Extent1].[UnitPrice] < cast(20 as decimal(18)))
AND
    (N‘London’ = [Extent2].[Region])

We can see that Fetching Strategy and Specification have been successful in shaping the TSQL sent to the server to retrieve the data. Below we can also see the effect of applying the business rules through our Domain Model.

exec sp_executesql N‘update [dbo].[Products]
set [UnitPrice] = @0
where ([ProductID] = @1)
‘,N‘@0 decimal(19,4),@1 int’,@0=3.2960,@1=1

Just one more thing

Part 4.0 will be the final part in the series and will focus on how this approach blends into a service layer in a Service Oriented Architecture and also make the code for NFetchSpec available for download.

Share/Save/Bookmark

7 comments

Helping Entity Framework v4.0 play it’s <ROLE> - Part 2.0

The content of this series of posts is based around a spiking effort / proof of concept that aims to modularize (I am avoiding the word framework) a set of libraries for the express purpose of addressing business intent for Domain models persisted with the Entity Framework. In part 1.0 we laid the groundwork and now we dig deeper.

I’m going to start this post at the end and then rewind all the way to beginning and step through how we got here. Here is some code that will return a list of products and in so doing, will dynamically determine the correct Entity type to return (a Product), will eagerly fetch their reference supplier and will apply a ‘where’ predicate to the LINQ To Entities query. All this will happen out of clear view as a result of being explicit and specifying a role / interface to the ORM when we ask it do something.

public void Some_Method_In_My_Service_Layer
{
    var products = Repository.Get<IRunOutDiscountForProducts>();
}

Now let’s briefly forget we saw this code and go back to the start.

Lets start by imagining some simple data access code that’s enormously compact and equally deceptive in it’s apparent simplicity. For a scenario, let’s propose that we want to get all the products in our system that are eligible for applying a run out discount. The business logic in achieving this function, specifies that a Products Unit Price Price  be greater 20.50 dollars and is purchased from suppliers in a given enumerable list of regions. For the sake of the example we will also say that this would require a Product entity and Supplier Entity in the following relationship.

product_supplier_class_diag

So given our the scenario we would be required to map the Entities appropriately, choose an appropriate method of loading (lazy or eager) and apply a suitable predicate to the SQL query. Let’s now imagine that by specifying a role (in this case the interface IRunOutDiscountForProducts), that we have provided the infrastructure code enough information to query the database for products and do so in a way that meets the proposed scenario requirements enumerated above.

var conParams = new Dictionary<string, string>();
conParams .Add(_conParamName, _connectionStringOnly);

var repository = FetchSpec.Configure
                    .With(new StubIoc()
                        { ScannedAssemblyPath = _scannedAssemblyPath })
                    .AndBuildSession<IRunOutDiscountForProducts>(conParams)
                    .ForRepository();

var products = repository.Get<IRunOutDiscountForProducts>();

The line of code that interests us most at this point is the last one. By applying the role of IRunOutDiscountForProducts to the GET<T> function, we are able to indicate to the infrastructure that our intent is to retrieve a list of Products for the express reason to apply a ‘run out’ discount to them. The next line of code you might expect to see would logically be something like:

products = repo.Get<IRunOutDiscountForProducts>();
foreach (var product in products)
{
    product.DiscountProductForRunOut();
}

repo.Save();

What figure 1.0 shows is that we would like our Repository to be smart enough to know exactly what and how to fetch based on the role (the generic parameterized interface).

Figure 1.0

explicit_concerns

I promise we will get to the end soon enough but bear with me for a minute or two. One thing about being explicit with roles, it makes understanding code all the more simple. The less ambiguity the less likely someone misunderstands intent. In the realm of software development the humble interface (not the UI kind) has carried the torch ably in helping us declare our intent more explicitly, make our code better understood and free of concrete dependencies / coupling. With reverence and honour for my past (COM programming veteran status), I apologise in advance for the ubiquitous IDog example but it makes a point.

public class Poodle : IDog
{
    //….etc
}

Explicitly a Poodle must now conform polymorphically et al to the contract specified by IDog – real 101 stuff no doubt. What about a marker interface? True enough, a very useful construct, bereft of polymorphic intent and largely a utility to express membership to a conceptual entity group of some kind, often put to use in frameworks to support dynamism of some description. Let’s use an NServiceBus IMessage as an example:

public interface IMessage {}

public class OrderCancelledMessage : IMessage
{
    //….etc
}

Without going too deep into this at a code level, suffice to say that the NServiceBus infrastructure will behave in certain ways when it comes across types that implement the IMessage interface, in other words the framework is directing us to ‘mark’ a given class (or interface) as being recognizable as a ‘Message’, making it identifiable to the frameworks internal workings.

The virtues of programming by interface are now well documented and for .NET developers the advent and popularity of generics has encouraged our creativity in placing stable abstractions  around things to make code more explicit. For example, a while back I wrote in the abstract on the use of interfaces to define roles; roles describe the polymorphic nature of a business domain command and arguably event. This series of posts is an extension of those made in the past, the focus however now moves to a proof of concept for the up coming Entity Framework 4.0.

What is a Role?

Roles identify or describe commands / behaviours in the domain, an level of intent that can be be nicely defined by an interface.

public interface IRunOutDiscountForProducts : IProductData
{
    void DiscountProductForRunOut();
}

We can use these roles (interfaces) to indicate to our infrastructure (an ORM in this case) what our intent is and have the infrastructure behave appropriately based on configuration and / or convention.

Since we started with an example that focused around products, lets continue with that subject for a moment. It may be that my system needs to fetch Products for a variety of reasons and not always with the same intent. We shouldn’t be asking for a generic list of Products, considering that we are interested in them with a very specific context in mind and its the context determines the behaviour and describes the a role.

Once our system becomes explicit in this way through the use of roles in our domain, we can do some interesting things. We can instruct the ORM how to load the entity graph by implementing Fetching Strategies, dynamically resolve the most appropriate Entity Mapping to use and which predicate to apply to the query for the purpose of business logic filtering. Not only does the the role provide a stable abstraction, it insulates other parts of the architecture, perhaps a service layer or controller, from changes, allowing the actors to vary independently.

The Roles Quadrant:

quadrant_roles

Whilst working on this proof of concept in my attempts at cajoling the Entity Framework to work in this fashion, it became evident that there were four main pieces of the puzzle, Fetching Strategies, Specifications, Mapping, and Repositories. One thing that I haven’t mentioned yet, is the effect on concurrency, scale and throughput that this approach can have. Through the use of roles we can plug into the architecture yet again and explicitly pick an isolation level for the operation at hand.

using (var scope = new TransactionScope(TransactionScopeOption.Required,
    new TransactionOptions()
    {
        IsolationLevel =
            SessionBuilder<IRunOutDiscountForProducts>.ScopeIsolation()
    }))
{
    //…..do some stuff here like load data 
    //…..change data by calling into your domain model
    //…..and finally save the changes

    scope.Complete();
}

Notice that in constructing the Transaction scope we use the SessionBuilder and ask it to supply an Isolation Level for the role specified. Of course their is some IOC magic involved here but essentially the only thing required to make work is the following interface. Here is an example implementation.

public interface IProvideIsolationLevelFor<TRole>
{
    IsolationLevel GetScopeIsolationForRole { get;}
}

///Implementation

public class RunoutDiscountIsolation :
    IProvideIsolationLevelFor<IRunOutDiscountForProducts>
{
    public IsolationLevel GetScopeIsolationForRole
    {
        get { return IsolationLevel.ReadCommitted; }
    }
}
This concrete class is responsible (explicitly) for providing the correct isolation level for the IRunOutDiscountForProducts role.

Loaded Up

Before looking at each of the four corners of the quadrant, I quickly want to draw your attention to the fact that Specifications, Fetching Strategies, Isolation Levels (for Transactions), Entities and indeed even their Mappings, can all be resolved from a container at runtime, based on the given role.
_container.Register(AllTypes
    .Of(typeof(IFetchingStrategy<>))
    .FromAssembly(assembly)
    .Configure(c => c.LifeStyle.Singleton).WithService.FirstInterface());

_container.Register(AllTypes
    .Of(typeof(ISpecification<>))
    .FromAssembly(assembly)
    .Configure(c => c.LifeStyle.Singleton).WithService.FirstInterface());

_container.Register(AllTypes
    .Of(typeof(IMappingRole<>))
    .FromAssembly(assembly)
    .Configure(c => c.LifeStyle.Singleton).WithService.FirstInterface());

_container.Register(AllTypes
    .Of(typeof(IProvideIsolationLevelFor<>))
    .FromAssembly(assembly)
    .Configure(c => c.LifeStyle.Singleton).WithService.FirstInterface());

_container.Register(AllTypes
    .Of(typeof(IEntity))
    .FromAssembly(assembly));
This will make the understanding an little easier as we move through the rest of the post.

Quadrant Position 1.0 – Fetching Strategies

Fetching strategies encapsulate our expression of requirement with respect to Eager and Lazy Loading. This feature is useful, when one considers that the Entity Framework (and most ORM’s for that matter) do not provide these capabilities with a consistent API experience, nor allow for an out of box experience friendly to a configurable or convention based approach to specifying loading characteristics for a given expression of intent. Wouldn’t it be nice if we could ask the ORM to fetch an Entity using a role, one specific to a command that exists within a given business capability? This functionality does exist with NHibernate but not currently with either version of Entity Framework, but the good news is that it is possible. There are a couple of ways of doing this and I have blogged about it more than once. At this point of the discussion it would be useful to show some code and how to configure a Fetching Strategy. First the interface:

public interface IFetchingStrategy<TRole> : IQueryConfigurable
{
    IEnumerable<IEagerFetchingIntention> Intentions { get; }
    IEnumerable<string> Includes { get; }
    void AddIntentions(IEagerFetchingIntention[] intentions);
    bool ShouldLazyLoad { get; }
    bool HasInstructions { get; }
}

Next let’s look at an implementation (we will skip the base class for now).

public class CustomerPreferedFetchingStratey :
             FetchingStrategy<IMakeCustomerPrefered>
{
    public CustomerPreferedFetchingStratey()
        : base(false) {

            var orders_intention =
                EagerFetchingIntention
                .CreateInstance<IMakeCustomerPrefered,
                                ICollection<IOrder>>(c => c.Orders);
            var orderlines_intention =
                EagerFetchingIntention
                .CreateInstance<IOrder,
                                ICollection<IOrderLine>>(o => o.OrderLines);

            this.AddIntentions(new IEagerFetchingIntention[]
            {
                orders_intention,
                orders_intention.And(orderlines_intention)
            });
    }
}
Without dwelling on all the moving parts, let’s summarise here by saying that this code has the responsibility of building up the ‘includes’ strings (see ObjectContext<T>.Include()) for eager fetching. No more magic strings applied to the ObjectContext.Include(“magic.more.magic”) method. With a Fetching Strategy we can determine our eager fetching in a strongly type fashion by explicitly specify a role to the Fetching Strategy. In this case above, we are using the IMakeCustomerPrefered role.

Quadrant Position 2.0 – Specification

The Specification pattern evolved around the problem of testing that the state condition of an object is met according to a given specification. This pattern has taken on some new potential with the help of LINQ. Using LINQ Expressions it’s possible to massage this pattern into something of a predicate store and when we think about developing with roles it becomes potentially more powerful again. Here is a quick look at a Specification and some usage:

var spec = new Specification<IRunOutDiscountForProducts>
              (p => p.UnitPrice < 20M && p.Supplier.Region == “London”);

Pretty simple, the constructor takes the Expression to initialise the boolean test for the specified state. The classical purpose of the pattern is to provide a single function, commonly named “IsSatisfied” to carry out the test against a given object to see if it’s state indeed meets that that has been specified.

var productToTest = new Product(){Supplier = new Supplier()};
var satisfied = spec.IsSatisfiedBy(productToTest);

This will code will obviously fail the specification test and IsSatisfiedBy() will return false. Whilst very useful in and of itself, the LINQ Expression enabled version / implementation of this pattern has some features that can be harnessed to apply a level of dynamism to the resolution of query predicates. Let’s have a closer look:

public interface ISpecification<T> : IQueryConfigurable
{
    Expression<Func<T, bool>> EvalPredicate { get; }
    Func<T, bool> EvalFunc { get; }
    bool IsSatisfiedBy(T entity);
}

The interface details the contract to provide both the Expression and Func that will provide the computation required to discern whether a specification has been satisfied. Further to that, these new properties give us opportunities to plug predicates or lambdas into the machinery as well. Looking a little deeper under the covers of the proof of concept code we will find this in operation:

return _ctx
       .CreateObjectSet<TRole>()
       .Where(predicate.EvalPredicate)
       .ToList();

Through operator overloading, Specifications can also be combined for OR and AND conditions:

Specification<Customer> german_customer_spec =
    new Specification<Customer>(c => c.Country == “Germany”);

Specification<Customer> us_customer_spec =
    new Specification<Customer>(c => c.Country == “Usa”);

var comb_country_spec = (german_customer_spec | us_customer_spec);

In the case where query predicates help to form a semi static business rule at the query level through filtering, it becomes a reasonably trivial task to deploy a new version or entirely new Specification for any given role, simply by deploying the library.

Quadrant Position 3.0 – Mapping

Now to the latest part of the puzzle to be rolled into the Proof of concept, mapping. Entity Framework 4.0 (sometime after initial release) will be augmented by code only mapping (hallelujah). When one looks at the (current CTP) API for this functionality it becomes immediately evident that this too is something that can be very easily made deterministic by adding a layer of indirection to accommodate this role based approach. The out of the box mapping in EF 4.0 makes working in this manner quite simple given the possibilities provided by the EntityConfiguration<T> class. Here is a simple example:

public class CustomerMapping : EntityConfiguration<ICustomer>
{
    public CustomerMapping()
    {
        Property(c => c.CustomerId).IsIdentity();
        Property(c => c.FirstName).HasMaxLength(50).IsRequired();
        Property(c => c.LastName).HasMaxLength(50).IsRequired();
        Relationship(c => c.Orders).IsOptional();
        Relationship(c => c.Orders).FromProperty(o => o.Customer);
    }
}

What’s required is to take this out of the box solution and add a layer of indirection requiring only a few new actors, an IMapping, an IMappingRole<T>  and a Mapping<T>.

mappingRolesConcept

public interface IMapping
{
    Type EntityType { get; }
    string ObjectSetName { get; }
    StructuralTypeConfiguration Configuration { get; }
}

public interface IMappingRole<TRole>
{
    IMapping[] Mappings { get; }
}

public abstract class Mapping<TEntity> :
                      EntityConfiguration<TEntity>, IMapping
{
    private string _objectSetName;

    public Type EntityType
    {
        get { return typeof(TEntity); }
    }

    public string ObjectSetName
    {
        get { return _objectSetName; }
    }

    public Mapping(string objectSetName)
    {
        _objectSetName = objectSetName;
    }

    public StructuralTypeConfiguration Configuration
    {
        get { return (StructuralTypeConfiguration)this; }
    }
}

The aggregation of IMapping’s in the Mapping Role will accommodate mapping an aggregate root with reference and collection entities. Here’s a more complete look that includes some implementing Mapping classes.

mappingRolesClassDiag

Below is an example Mapping class, notice that we still need to use the actual Entity Type and not an interface. This is due to EntityConfiguration<T> lacking in support for interfaces (as of today, perhaps that will change or already has with RC 1).

public class ProductMapping : Mapping<Product>
{
    public ProductMapping(string objectSetName) : base(objectSetName)
    {
        Property(p => p.ProductID).IsIdentity();
        Property(p => p.ProductName).HasMaxLength(50).IsRequired();
        Property(p => p.UnitPrice).Precision = 19;
        Property(p => p.UnitPrice).Scale = 4;
        Relationship(p => p.Supplier).IsOptional();
        Relationship(p => p.Supplier).IsOptional().FromProperty(s => s.Products);
    }
}

Quadrant Position 4.0 – The Repository

The final square on the grid is the Repository. The repository offers nothing more than five overrides of the one method, Get<T>. The five versions of the method are to cover the variable requirements that might crop up when consumers wish to provide Fetching Strategies, Specifications and Entities (concrete ones) inline and directly to the infrastructure. Fetching Strategies are probably the least likely candidate for this requirement but it may come in useful, Specifications on the other hand will from time to time no doubt be populated dynamically from user input, served as part of a request or message and subsequently used as a filter parameter. Let’s have a brief look at the Interface:

public interface IRepository : IUnitOfWork
{
    IList<TRole> Get<TRole>();
    IList<TRole> Get<TRole>(IQueryConfigurable[] configurables);
    IList<TRole> Get<TRole>(ISpecification<TRole> predicateWhere)
                            where TRole : class;
    IList<TRole> Get<TRole>(IFetchingStrategy<TRole> strategy)
                            where TRole : class;
    IList<TRole> Get<TRole>(ISpecification<TRole> predicateWhere,
                            IFetchingStrategy<TRole> strategy)
                            where TRole : class;
    IoC IocContainer { set; }
    ObjectContext Session { set; }
}

The first two versions of Get<T> will resolve as much as they can from the container, a Fetching Strategy, a Specification, the Mapping and will use the closest adjacent Entity type, all based on the identity of the generic parameter – that is, the ROLE. The last three versions of the Get<T> function is provided to work with the Entity Framework in a more familiar mode where and EDMX file can be specified, the concrete Entity Type itself is provided as the role parameter, we can also push through Fetching Strategies and Specifications ‘in-line’ in these scenarios. Probably not my preferred method but it’s available.

Configuration

I decided at the death to implement a fluent configuration to prime the infrastructure and create a Repository. The fluent interface is designed with the view to keeping things compact and easy to setup.

Resolve it all

public void resolves_everything_from_container()
{
    var compParams = new Dictionary<string, string>();
    compParams.Add(_conParamName, _connectionStringOnly);

    var repo = FetchSpec.Configure
                        .With(new StubIoc()
                            { ScannedAssemblyPath = _scannedAssemblyPath })
                        .AndBuildSession<IRunOutDiscountForProducts>(compParams)
                        .ForRepository();

    var products = repo.Get<IRunOutDiscountForProducts>();
}

In this example above, we are using a stub for IoC, and hard wiring the scanned assembly path to find all the implementing Fetching Strategies, Specifications, Mappings etc. The default behaviour in the spiking code is to enumerate the assemblies with the executing processes deployment.

Provide it all

For those that like the EDMX way of doing things and want to provide all the Fetching and Speciation instructions in line, this is the way to go about it:

public class CustomerBuyingStatusRepository : Repository
{
    public CustomerBuyingStatusRepository()
    {
        //BEWARE THIS STRING WONT COMPILE ITS MESSED UP
        //FOR THE PURPOSE OF VIEWING IN THE BROWSER.
        const string constring = “metadata=res://*/Northwind.csdl|res://*/” +
                                 “Northwind.ssdl|res://*/Northwind.msl;” +
                                 “provider=System.Data.SqlClient;provider “ +
                                 “etc, etc, etc”;

        this.IocContainer = new IoC();
        this.Session = new NorthwindEntities(constring);
    }
}

public void using_concrete_repository_entity_and_inline_spec_and_fetching()
{
    var customersStartWithA =
        new Specification<Customer>(c => c.CompanyName.StartsWith(“A”));

    var fetch = new FetchingStrategy<Customer>(true);

    fetch.AddIntentions(new IEagerFetchingIntention[]
    {
        EagerFetchingIntention.CreateInstance<Customer,
                                              ICollection<IOrder>>(c => c.Orders)
    });

    var repo = new CustomerBuyingStatusRepository();

    var custs = repo.Get<Customer>(customersStartWithA, fetch);

    foreach (var cust in custs)
    {
        Console.WriteLine(cust.CompanyName);
        cust.MakePrefered();
    }
}

I could have easily left out the ability to support this in-line method, given that the purpose of the spike was to proof the role based approach, having it’s greatest value proposition in being resolved dynamically against the Role. Nonetheless it is possible to mix and match or exclusively do either if you absolutely must. No prizes for guessing which mode I am more partial to, however I will reserve final judgement until it gets a good hit out in the real world, remember this is all the result of a brute force spiking effort.

What’s Left?

In part 3.0 we will look at concurrency and throughput through the lens of a service layer. I will also make the code download available in part 3.0.

Share/Save/Bookmark

3 comments

Next Page »

Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia