2005-04-14
Live from TechDays 2005
For those readers who were at the TechDays in Geneva today and followed my presentation on SQL2K5 ("SQL Server 2005 - The Quantum Leap"), there may be two points worth highlighting :
- when consuming a SQL2K5-hosted web services from Excel (with the Office 2003 Web Services Toolkit) you probably noticed that I added a web reference to the VBA project and the URL for this reference was something like : http://localhost/sql/myservice?wsdlsimple
Hmmm... why ?wsdlsimple and not ?wsdl ? Well, simply because the wsdl emitted by ?wsdlsimple is geared towards better interoperability, and as a matter of fact if you try to add a reference to the ?wsdl form of URL, Excel will never discover the available operations. I'll probably post more details on this later on.
- the other comment I'll make regards the Integration Services demo. In this demo, I added web services tasks to call the same web service on Xignite.com 5 times in a row, for the sole purpose of downloading historical quotes for MSFT, SAP, and so forth.
One question that could have been asked is : "well, you just told us that SSIS was way better than DTS 2000, so why the hell didn't you use a FOR loop to call the same task 5 times with different parameters ?" Well, good point. The very reason is that I could not find (yet) any way to specify a variable value for a web service operation parameter in a "web service task" in Integration Services.
There does not seem to exist a syntax for varying parameters. I tried different flavors of @[User::MyVariable] without success.
I can't believe that this feature won't be present in the release version.
BTW, slides and code samples should be soon available on www.techdays.ch.
03.04.05
See you at TechDays 2005 !
Short information post (it's been a long time ...) : TechDays 2005 will be held in Geneva on April 14th/15th.
Plenty of interesting sessions organized to meet the expectations of the following five profiles : IT Professionals, Developers, Architects, SQL Server and Office.
I'll be on the stage for SQL Server 2005 as well as VSTO 2005 sessions.
More information available on www.techdays.ch
-S
11.01.05
A quick'n easy Google web part in SharePoint Services
Use the Form web part and use the following HTML:
<A HREF="http://www.google.com/"> <IMG SRC="http://www.google.com/logos/Logo_40wht.gif" border="0" ALT="Google" align="absmiddle"></A><INPUT TYPE=text name=q size=25 maxlength=255 value="" onkeypress="if(event.keyCode!=13){return true;} window.open('http://www.google.com/search?ie=UTF-8 &oe=UTF-8&q=' + this.value,'Google','');return false;">
17.10.04
Filtered enumerations
In Yield and generics rock !, Bertrand Leroy exposed a very elegant way to filter an generic enumeration using the yield keyword.
He also suggested that "Of course, you can do that with .NET 1.1, but if you try it, you'll see that the code will be considerably more verbose". That's correct !
But .NET 1.1 is still all that is available for production purposes, so here's a possible .NET 1.1 strategy to do the same thing.
/// <summary> /// Generic representation of a predicate /// </summary> public delegate bool Predicate(object o);/// <summary> /// A class that allows to filter an enumeration. It only /// enumerates the members of the aggregated enumeration /// that conform to a given predicate /// </summary> public class FilteredEnumerable : IEnumerable,IEnumerator { readonly IEnumerator unfilteredEnum = null; readonly Predicate filter = null;
/// <summary> /// Creates a new FilteredEnumerable based on an /// originally unfiltered enumeration /// and a given predicate /// </summary> /// <param name="unfilteredEnum"></param> /// <param name="filter"></param> public FilteredEnumerable(IEnumerable unfilteredEnum, Predicate filter) { this.unfilteredEnum = unfilteredEnum.GetEnumerator(); this.filter = filter; }
public IEnumerator GetEnumerator() { return this; }
public void Reset() { unfilteredEnum.Reset(); }
public object Current { get { return = unfilteredEnum.Current; } }
public bool MoveNext() {
if( filter == null ) return unfilteredEnum.MoveNext();
//Proceed to the next element of the //original enumeration //that conform to the predicate bool next = true;
while( ( next = unfilteredEnum.MoveNext() ) && ! filter(unfilteredEnum.Current) );
return next; } }
Sample code to use it :
private int CountPositiveValues(int[] tab) { FilteredEnumerable enumerable = new FilteredEnumerable(tab, new Predicate(IsStrictlyPostitiveInt));int count = 0;
foreach(int value in enumerable) { Console.WriteLine("Found positive value : " + value); count++; }
return count; }
public static bool IsStrictlyPostitiveInt(object i) { if( ! (i is int) ) throw new ArgumentException("int expected");
return ((int)i) > 0; }
Hope this helps, and sorry for those folks who may have written the same thing before, I quickly google'd for something similar but did not find anything but C# 2.0 stuff.
09.10.04
Dynamic proxies over delegate types
One of the few users of the DynaProx.NET framework I posted on GotDotNet recently asked me if it was possible to create dynamic proxies overs delegates.
Short answer : "not in this release".
Long anser : "Well, it never occured to me that one would actually try to do that. Give me some time to think about it, hopefully we'll find a solution"
The goal is to allow a user to do something like :
public delegate void DeleFoo();public delegate int DeleBar(string geek);
//Test code public class SomeTester{ public static void Main(){ DeleFoo f = new DeleFoo(Foo); DeleBar b = new DeleBar(Bar);
//That would be cool if we could do this : DeleFoo fProxy = (DeleFoo)ProxyFactory. GetDelegateProxy(typeof(DeleFoo), new MyDelegateAspect(f));
DeleBar fProxy = (DeleBar)ProxyFactory. GetDelegateProxy(typeof(DeleBar), new MyDelegateAspect(b));
//And then transparently use fProxy //and bProxy instead of f and b
}
private static void Foo(){ ... }
private static int Bar(string geek){ Console.WriteLine("Hey, {0}, what a geek you are",geek); return 33; } }
//The "Aspect", an IInvocationHandler //(Avalon/Java terminology) //or ICallHandler (DynaProx terminology) //equivalent for delegate //types public MyDelegateAspect : ISomeFrameworkProvidedInterface { private Delegate _d;
public MyDelegateAspect(Delegate d){_d = d;}
public object Invoke(object[] parms){ DoSomethingRelevantToYourContext(); _d.DynamicInvoke(parms); } }
Well I'm happy to say that the next release of DynaProx that I should post some time next week will have support for such "dynamic proxies over delegates". If anyone has an idea of a cool scenario in which those animals would prove useful, feel free to post a comment !
The next release (that I have yet to find a version number) will also include numerous improvements over the existing code that was a mere refactoring of the code posted with my original DNG article.
By the way, coding this part I noticed two things worth mentioning :
- classes generated by the compiler for delegate types are sealed
- given a delegate type :
//some delegate type
Type delType = ...;
If we look at the compiled delegate type with reflector we see that it has a (object,IntPtr) constructor. Thus we might think that we can dynamically create an instance of that type using something like :
//some method with the right signature //we want to bind our delegate instance to MethodInfo m = ...;//Assume it's a static method Delegate delInstance = (Delegate)Activator. CreateInstance(delType, new object[]{null,m.MethodHandle.Value});
Well this does not work (yields an TargetInvocationException), you have to use Delegate.CreateDelegate instead, which behind the scenes calls Delegate.InternalAlloc ; any hint on why a plain CreateInstance fails is welcome.
Stay tuned ...
2004-09-11
Generics in .NET 2.0 make "polymorphic" delegates real !
After so many hours spent developing codebehinds and windows forms, I'm now convinced that there is space for improvement in the delegate/event model supported by the .NET Framework.
To be more specific, one aspect that I find extremely painful is the fact that delegates cannot inherit one from each other, which yields the following consequence : a delegate can only be instanciated using a method signature that exactly matches the delegate signature.
Let me make this clear : the ImageButton web control class defines a Click event, of the delegate type ImageClickEventHandler defined as follows :
public delegate void ImageClickEventHandler( object sender, ImageClickEventArgs e );
Now let me define a OnClick method defined as follows :
public void OnClick(EventArgs e) { //some code here }
Even though the ImageClickEventArgs class inherits from EventArgs, I cannot bind OnClick to the Click event of my ImageButton, because OnClick does not exactly match the signature of ImageClickEventHandler. The C# compiler refuses it with the CS0123 error.
What I yould like to be able to express using C# is the fact that ...
public delegate void ImageClickEventHandler(ImageClickEventArgs e)
... somewhat "specializes", or "inherits" from ...
public delegate void EventHandler(EventArgs e)
Which makes sense : when raising an image click event, an instance of ImageClickEventArgs is created. After all, it could be passed to an EventHandler since it is a subclass of EventArgs.
Well, as we experienced it, this does not work with .NET 1.x. The ImageClickEventHandler delegate gets compiled into a class that directly inherits from MulticastDelegate, not EventHandler. There's no C#-provided way of specifying inheritance between the two types.
This can have extremely annoying consequences : if a developer is asked by its users to replace all buttons in the user interface by image buttons, all event handlers must be changed accordingly which makes this refactoring a pain.
Note that I'm far from the only one to wonder whether this kind of trick is possible, Micheal Earl also has a blog entry about it.
After long nightly thoughts trying to find a workaround , I finally gave up until I once tried to do the same thing with Whidbey.
And quickly found out that generics (that also apply to delegates !) were the solution. Indeed, what I was trying to express by using the term "inheritance" simply was that 'all button event handlers only differ by the type of the argument passed'. In other words, all button event handlers conform to the generic delegate signature below :
public delegate void EventHandler<T>(T t);
Which I can further refine using constaints by mandating that T be a subclass of EventArgs :
public delegate void EventHandler<T>(T t) where T : EventArgs;
Which means I can develop a sample ImageButton class as follows :
//Unchanged ImageClickEventArgs definition
public class ImageClickEventArgs : EventArgs {}
//Fake ImageButton class
class ImageButton
{
//The click event is now a specific type
//based on the EventHandler generic type
public event EventHandler<ImageClickEventArgs> Click;
//Simple method allowing a client
//to raise the Click event
public void RaiseClick()
{
if (Click != null)
Click(new ImageClickEventArgs());
}
}
What's the change ? Well, if I write the following sample program :
class Program
{
static void Main(string[] args)
{
//Create a fake image button
ImageButton btn = new ImageButton();
//Bind the Click event to a method that does not
//accept ImageClickEventArgs as an argument, but
//EventArgs
btn.Click +=new EventHandler<ImageClickEventArgs>(OnClick);
//Simulate a user click
btn.RaiseClick();
}
static void OnClick(EventArgs args)
{
Console.WriteLine("Button was clicked !!!");
}
}
... it not only compiles, but runs fine !
Why does this work ? Well, it has to do with the way the CLR treats types instanciated from a generic type, but this is another story that I may tell you in a future nightly thought ...
Also note that the .NET Framework Class Library 2.0 itself defines such a EventHandler<T> generic handler. I reproduced my EventHandler type for illustrating how it solves the original problem.
-S
2004-08-11
La couche de présentation est-elle la moins stable ? (II)
Sami a ouvert un débat très intéressant.
Je souhaite l'élargir, en rebondissant sur ce que dit Sami : "Factoriser du code lorsqu’on gère 40 évènements dans un écran contenant 50 champs et autant de contrôles de surface relève du défi" et en posant la question suivante : si la couche de présentation est effectivement la moins stable, cela ne vient-il pas de ce sacro-saint modèle de programmation évènementiel ?
Je n'ai pas la réponse à cette question mais des chercheurs ont déjà fait le constat que ce modèle évènementiel souffrait de nombreux défauts.
Témoin les travaux du Professeur Petitpierre de l'Ecole Polytechnique Fédérale de Lausanne, comme "Synchronous Java".
De quoi s'agit-il au juste ? D'une amélioration syntactique significative au langage Java définissant directement dans le langage :
- le concept d'objet actif et de méthode bloquante. Lorsqu'on appelle une méthode sur une instance d'une classe active (c'est-à-dire un objet actif), l'appel est bloqué tant que l'object actif (qui tourne par définition dans son propre thread) n'a pas accepté l'appel
- la notion de choix entre appels. SJava permet de lancer parallèlement plusieurs invocations de méthodes sur objects actifs. Le premier appel qui est accepté sera exécuté, les autres abandonnés.
- et bien d'autres choses passionnantes
Quel rapport avec la couche de présentation, me direz vous ? Eh bien le modèle évènementiel est justement lié au fait que dans une interface utilisateur, on ne sait pas à l'avance où va cliquer l'uitlisateur. Plusieurs contrôles peuvent être activés en même temps, offrant leurs services à l'utilisateur. Il se peut du reste qu'un évènement applicatif interne (notification, timeout) se produise avant même qu'un évènement utilisateur se produise.
Le concept de choix introduit par SJava permet de s'affranchir de 2 problèmes identifiés par les auteurs de ces travaux :
- les event listeners favorisent un style de programmation aussi peu lisible et condamnable que les GOTOs
- le diagramme d'état d'une application n'est pas immédiatement visible à celui qui lit le code des event handlers (en habitué des code-behinds, même réduits à leur plus simple expression, je souscris à ce point de vue)
Et j'arrête la paraphrase ici, ce lien vous dira tout ou presque sur le sujet.
En bref, pour revenir à la question initialement posée : la couche de présentation n'est-elle pas la moins stable parce que nous ne disposons pas de l'outil/syntaxe approprié pour représenter de manière informatique le séquencement des opérations effectuées par un utilisateur ?
Ce que j'aimerais, et ce qui arrivera peut-être un jour via une technologie adaptée, c'est un mapping 1-1 entre ce que l'on écrit typiquement dans un use case specification (l'utilisateur fait ceci, le système répond cela, l'utilisateur fait cela, le système répond autre chose), c'est-à-dire une représentation séquentielle des choses, et le code. Mais l'évènementiel empèche pour l'instant cette lisibilité.
01.08.04
Looking for a multi-purpose text editor ?
Thanks to one of my colleagues, I recently discovered SCITE, the Scintilla Text Editor (http://gisdeveloper.tripod.com/scite.html)
If, like me, you're maniuplating hundreds of file types (ranging from .java to .sql, .cs, ...), possibly within the same demo, talk or training session, then you're probably looking for a fast text editor with decent syntax highlighting capabilities that you can use to demo code snippets to your audience.
Scite does this and much more. You can virtually hook any command-line utility to it by editing its config files. I plugged CSC, OSQL, SQL Plus, iSQL, javac and many more into Scite. It's extremely fast and pops up at the same speed as notepad.
After 3 months of practise I can comfortably say that it's by far the best text editor I've ever used !
Needless to say that it is free ![]()
Give it a try ! And by the way, thanks to the guys who are behind this amazing little piece of software.
22.07.04
DbException is your new best friend
Determine what's wrong with the .NET 1.x code snippet below :
public void Foo(){
try{
IDbConnection conn = ConnectionFactory.CreateConnection();
IDbCommand cmd = conn.CreateCommand();
...
}
catch(System.Data.DbException ex)
{
...
}
}
- Foo is a reserved C# word
- The CreateCommand method does not exist
- DbException does not exist
The answer is 3) : in .NET 1.*, ADO.NET provider-specific exception classes (OleDbException, SqlException, ...) have nothing in common, in that they do not inherit from a common exception class that would be dedicated to all database access errors.
This makes it difficult if not impossible to code truly database-independant data access code : event if you stick to IDbXXX interfaces to access data or use a toolkit such as MS Data Access App Block you'll run into a problem when catching exceptions.
Indeed, imagine that at some point you want to catch "all database exceptions" ?
public void SomeMethod(){
try{
//Manipulate IdbXXX implementors
}
catch(?????){ //I want to catch database-related exceptions only
}
}
Well the only receipe that works is to have the knowledge of the underlying ADO.NET provider type, for instance SqlClient, and catch SqlException. Your code is no longer DB-agnostic.
There are many workarounds to this situation, some of them around the Template Method design pattern (which is basically what the Data Access App Block is all about), some others using Reflection (based on the assumption that OleDbException, SqlException, ... all have the same properties even though then do not inherit from a common base class)
But none of them is as clean as what Microsoft introduced in .NET 2.0 : the System.Data.Common.DbException class !
But I'm not quite sure I'm satisfied yet. OK I'm now able to catch all data access exceptions, but I'm not able to do anything intelligent with them, such as :
//some DAO
void InsertCustomer(Customer c)
{
try{
//the SQL INSERT statement execution
}catch(DbException e){
//what I want : if the DB tells me "DUPLICATE KEY",
//then throw a DuplicateCustomer exception, so that
//the controller up in the call stack will proceed to
//a meaningful error page
//But how the F*** do I determine that it is a duplicate key
//error (other than parsing the e.Message property or downcasting it
//to a SqlException ?)
}
}
So I would expect DbException to have common properties, such as a collection of errors, each one having a SqlState property to detect this primary key violation. After all SQL statuses values are (correct me if I'm wrong) part of the SQL Ansi specs, so it would make sense to expose them in the base class for all provider-specific exception classes.
BTW, isn't it the case with JDBC's SQLException class ?
What does the community think ?
One more blog
So I have a blog.
Frightening : am I doomed to spend every single night thinking about something intelligent to say, to finally realize the vacuum in my head ?
That's exactly what happened while starting this weblog :
1) choosing a language. Well, english *should* mean more potential readers, but more headaches as well. Finally Sebastien Ros's choice convinced me that all Sebs should be blogging in english.
2) finding a title. What about ICloneable, "Template Method", N2EE, void (*ptr)(void (*p)(void),int), or ldloc.0 ? Well, SyncLock(Me) is not so bad, it seems to say "stop on my page !"
All this took me close to 1 hour, not to mention the writing of those ~10 lines. Probably the blank page effect.
"Patience, j'apprends", said Laurent, well I guess I'm doing the very same thing.