Accessing Windows Azure Diagnostics Logs With LINQPad

If you are using Windows Azure Diagnostics with the DiagnosticMonitorTraceListener you will most likely have a table in your storage account called WADLogsTable with a ton of data in it. It can be a bit overwhelming.

A colleague and I wanted to get two simple pieces of information: an event’s date and the corresponding message. Furthermore, we only wanted events that had happened today. Here’s what we came up with using LINQPad and the Azure Storage Driver.

First, make sure you’re using a table storage account as your database. In my case, my connection is called mycloudstorageaccount.

Then simply perform your query. If you want to copy/paste, here’s the text version:

from l in WADLogsTable
where l.PartitionKey.CompareTo(DateTime.Today.Ticks.ToString("d19")) > 0
select new
{
	DateTime = new DateTime(l.EventTickCount.Value),
	l.Message
}

Oh, and don’t forget to check out the SQL tab if you are interested in the « low level stuff. » It will show the actual URL that was used to query Windows Azure.

Publicités

Driver Azure Table Storage pour LINQPad

Vous connaissez LINQPad ? Scott Hanselman le recommande systématiquement dans liste annuelle d’outils pour développeurs. En ce qui me concerne, je m’en sers pratiquement tous les jours—enfin, quand je développe.

linqpad

À la base, c’est un logiciel qui vous permet d’exécuter des requêtes Linq :

linq_query

Mais ça permet aussi d’exécuter des bouts de code arbitraires, juste pour voir ce que ça donne :

code_sample

La fonctionnalité que j’utilise le plus c’est définitivement celle-ci, mais ces derniers temps je travaille de plus en plus avec Windows Azure et notamment Table Storage. Bien que LINQPad supporte des requêtes sur SQL Azure, j’étais un peu embêté quand il s’agissait d’effectuer rapidement des requêtes sur le Table Storage. Du coup, j’ai décidé d’écrire un driver pour le supporter !

Le driver permet d’ajouter des comptes de stockage (storage accounts) en tant que connexions LINQPad :

add_storage_account

Une fois que vous avez ajouté le compte—qui peut être votre compte de développement local, si l’émulateur est activé, ou un compte sur le cloud—vous le verrez apparaitre dans la liste de connexions avec ses tables et leurs colonnes.

linqpad_tables

La suite c’est du LINQPad “comme d’habitude”. Enfin, si vous avez vos habitudes, sinon vous pouvez commencer par un clic droit sur une table pour insérer une des requêtes par défaut.

Evidemment, pour ce faire, il faut télécharger le driver. Vous avez deux choix :

Petit warning : on est en version 1.0.0-beta. Ça veut dire que je n’ai pas testé le code, mais qu’il a l’air de marcher. Si vous utilisez Azure Table Storage et LINQPad et que vous voulez tester le driver, tout feedback est bienvenu !

You cannot always be that optimistic

I’m talking about optimistic concurrency of course.

As I’ve said before, my blog now runs on a new engine. To make a long story short, I lost my old blog, I wanted to play with the newest Microsoft technologies, so I picked up the engine my friend Patrice is working on that uses ASP.NET, C# 3.0 and LINQ (and a sprinkle of ASP.NET AJAX here and there). And it’s great! What’s more, I now have material for blogging.

So, what am I going to start with? If « optimistic concurrency » and the paragraph above didn’t give you a hint, I’m going to talk about LINQ. LINQ to SQL to be precise, or DLINQ, however you want to call it.

Let’s start from the beginning. What is LINQ? Lire la suite

No siempre se puede ser tan optimista

Estoy hablando de la concurrencia optimista (optimistic concurrency) por supuesto.

Como ya lo he dicho, mi blog ahora funciona con un nuevo motor. Para no cansarlos con el cuento, perdí mi blog, quería jugar con las últimas tecnologías de Microsoft, así que recuperé el motor de mi amigo Patrice que utiliza ASP.NET, C# 3.0  y LINQ (y una pizca de ASP.NET AJAX aquí y allá). ¡Y es genial! No solo eso, sinon que también tengo material para el blog.

Así que, por qué voy a comenzar? Si la « concurrencia optimista » y el parráfo de arriba no les a dado pistas, voy a habler de LINQ. LINQ to SQL para ser exactos, o DLINQ, como quieran llamarle.

Empecemos desde el principio. ¿Qué es LINQ? Lire la suite

On ne peut pas toujours être aussi optimiste

Je parle de l’accès simultané optimiste (optimistic concurrency) bien sûr.

Comme je l’ai déjà dit, mon blog marche maintenant avec un nouveau moteur. Pour résumer, j’ai perdu mon ancien blog, je voulais jouer avec les dernières technologies Microsoft, donc j’ai repris le moteur sur lequel travaille mon ami Patrice et qui utilise ASP.NET, C# 3.0 et LINQ (et un tout petit peu d’ASP.NET AJAX par ci et par là). Et c’est génial ! Et en plus, j’ai maintenant du matériel pour blogguer.

Alors, par où vais-je commencer ? Si « l’accès simultané optimiste » et le paragraphe ci-dessus ne vous ont pas donné d’indice, je vais parler de LINQ. LINQ to SQL pour être exact, ou DLINQ, peu importe comment on l’appelle.

On va commencer par le début. Qu’est-ce que LINQ ?

LINQ, un nom de code qui veut dire Language Integrated Queries (requêtes intégrées au langage), est un ensemble d’extensions pour C# et Visual Basic qui donne à ces langages une syntaxe native pour réaliser des requêtes. Des requêtes sur quoi ? Bien, pour le moment, ça peut être tout allant des objets (LINQ to Object), du XML (LINQ to XML) ou des bases de données (LINQ to SQL et LINQ to Entities).

Et à quoi ça ressemble ? Voici un exemple en C# :

var query = from p in db.Posts
            orderby p.date_post descending
            select new {
                       Title = p.title_post,
                       Description = p.text_post,
                       Date = p.date_post,
                       p.url_post,
                       Tags = p.PostsTags,
                       CommentCount = p.PostsComments.Count };

Vous n’allez peut-être pas me croire, mais le code ci-dessus est bien du C#. Et qu’est-ce que je fais ? Bon, je ne vais pas rentrer dans les détails, mais que fais des requêtes sur ma base de données pour récupérer des posts du blog. La requête est stockée dans une variable typée implicitement à partir de l’opération à droite de l’assignation et les résultats seront des objets d’un type anonyme qui contiendra les propriétés définies entre accolades. Comme c’est du DLINQ que j’utilise, le code ci-dessus sera converti en SQL pour être exécuté sur SQL Server (oui, c’est le seul serveur supporté actuellement).

Et qu’est-ce qu’il en est de cet « accès simultané optimiste » ? Qu’est-ce que c’est et qu’est-ce que ça fait ?

L’accès simultané optimiste est un modèle utilisé pour la mise à jour de bases de données dans des environnements multi-utilisateurs. En quelques mots, ça consiste à comparer un ou plusieurs champs de l’enregistrement à mettre à jour pour verifier qu’il n’a pas été modifié par quelqu’un d’autre depuis la dernière fois qu’il a été accédé. C’est une approche valide utilisée en ADO.NET et LINQ.

Alors, quel est le problème ?

Le code ci-dessus marche avec les classes créées par le nouveau designer LINQ livré avec Visual Studio Orcas, ou devrais-je dire 2008. Et ce code marche très bien pour récupérer tous les posts de la base, mais les problèmes commencent quand j’essaie de mettre à jour un enregistrement comme ceci :

var query = from p in db.Posts
            where p.id_post == int.Parse(postid)
            select p;

Post originalPost = query.FirstOrDefault();

originalPost.title_post = newPost.title;
originalPost.text_post = newPost.description;

db.SubmitChanges();

J’avais l’erreur « SQL Server does not handle comparison of NText, Text, XML, or Image data types » (SQL Server ne supporte pas la comparaison de types NText, Text, XML ou Image) et je ne comprenais pas pourquoi.

D’après le message, je pouvais deviner qu’il y avait un problème avec la requête générée qui doit comparer tous les champs de ma table avant la mise à jour pour un accès simultané optimiste. Toutefois, si l’on regarde ce que dit le designer, ça ne devrait pas être le cas, du moins pas pour la seule colonne NText :

dlinq_designer_update_check

Ah, mais regardez le code généré et qu’est ce que l’on voit ?

[global::System.Data.Linq.Column(Storage="_text_post", Name="text_post",
    DBType="NText NOT NULL", CanBeNull=false)]
public string text_post {
    // ...
}

En fait, le problème n’est pas tellement ce que l’on voit, mais ce qui manque : il manque un attribut sur la propriété :

[global::System.Data.Linq.Column(Storage="_text_post", Name="text_post",
    DBType="NText NOT NULL", CanBeNull=false,
    UpdateCheck=System.Data.Linq.UpdateCheck.Never
)]
public string text_post {
    // ...
}

Maintenant la colonne NText ne sera pas comparée et LINQ générera la bonne requête.