Transformace dat pomocí LINQ (C#)
Language-Integrated dotaz (LINQ) není pouze o načítání dat. Je to také výkonný nástroj pro transformaci dat. Pomocí dotazu LINQ můžete jako vstup použít zdrojovou sekvenci a upravit ji mnoha způsoby, abyste mohli vytvořit novou výstupní sekvenci. Samotnou sekvenci můžete změnit, aniž byste museli měnit prvky řazením a seskupením. Ale pravděpodobně nejúčinnější funkce dotazů LINQ je schopnost vytvářet nové typy. To je dosaženo v klauzuli Select . Můžete například provádět následující úlohy:
Sloučí více vstupních sekvencí do jedné výstupní sekvence, která má nový typ.
Vytvořte výstupní sekvence, jejichž prvky se skládají pouze z jedné nebo několika vlastností každého prvku ve zdrojové sekvenci.
Vytvořte výstupní sekvence, jejichž prvky se skládají z výsledků operací provedených ve zdrojových datech.
Vytvořte výstupní sekvence v jiném formátu. můžete například transformovat data z SQL řádků nebo textových souborů do XML.
Jsou to jenom několik příkladů. Tyto transformace je samozřejmě možné v jednom dotazu zkombinovat různými způsoby. Kromě toho se výstupní sekvence jednoho dotazu dá použít jako vstupní sekvence nového dotazu.
Spojování více vstupů do jedné výstupní sekvence
Dotaz LINQ můžete použít k vytvoření výstupní sekvence, která obsahuje prvky z více než jedné vstupní sekvence. následující příklad ukazuje, jak kombinovat dvě datové struktury v paměti, ale stejné zásady lze použít pro kombinování dat z XML nebo SQL nebo zdrojů datových sad. Předpokládejme následující dva typy tříd:
class Student
{
public string First { get; set; }
public string Last {get; set;}
public int ID { get; set; }
public string Street { get; set; }
public string City { get; set; }
public List<int> Scores;
}
class Teacher
{
public string First { get; set; }
public string Last { get; set; }
public int ID { get; set; }
public string City { get; set; }
}
Následující příklad ukazuje dotaz:
class DataTransformations
{
static void Main()
{
// Create the first data source.
List<Student> students = new List<Student>()
{
new Student { First="Svetlana",
Last="Omelchenko",
ID=111,
Street="123 Main Street",
City="Seattle",
Scores= new List<int> { 97, 92, 81, 60 } },
new Student { First="Claire",
Last="O’Donnell",
ID=112,
Street="124 Main Street",
City="Redmond",
Scores= new List<int> { 75, 84, 91, 39 } },
new Student { First="Sven",
Last="Mortensen",
ID=113,
Street="125 Main Street",
City="Lake City",
Scores= new List<int> { 88, 94, 65, 91 } },
};
// Create the second data source.
List<Teacher> teachers = new List<Teacher>()
{
new Teacher { First="Ann", Last="Beebe", ID=945, City="Seattle" },
new Teacher { First="Alex", Last="Robinson", ID=956, City="Redmond" },
new Teacher { First="Michiyo", Last="Sato", ID=972, City="Tacoma" }
};
// Create the query.
var peopleInSeattle = (from student in students
where student.City == "Seattle"
select student.Last)
.Concat(from teacher in teachers
where teacher.City == "Seattle"
select teacher.Last);
Console.WriteLine("The following students and teachers live in Seattle:");
// Execute the query.
foreach (var person in peopleInSeattle)
{
Console.WriteLine(person);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
The following students and teachers live in Seattle:
Omelchenko
Beebe
*/
Další informace najdete v tématu klauzule JOIN a klauzule SELECT.
Výběr podmnožiny jednotlivých zdrojových elementů
Existují dva hlavní způsoby, jak vybrat podmnožinu každého prvku ve zdrojové sekvenci:
Chcete-li vybrat pouze jednoho člena zdrojového prvku, použijte operaci tečka. V následujícím příkladu Předpokládejme, že
Customerobjekt obsahuje několik veřejných vlastností včetně řetězce s názvemCity. Při spuštění tento dotaz vytvoří výstupní sekvenci řetězců.var query = from cust in Customers select cust.City;Chcete-li vytvořit prvky, které obsahují více než jednu vlastnost ze zdrojového elementu, můžete použít inicializátor objektu s pojmenovaným objektem nebo anonymním typem. Následující příklad ukazuje použití anonymního typu k zapouzdření dvou vlastností z každého
Customerprvku:var query = from cust in Customer select new {Name = cust.Name, City = cust.City};
Další informace naleznete v tématu Inicializátory objektů a kolekcí a anonymní typy.
Transformace objektů v paměti do jazyka XML
dotazy LINQ usnadňují transformaci dat mezi datovými strukturami v paměti, SQL databází, ADO.NET datových sad a datovými proudy XML nebo dokumenty. Následující příklad transformuje objekty v datové struktuře v paměti do elementů XML.
class XMLTransform
{
static void Main()
{
// Create the data source by using a collection initializer.
// The Student class was defined previously in this topic.
List<Student> students = new List<Student>()
{
new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores = new List<int>{97, 92, 81, 60}},
new Student {First="Claire", Last="O’Donnell", ID=112, Scores = new List<int>{75, 84, 91, 39}},
new Student {First="Sven", Last="Mortensen", ID=113, Scores = new List<int>{88, 94, 65, 91}},
};
// Create the query.
var studentsToXML = new XElement("Root",
from student in students
let scores = string.Join(",", student.Scores)
select new XElement("student",
new XElement("First", student.First),
new XElement("Last", student.Last),
new XElement("Scores", scores)
) // end "student"
); // end "Root"
// Execute the query.
Console.WriteLine(studentsToXML);
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
Kód generuje následující výstup XML:
<Root>
<student>
<First>Svetlana</First>
<Last>Omelchenko</Last>
<Scores>97,92,81,60</Scores>
</student>
<student>
<First>Claire</First>
<Last>O'Donnell</Last>
<Scores>75,84,91,39</Scores>
</student>
<student>
<First>Sven</First>
<Last>Mortensen</Last>
<Scores>88,94,65,91</Scores>
</student>
</Root>
Další informace naleznete v tématu vytváření stromů XML v jazyce C# (LINQ to XML).
Provádění operací se zdrojovými elementy
Výstupní sekvence nemusí obsahovat žádné elementy nebo vlastnosti elementu ze zdrojové sekvence. Výstupem může být například sekvence hodnot, které jsou vypočítány pomocí zdrojového prvku jako vstupní argumenty.
Následující dotaz provede sekvenci čísel reprezentujících poloměry kroužků, vypočítá oblast pro každý poloměr a vrátí výstupní sekvenci obsahující řetězce naformátované pomocí počítané oblasti.
Každý řetězec výstupní sekvence bude formátován pomocí interpolace řetězce. Interpolovaná řetězcová událost bude mít $ před otevírací uvozovkou řetězce a operace může být provedena v rámci složených závorek umístěných uvnitř interpolované řetězcové řetězce. Po provedení těchto operací budou výsledky zřetězeny.
Poznámka
Volání metod ve výrazech dotazů není podporováno, pokud bude dotaz přeložen do jiné domény. například nemůžete volat běžnou metodu jazyka C# v, Technologie LINQ to SQL protože pro ni SQL Server nemá žádný kontext. Uložené procedury však lze namapovat na metody a volat je. Další informace najdete v tématu uložené procedury.
class FormatQuery
{
static void Main()
{
// Data source.
double[] radii = { 1, 2, 3 };
// LINQ query using method syntax.
IEnumerable<string> output =
radii.Select(r => $"Area for a circle with a radius of '{r}' = {r * r * Math.PI:F2}");
/*
// LINQ query using query syntax.
IEnumerable<string> output =
from rad in radii
select $"Area for a circle with a radius of '{rad}' = {rad * rad * Math.PI:F2}";
*/
foreach (string s in output)
{
Console.WriteLine(s);
}
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Area for a circle with a radius of '1' = 3.14
Area for a circle with a radius of '2' = 12.57
Area for a circle with a radius of '3' = 28.27
*/