2010-11-18 7 views
0

Je crée un planificateur de tâches sur SQL Server 2008.
J'ai une table que j'utilise pour stocker des tâches. Chaque tâche est un nom de tâche (par exemple, ImportFile) et des arguments. Je stocke les arguments dans la colonne XML, car les différentes tâches ont des signatures différentes.Sélection d'une table à l'aide de la colonne XML

Table est comme suit:
Id:integer(PK) | operation:nvarchar | Arguments:xml

Avant faire la queue une tâche, je dois souvent pour vérifier que la tâche donnée n'a pas encore été prévue. La recherche est effectuée en fonction des opérations et des arguments. En utilisant Linq-to-Sql, comment puis-je vérifier si une opération donnée + args est déjà présente dans la file d'attente?

Je cherche quelque chose comme:

var isTaskScheduled = db.Tasks.Any(t => 
    t.Opearation == task.Operation && 
    t.Arguments == task.ArgumentsAsXElement); 

(qui ne fonctionne pas parce que SQL Server ne peut pas comparer le type XML)

Toutes les suggestions de mise en œuvre d'autres?

Répondre

1

Vous pouvez faire surface, par ex. une propriété de chaîne qui encapsule votre Arguments, ou peut-être qu'il suffirait d'avoir, par exemple, la longueur et un CRC de vos Arguments comme des propriétés supplémentaires de votre classe:

public partial class Task 
{ 
    public int ArgumentLength 
    { .... } 

    public int ArgumentCRC 
    { .... } 
} 

De cette façon, si vous pouvez comparer la longueur (de votre XML) et le CRC et ils correspondent, vous pouvez être sûr et sûr Supposons que les deux XML sont identiques. Votre chèque serait alors quelque chose comme:

var isTaskScheduled = 
    db.Tasks.Any(t => t.Operation == task.Operation && 
         t.ArgumentLength == task.ArgumentLength && 
         t.ArgumentCRC == task.ArgumentCRC); 

ou quelque chose comme ça.

+0

Oui, raisonnable. Mais j'ai un problème avec une partie * assez sûre. J'espérais qu'il existe une meilleure solution.Une variante de cette approche consiste à utiliser le CRC pour réduire significativement le sous-ensemble de résultats, puis (si plus d'un résultat est renvoyé), faire une comparaison XML (coûteuse). –

0

Vous pouvez écrire une classe qui implémente IComparable:

public class XMLArgument : IComparable 
{ 
    public XMLArgument(string argument) 
    { 

    } 

    public int CompareTo(object obj) 
    { 
     ... 
    } 
} 

var isTaskScheduled = db.Tasks.Any(t => 
    t.Opearation == task.Operation && 
    (new XMLArgument(t.Arguments)).CompareTo(new XMLArgument(task.ArgumentsAsXElement)) == 0); 
1

Cela peut être un étirement, mais vous pouvez utiliser un « Hashcode » lors de l'enregistrement des données à la base de données, puis interroger sur la valeur hashcode à date/heure ultérieure

Cela suppose que vous avez une classe qui représente votre entité de tâche et que vous avez substitué la méthode GetHashCode de cette classe. Maintenant, lorsque vous allez interroger la base de données pour voir si la tâche est dans la file d'attente planifiée, vous interrogez simplement le hashcode, évitant ainsi d'avoir à faire un xml piquer au moment de la requête.

var t1 = new Tâche {Opération = "Exécuter", Arguments = "someXElement.value"}; var t2 = new Tâche {Opération = "Exécuter", Arguments = "someXElement.value"};

dans le code au-dessus de t1 == t2 car vous surchargez GetHashCode et calculez le hachage pour Operation + Arguments.Value. Si vous stockez le hashcode dans la base de données, vous pouvez facilement dire si vous avez un objet dans le DB qui est égal au code de hachage que vous vérifiez.

Cela peut être similaire à ce dont parlait marc_s.

Questions connexes