Home > C#, Magiq > Magiq: Plugin support & the insert API changes

Magiq: Plugin support & the insert API changes

The the main feature of Magiq 0.3.0 is sql server bulk insert support, we needed to improve Magiq with plugins.
These plugins would act as interceptors, and they could be applied at configuration level (for example, logging) and query level (bulk insert).

What I wanted is to have a natural way to assign plugins that would work the same for the four operations: insert, update, delete and query.
Ok, what I wanted was actually complicated.
Since I thougth this for Bulk insert, I tried an API for Inserts:

source.Insert( x => new Item{ Name = x.Name })
      .Using( new BulkInsert() )
      .Into( destination );

Same could work for Updates, but no for Deletes and Queries, because those doesn’t have “intermediate” class. Let me explain: insert and update are performed using several calls. Insert have one for declaring the new expression ( x => new Item{ Name = x.Name }) and one for declaring the destination. The same happens with update, we have several for declaring the “sets” and one Update() to finish de operation. Delete and Query, however, works with one single call (They doesn’t need anything else in order to work), so I don’t have a place to put the “Using” method :(.

So, how could it be implemented for Delete and Query? I thought it should be before calling the operation, something like

source.Using( new BulkInsert() )
      .Insert( x => new Item{ Name = x.Name })
      .Into( destination );

The issue with this approach is that the plugin should be for all the operations and not the specific one. But I’m ok with that, I suppose It could be implemented like NHibernate listeners.
So… the idea is to wrap the IEnumerable or IQueryable with another one that is plugged to one or more plugins. Later, I could check for the type of the collection and make use of the plugins. The problem with this solution is that nothing ensures that collection to be the one used in the magiq operations. For example, something like this:

source.Using( new BulkInsert() )
      .Where( somecondition )
      .Insert( x => new Item{ Name = x.Name }).Into( destination );

Magiq will work with the last queryable and not the plugged one. I know, I could check all the chain but, again, nothing ensures that the plugged collection is there.

Talking to my friend Rezlaj, we got to a solution I don’t like a lot but… it’s a solution. The idea is to have all the stuff inside a interface IMagiq that could be getted using an extension method Magiq applied to a collection. It would look like:

      .Where( somecondition )
      .Insert( x => new Item{ Name = x.Name }).Into( destination );

This IMagiq interface have the methods to add plugins and could have another methods to interact with the operation in the future. Of course, there still are the extensions methods Delete, Set, ToQueryable (well, not this last one, because I changed it to Query because I think is better). But they delegates all to the IMagiq interface.
I think I should change the blog title to “The problem with that…”. You may ask way…

The problem with that (the previous that, actually. I mean, the new API) is that all the operations are applied to a T where T : class except Insert. Why? WHY?! because the source of an insert operation could be a colection of int’s, date’s, whatever. For example, this should be supported (and it is!):

sells.Where( x => x.Date == DateTime.Now)
     .Select( x => x.Total )
     .Insert( x => new SellRecord{ Total = x.Name, Date = DateTime.Now })
     .Into( records );

(I know, the example is not the happiest one, but it’s helpful for explaining my point)
So… the source collection is a collection of decimals. Ok, how could it be solved? because IMagiq needs the T : class constraint. Well, there was an idea in my head for the last couple of days about how linq and all the magiq operations except insert reverses the analogous sql structure. So… It makes more sense to have the insert reversed. Something like:

records.Insert( x => new SellRecord{ Total = x.Name, Date = DateTime.Now })
       .From( sells.Where( x => x.Date == DateTime.Now) )

Ok, it’s just an example, it won’t compile (but It will complain… cuak). I need the source type before the NewExpression, so it have no choice that be:

records.From( sells.Where( x => x.Date == DateTime.Now) )
       .Insert( x => new SellRecord{ Total = x.Name, Date = DateTime.Now })

Now, the collection wrapped by IMagiq is the destination and it could have the constraint.

So, summarizing:

  • Magiq() Extension method was added
  • IMagiq adds support to plugins
  • Insert API changed to destination.From( source ).Insert( new )
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: