Je suis tombé sur un bug intéressant avec linq à sql. Jetez un oeil sur le code ci-dessous qui est librement traduit à partir d'une requête LINQtoSQL à partir d'un moteur de recherche que j'écris.LINQ to SQL et les durées de vie des objets, les références et les valeurs
Le but de la requête est de trouver tous les groupes qui ont l'ID "Joe", "Jeff", "Jim" dans l'ordre consécutif.
Faites très attention aux variables nommées localKeyword et localInt. Si vous deviez supprimer les déclarations de ces apparemment variables locales inutiles et les remplacer par celles qu'ils mandatent, la requête ne fonctionnerait plus. Je suis encore un débutant avec linq to sql mais on dirait qu'il passe tous les locaux comme références. Cela entraîne la requête ayant uniquement la valeur de variables locales lorsque la requête est évaluée. Dans LINQ to SQL ma requête a fini par ressembler à
SELECT * FROM INDEX ONE, INDEX TWO, INDEX THREE
WHERE ONE.ID = 'Jim' and TWO.ID = 'Jim' and
TWO.SEQUENCE = ONE.SEQUENCE + 2 and
THREE.ID = 'Jim' and
THREE.SEQUENCE = ONE.SEQUENCE + 2 and
ONE.GROUP == TWO.GROUP and ONE.GROUP == THREE.GROUP
La requête est bien sûr paraphrasée. Qu'est-ce qui se passe exactement, est-ce un bug? Je demande peut-être mieux comprendre pourquoi cela se produit. Vous devriez trouver le code compile en studio visuel 2008.
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace BreakLINQ
{
class Program
{
public struct DataForTest
{
private int _sequence;
private string _ID;
private string _group;
public int Sequence
{
get
{
return _sequence;
}
set
{
_sequence = value;
}
}
public string ID
{
get
{
return _ID;
}
set
{
_ID = value;
}
}
public string Group
{
get
{
return _group;
}
set
{
_group = value;
}
}
}
static void Main(string[] args)
{
List<DataForTest> elements = new List<DataForTest>
{
new DataForTest() { Sequence = 0, ID = "John", Group="Bored" },
new DataForTest() { Sequence = 1, ID = "Joe", Group="Bored" },
new DataForTest() { Sequence = 2, ID = "Jeff", Group="Bored" },
new DataForTest() { Sequence = 3, ID = "Jim", Group="Bored" },
new DataForTest() { Sequence = 1, ID = "Jim", Group="Happy" },
new DataForTest() { Sequence = 2, ID = "Jack", Group="Happy" },
new DataForTest() { Sequence = 3, ID = "Joe", Group="Happy" },
new DataForTest() { Sequence = 1, ID = "John", Group="Sad" },
new DataForTest() { Sequence = 2, ID = "Jeff", Group="Sad" },
new DataForTest() { Sequence = 3, ID = "Jack", Group="Sad" }
};
string[] order = new string[] { "Joe", "Jeff", "Jim" };
int sequenceID = 0;
var query = from item in elements
select item;
foreach (string keyword in order)
{
if (sequenceID == 0)
{
string localKeyword = keyword;
query = from item in query
where item.ID == localKeyword
select item;
}
else
{
string localKeyword = keyword;
int localSequence = sequenceID;
query = from item in query
where (from secondItem in elements
where secondItem.Sequence == item.Sequence + localSequence &&
secondItem.ID == localKeyword
select secondItem.Group).Contains(item.Group)
select item;
}
sequenceID++;
}
}
}
}
La valeur de la requête fois le code terminée doit avoir la valeur { « Joe », « Bored », 1}.
Être pinailler, vous avez l'aide System.Linq; deux fois. –
Je ne vois pas d'éléments LINQ to SQL dans votre code. C'est seulement LINQ aux objets. btw voir: http://stackoverflow.com/questions/1095707/what-is-the-exact-definition-of-a-closure/1095770#1095770 –