Archive

Archive for February, 2010

Magiq-to-NHibernate: Collection filtering and moving to NHibernate 3

February 25, 2010 1 comment

Few days ago I started having troubles with Linq-to-NHibernate from the current release 2.1.2. The main problem cames when I design the collection filtering strategy. Basically, my idea was to go from:

parent.ChildCollection

to:

session.Linq<Child>().Single( x=>x.Id == parent.Id ).SelectMany( x=>x.ChildCollection );

Having this, we could add many expressions to that queryable as we want.

The thing is, as Chadly posted, Linq-to-nhibernate 1.0 uses the query parameter (the x in the previous expression) as the criteria alias, so this works:

session.Linq<Child>()
       .Single( x=>x.Id == parent.Id )
       .SelectMany( x=>x.ChildCollection, (p,x) => x )
       .Where( x => x.Something );

but this doen’t:

session.Linq<Child>()
       .Single( x=>x.Id == parent.Id )
       .SelectMany( x=>x.ChildCollection, (p,x) => x )
       .Where( z => z.Something );

Since the chosen strategy for dynamically generating the query involved the definition of the “alias” parameter, and the user will need to know which is, I gave up. So I tried NHibernate 3. And it worked 🙂

It was really painful to change what I’ve done for the old linq provider, because it uses criteria and the new one uses hql. It’s not easy at all to get a IDbCommand from a HQL, but not impossible.

By now, deletes, updates, inserts and bulkinserts are working properly for linq-to-nhibernate 2.0 with the same limitation as before: no inheritance, no collections.
In the next days I will be working on collection support, composite ids and mappings.

Magiq-to-NHibernate: First commit!

February 22, 2010 1 comment

The past weekend I started to play with NHibernate for getting Magiq-to-NHibernate features up. It’s wonderful to work with an actually well done-designed framework 🙂
By now, only updates and deletes are working, and for simple classes that doesn’t have subclasses. Collection operations aren’t done either. Oh, and also it only works with SQL Server.
I know the actual problem will be when adding support to joined and union subclasses… well… one step at a time 🙂

Magiq: BulkCopy support

February 19, 2010 Leave a comment

With all the behavior stuff, I have normalized the design in favor of new Magiq providers. Now there’s a MagiqToDatabases abstract class that only needs a few methods to implement. Also, there is a normalization in the operations: Now Magiq have the classes DatabaseInsert, DatabaseUpdate, DatabaseQuery and DatabaseDelete, which contains properties like the columns to update, the expressions of the values, etc.

For implementing BuilkCopy, there was only two things needed to override:

  • The way Magiq-to-objects inserts into a SqlServer based destination: For example, for a Linq-to-Sql table, the way Magiq-to-objects inserts is using the Insert method of Table. The idea is to override that with a SqlBulkCopy. Note: this “way Magiq-to-objects inserts” is called IInsertDestination.
  • Use magiq-to-objects instead any SqlServer insert strategy defined: For using BulkCopy when the source belongs to the same provider, avoiding the regular insert…select… statement

So, following the behavior schema, Magiq provides two interfaces for all this: IObjectsInsertBehavior and IInsertBehavior.

  • IObjectsInsertBehavior provides the way for overriding the IInsertDestination.
  • IInsertBehavior provides the way for overriding the strategy to use, so we can avoid using the default strategy

Also, it needed a way to know if the destination is a SqlServer. Well… all the database operations and strategies implements an interface called IDatabaseBasedExecution that provides a IDatabaseAdapter. And this last interface give us a IDialect that could be a SqlServerDialect.

Ok, ok, but show me some code!!

public class BulkCopy : MagiqBehavior, IObjectsInsertBehavior, IInsertBehavior
{
	public int BatchSize { get; set; }
	public int Timeout { get; set; }

	public BulkCopy()
	{
		BatchSize = 0;
		Timeout = 30;
	}

	private static bool Applies(IDatabaseBasedExecution execution)
	{
		return execution != null && execution.DatabaseAdapter.Dialect is SqlServerDialect;
	}
	
	public IInsertDestination<TNew> GetInsertDestination<TSource, TDestination, TNew>(IInsert<TSource, TDestination, TNew> insert)
		where TDestination : class
		where TNew : class, TDestination, new()
	{
		var insertDestination = Next<IObjectsInsertBehavior>().Call(x => x.GetInsertDestination(insert));
		var databaseOperation = insertDestination as IDatabaseBasedExecution;

		if (Applies(databaseOperation))
			return new BulkCopyDestination<TSource, TDestination, TNew>(insert, databaseOperation.DatabaseAdapter)
					   {
						   BatchSize = BatchSize,
						   Timeout = Timeout
					   };

		return insertDestination;
	}

	public IInsertStrategy GetInsertStrategy<TSource, TDestination, TNew>(IInsert<TSource, TDestination, TNew> insert) where TDestination : class where TNew : class, TDestination, new()
	{
		var strategy = Next<IInsertBehavior>().Call(x => x.GetInsertStrategy(insert));
		var databaseOperation = strategy as IDatabaseBasedExecution;

		if (Applies(databaseOperation))
			return new InsertStrategy<TSource, TDestination, TNew>(insert);

		//overrides the strategy with magiq-to-objects
		return strategy;
	}

	public int Execute(IInsertStrategy strategy)
	{
		//default behavior
		return Next<IInsertBehavior>().Call(x => x.Execute(strategy));
	}
}

And the way to use it:


var sellsFromSomeRepository = ...;

records.From(sells)
       .Using<BulkCopy>()
       .Insert(x => new Record
                     {
                        Type = RecordType.Sell,
                        Description = "Sell from " + x.Date,
                        Amount = x.Total
                     });

And of course, if you use BulkCopy for inserting into a non SqlServer repository, the plugin continues without changes, so it could be used in a testing environment in which the repositories are setted to a List.

Magiq: Named scopes in C#

February 18, 2010 Leave a comment

Some weeks ago, my friend Jonas told me about Ruby’s ActiveRecord Named scopes and I thought what a marvelous feature! Later, I realize that it can be implemented in c# using Magiq.

Suppose you have a store that sells products and these products has expiration date. You call “Available” the products that had not yet expired. In order to find the not expired products, we could do, using Linq:

var availableProducts = store.Products.Where( x => x.ExpirationDate > DateTime.Now );

The problem with this approach is that the more time passes, more products the store will have and more expired, so it could retrieve the entire products collection just to filter some. Magiq to the rescue!

var availableProducts = store.Products.Query( x => x.ExpirationDate > DateTime.Now );

As I told in a previous post, it will generate a new sql query with the new condition.

Ok. In a perfect world, you will have something like an AvailableProducts property in the Store class, because the availability definition could change in the future.

public IEnumerable<Product> AvailableProducts {
    get {
         return Products.Query( x => x.ExpirationDate > DateTime.Now );
        }
    }
}

Now, what happens if besides store, we have a warehouse full of products and we need the available products from there? We will have add the same method in the Warehouse class.

Wouldn’t be nice if we could do it this way:

var availableProductsFromStore = store.Products.Available();

var availableProductsFromWarehouse = warehous.Products.Available();

Ok, we can 🙂

public static class ProductNamedScopes
{
	public static IEnumerable<Product> Available( this IEnumerable<Product> self )
	{
		return self.Query( x => x.ExpirationDate > DateTime.Now );
	}
}

I know, this could be implemented using pure linq, a foreach, ado.net, NHibernate’s collection filtering, etc. But Magiq let you hide all that stuff and use pure Linq in a generic way.

Magiq 0.3.0 available!

February 17, 2010 Leave a comment

I’m glad to announce that the new version of Magiq is available.
Magiq now support:

  • Plugin model
  • BulkCopy as a Plugin for using SqlBulkCopy when inserting into sql server from any source.

And also there was a huge refactoring in order to have simplicity when implementing new providers.

You can download this version from here.

Magiq Behaviors: Implementing plugins for magiq

February 16, 2010 Leave a comment

In a previous post I talk about the API for Magiq plugins and for the next two weeks, I was trying to figure out a way to actually implement it! But a lot of headaches later, I finally get to somewhere.

If you are new here, Magiq is a framework that provides mass deletes, mass inserts, mass updates and collection queries to several Linq providers.

The main idea was to implement it as listeners/interceptos/aspects, so you can choose to decorate the calls (for example, in order to implement a logger) or to override them (for example, the actual insert for a bulkinsert). The other idea is to have all this stuff strongly typed, so no generic aspect framework was allowed.

So… Let’s rock!

First, each behavior is represented by one interface and a default class implementing it. Plugins will be classes implementing those interfaces, acting as a chain of responsability.
Second, each class that interacts with behaviors should inherit form BehaviorHandler, where TBehavior is a specific type of behavior that this class is handling. The class is able to work with other behaviors, but for API simplicity, it provides a default.

public interface IBehavior1{
     void DoSomething();
     int GetSomethingElse();
}

public interface IBehavior2{
     void DoAnotherThing();
}

public class Class1 : BehaviorHandler<IBehavor1> {
     public int Bla(){
           Call( x=>x.DoSomething() );
           Behavior<IBehavior2>().Call( x=> x.DoAnotherThing() );
           return Call( x=> x.GetSomethingElse() );
     }
}

All the “Calls” are done using this method:

public static void Execute<TBehavior>(IMagiqBehavior behavior, Action<TBehavior> action)
{
	if (behavior == null)
		return;

	if (!(behavior is TBehavior))
	{
		Execute(behavior.NextBehavior, action);
		return;
	}

	action((TBehavior)behavior);
}

So, it follow the chain only for the behaviors that implement the specific interface.

Finally, a plugin behavior will look like this:

public class Plugin : IBehavior1
{
     public IMagiqBehavior NextBehavior{ get; set; }

     public void DoSomething(){
           //do something before
           Next<IBehavior1>().Call( x => x.DoSomething() );
           //do something after
     }

     public int GetSomething(){
           //do something before
           var result = Next<IBehavior1>().Call( x => x.GetSomethingElse() );
           //do something after
           return resut;
     }
}

In the following days I will be posting the entire bulk insert implementation following this schema.

Categories: C#

Performing several validations in C#

February 6, 2010 Leave a comment

In the project I’m working on, one of the requirements about error handling was that a lot of things could be validated at the same time and it shouldn’t stop validating when some fails. As the errors are treated as exceptions and exceptions breaks the method flow, it’s obvious that we can’t make the validations left when an exception occurs.

So, I start thinking about a validation scope where there are no rules, everything is possible. But when the scope ends, all the exceptions are thrown.

public void PerformOperation(string param1, int param2)
{
     using (var validationScope = new ValidationScope())
     {
          validationScope
            .When(string.IsNullOrEmpty(param1))
            .Throw<InvalidParam1Exception>();
     
          int something = DoSomethingWith(param1);
 
          validationScope
            .When(something < 10)
            .Throw<InvalidSomethingException>();

          validationScope.Try( () => DoSomethingThatCouldFail(param1) );
     }
     //Do whatever this method should do
}

Basically, ValidationScope methods executes the delegates and conditions and stores the exceptions in a private collection. When the scope is disposed, the exceptions are thrown as one CompositeException containing each of them.

Nice, isn’t it?
You can download the complete source code from here.

Categories: C# Tags: ,