Ich stieß auf eine interessante Bug mit LINQ zu SQL. Sehen Sie sich den folgenden Code an, der aus einer LINQtoSQL-Abfrage einer Suchmaschine, die ich gerade schreibe, übersetzt wurde.LINQ to SQL und Objektlebenszeiten, Referenzen vs. Werte
Das Ziel der Abfrage ist, alle Gruppen zu finden, die die IDs "Joe", "Jeff", "Jim" in fortlaufender Reihenfolge haben.
Achten Sie besonders auf die Variablen localKeyword und localInt. Wenn Sie die Deklarationen dieser scheinbar nutzlosen lokalen Variablen löschen und sie durch die Proxys ersetzen würden, würden Sie feststellen, dass die Abfrage nicht mehr funktioniert.
Ich bin immer noch ein Anfänger mit LINQ zu SQL, aber es sieht aus wie es alle Einheimischen als Referenzen weitergegeben wird. Dies führt dazu, dass die Abfrage nur den Wert von lokalen Variablen hat, wenn die Abfrage ausgewertet wird. In LINQ to SQL endete meine Abfrage wie
Die Abfrage ist natürlich umschrieben. Was genau passiert, ist das ein Fehler? Ich möchte vielleicht besser verstehen, warum dies geschieht. Sie sollten den Code kompiliert in Visual Studio 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++;
}
}
}
}
Der Wert der Abfrage finden, nachdem der Code abgeschlossen ist sollte den Wert { "Joe", "Bored", 1}.
Als nitpick, Sie haben System.Linq verwendet; zweimal. –
Ich kann in Ihrem Code keine LINQ to SQL-Dateien sehen. Das ist nur LINQ zu Objekten. btw siehe: http://StackOverflow.com/Questions/1095707/what-is-the-Exact-Definition-of-A-Closure/1095770#1095770 –