Erstellen einer DataTable aus einer Abfrage (LINQ to DataSet)Creating a DataTable From a Query (LINQ to DataSet)

Das DataTable-Objekt wird häufig zur Datenbindung eingesetzt.Data binding is a common use of DataTable object. Die CopyToDataTable-Methode kopiert die Ergebnisse einer Abfrage in eine DataTable, die dann für die Datenbindung verwendet werden kann.The CopyToDataTable method takes the results of a query and copies the data into a DataTable, which can then be used for data binding. Wenn die Datenoperationen ausgeführt wurden, wird die neue DataTable wieder mit der ursprünglichen DataTable zusammengeführt.When the data operations have been performed, the new DataTable is merged back into the source DataTable.

Die CopyToDataTable-Methode verwendet den folgenden Prozess, um aus einer Abfrage eine DataTable zu erstellen:The CopyToDataTable method uses the following process to create a DataTable from a query:

  1. Die CopyToDataTable-Methode klont eine DataTable aus der Quelltabelle (ein DataTable-Objekt, das die IQueryable<T>-Schnittstelle implementiert).The CopyToDataTable method clones a DataTable from the source table (a DataTable object that implements the IQueryable<T> interface). Die IEnumerable Quelle stammt im Allgemeinen von einem LINQ to DataSet Ausdruck oder einer Methoden Abfrage.The IEnumerable source has generally originated from a LINQ to DataSet expression or method query.

  2. Das Schema der geklonten DataTable wird aus den Spalten des ersten aufgezählten DataRow-Objekts in der Quelltabelle generiert, und als Name für die geklonte Tabelle wird der Name der Quelltabelle mit dem Zusatz "Abfrage" verwendet.The schema of the cloned DataTable is built from the columns of the first enumerated DataRow object in the source table and the name of the cloned table is the name of the source table with the word "query" appended to it.

  3. Für jede Zeile in der Quelltabelle wird der Inhalt der Zeile in ein neues DataRow-Objekt kopiert, dass dann in die geklonte Tabelle eingefügt wird.For each row in the source table, the content of the row is copied into a new DataRow object, which is then inserted into the cloned table. Die Eigenschaften RowState und RowError bleiben beim Kopieren erhalten.The RowState and RowError properties are preserved across the copy operation. Wenn die ArgumentException-Objekte in der Quelle aus unterschiedlichen Tabellen stammen, wird eine DataRow ausgelöst.An ArgumentException is thrown if the DataRow objects in the source are from different tables.

  4. Nachdem alle DataTable-Objekte in der abfragbaren Eingabetabelle kopiert wurden, wird die geklonte DataRow zurückgegeben.The cloned DataTable is returned after all DataRow objects in the input queryable table have been copied. Wenn die Ausgangsfolge keine DataRow-Objekte enthält, gibt die Methode eine leere DataTable zurück.If the source sequence does not contain any DataRow objects, the method returns an empty DataTable.

Beachten Sie, dass ein Aufruf der CopyToDataTable-Methode zur Ausführung der an die Quelltabelle gebundenen Abfrage führt.Note that calling the CopyToDataTable method will cause the query bound to the source table to execute.

Wenn die CopyToDataTable-Methode in einer Zeile der Quelltabelle auf einen NULL-Verweis oder einen Wert trifft, der NULL zulässt, wird der Wert durch Value ersetzt.When the CopyToDataTable method encounters either a null reference or nullable value type in a row in the source table, it replaces the value with Value. Auf diese Weise werden die NULL-Werte in der zurückgegebenen DataTable korrekt behandelt.This way, null values are handled correctly in the returned DataTable.

Hinweis: Die CopyToDataTable -Methode akzeptiert eine Abfrage als Eingabe, die Zeilen aus mehreren DataTable - DataSet Objekten oder-Objekten zurückgeben kann.Note: The CopyToDataTable method accepts as input a query that can return rows from multiple DataTable or DataSet objects. Die CopyToDataTable-Methode kopiert die Daten, jedoch nicht die Eigenschaften, aus dem DataTable-Quellobjekt oder DataSet-Quellobjekt zum zurückgegebenen DataTable-Objekt.The CopyToDataTable method will copy the data but not the properties from the source DataTable or DataSet objects to the returned DataTable. Sie müssen die Eigenschaften explizit für das zurückgegebene DataTable-Objekt festlegen, z. B. Locale und TableName.You will need to explicitly set the properties on the returned DataTable, such as Locale and TableName.

Im folgenden Beispiel wird die Tabelle "SalesOrderHeader" nach Aufträgen abgefragt, die nach dem 8. August 2001 eingegangen sind. Dabei kommt die CopyToDataTable-Methode zum Einsatz, um aus dieser Abfrage eine DataTable zu erstellen.The following example queries the SalesOrderHeader table for orders after August 8, 2001 and uses the CopyToDataTable method to create a DataTable from that query. Die DataTable wird dann an eine BindingSource gebunden, die als Proxy für eine DataGridView fungiert.The DataTable is then bound to a BindingSource, which acts as proxy for a DataGridView.

// Bind the System.Windows.Forms.DataGridView object
// to the System.Windows.Forms.BindingSource object.
dataGridView.DataSource = bindingSource;

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable orders = ds.Tables["SalesOrderHeader"];

// Query the SalesOrderHeader table for orders placed 
// after August 8, 2001.
IEnumerable<DataRow> query =
    from order in orders.AsEnumerable()
    where order.Field<DateTime>("OrderDate") > new DateTime(2001, 8, 1)
    select order;

// Create a table from the query.
DataTable boundTable = query.CopyToDataTable<DataRow>();

// Bind the table to a System.Windows.Forms.BindingSource object, 
// which acts as a proxy for a System.Windows.Forms.DataGridView object.
bindingSource.DataSource = boundTable;
' Bind the System.Windows.Forms.DataGridView object
' to the System.Windows.Forms.BindingSource object.
dataGridView.DataSource = bindingSource

' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)

Dim orders As DataTable = ds.Tables("SalesOrderHeader")

' Query the SalesOrderHeader table for orders placed 
'  after August 8, 2001.
Dim query = _
    From order In orders.AsEnumerable() _
    Where order.Field(Of DateTime)("OrderDate") > New DateTime(2001, 8, 1) _
    Select order

' Create a table from the query.
Dim boundTable As DataTable = query.CopyToDataTable()

' Bind the table to a System.Windows.Forms.BindingSource object, 
' which acts as a proxy for a System.Windows.Forms.DataGridView object.
bindingSource.DataSource = boundTable

Erstellen einer benutzerdefinierten copydedatcustom<T->-MethodeCreating a Custom CopyToDataTable<T> Method

Die vorhandenen CopyToDataTable-Methoden arbeiten nur mit einer IEnumerable<T>-Quelle, bei der der generische Parameter T den Typ DataRow aufweist.The existing CopyToDataTable methods only operate on an IEnumerable<T> source where the generic parameter T is of type DataRow. Obwohl dies hilfreich ist, können Tabellen dabei nicht aus einer Sequenz von Skalartypen, aus Abfragen, die anonyme Typen zurückgeben, oder aus Abfragen, die Tabellenjoins durchführen, erstellt werden.Although this is useful, it does not allow tables to be created from a sequence of scalar types, from queries that return anonymous types, or from queries that perform table joins. Ein Beispiel für die Implementierung von zwei benutzerdefinierten CopyToDataTable Methoden, die eine Tabelle aus einer Sequenz von skalaren oder anonymen Typen laden, finden Sie unter Gewusst wie: Implementieren Sie das copydatable<t->, wobei der generische Typ t keine DataRows ist.For an example of how to implement two custom CopyToDataTable methods that load a table from a sequence of scalar or anonymous types, see How to: Implement CopyToDataTable<T> Where the Generic Type T Is Not a DataRows.

Für die Beispiele in diesem Abschnitt werden die folgenden benutzerdefinierten Typen verwendet:The examples in this section use the following custom types:

public class Item
{
    public int Id { get; set; }
    public double Price { get; set; }
    public string Genre { get; set; }
}

public class Book : Item
{
    public string Author { get; set; }
}

public class Movie : Item
{
    public string Director { get; set; }
}
Public Class Item
    Private _Id As Int32
    Private _Price As Double
    Private _Genre As String

    Public Property Id() As Int32
        Get
            Return Id
        End Get
        Set(ByVal value As Int32)
            _Id = value
        End Set
    End Property

    Public Property Price() As Double
        Get
            Return _Price
        End Get
        Set(ByVal value As Double)
            _Price = value
        End Set
    End Property

    Public Property Genre() As String
        Get
            Return _Genre
        End Get
        Set(ByVal value As String)
            _Genre = value
        End Set
    End Property

End Class
Public Class Book
    Inherits Item
    Private _Author As String
    Public Property Author() As String
        Get
            Return _Author
        End Get
        Set(ByVal value As String)
            _Author = value
        End Set
    End Property
End Class

Public Class Movie
    Inherits Item
    Private _Director As String
    Public Property Director() As String
        Get
            Return _Director
        End Get
        Set(ByVal value As String)
            _Director = value
        End Set
    End Property

End Class

BeispielExample

In diesem Beispiel werden die Tabellen SalesOrderHeader und SalesOrderDetail durch eine JOIN-Operation miteinander verknüpft, um die Onlinebestellungen für den Monat August abzurufen und aus der Abfrage eine Tabelle zu erstellen.This example performs a join over the SalesOrderHeader and SalesOrderDetail tables to get online orders from the month of August and creates a table from the query.

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable orders = ds.Tables["SalesOrderHeader"];
DataTable details = ds.Tables["SalesOrderDetail"];

var query =
    from order in orders.AsEnumerable()
    join detail in details.AsEnumerable()
    on order.Field<int>("SalesOrderID") equals
        detail.Field<int>("SalesOrderID")
    where order.Field<bool>("OnlineOrderFlag") == true
    && order.Field<DateTime>("OrderDate").Month == 8
    select new
    {
        SalesOrderID =
            order.Field<int>("SalesOrderID"),
        SalesOrderDetailID =
            detail.Field<int>("SalesOrderDetailID"),
        OrderDate =
            order.Field<DateTime>("OrderDate"),
        ProductID =
            detail.Field<int>("ProductID")
    };

DataTable orderTable = query.CopyToDataTable(); 
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)

Dim orders As DataTable = ds.Tables("SalesOrderHeader")
Dim details As DataTable = ds.Tables("SalesOrderDetail")


Dim query = _
    From order In orders.AsEnumerable() _
    Join detail In details.AsEnumerable() _
    On order.Field(Of Integer)("SalesOrderID") Equals _
            detail.Field(Of Integer)("SalesOrderID") _
    Where order.Field(Of Boolean)("OnlineOrderFlag") = True And _
            order.Field(Of DateTime)("OrderDate").Month = 8 _
    Select New With _
    { _
        .SalesOrderID = order.Field(Of Integer)("SalesOrderID"), _
        .SalesOrderDetailID = detail.Field(Of Integer)("SalesOrderDetailID"), _
        .OrderDate = order.Field(Of DateTime)("OrderDate"), _
        .ProductID = detail.Field(Of Integer)("ProductID") _
    }

Dim table As DataTable = query.CopyToDataTable()

BeispielExample

Im folgenden Beispiel wird eine Auflistung für Artikel abgefragt, deren Preis mehr als $ 9,99 beträgt, und eine Tabelle aus den Abfrageergebnissen erstellt.The following example queries a collection for items of price greater than $9.99 and creates a table from the query results.

// Create a sequence. 
Item[] items = new Item[] 
{ new Book{Id = 1, Price = 13.50, Genre = "Comedy", Author = "Gustavo Achong"}, 
  new Book{Id = 2, Price = 8.50, Genre = "Drama", Author = "Jessie Zeng"},
  new Movie{Id = 1, Price = 22.99, Genre = "Comedy", Director = "Marissa Barnes"},
  new Movie{Id = 1, Price = 13.40, Genre = "Action", Director = "Emmanuel Fernandez"}};

// Query for items with price greater than 9.99.
var query = from i in items
             where i.Price > 9.99
             orderby i.Price
             select i;

// Load the query results into new DataTable.
DataTable table = query.CopyToDataTable();
Dim book1 As New Book()
book1.Id = 1
book1.Price = 13.5
book1.Genre = "Comedy"
book1.Author = "Gustavo Achong"

Dim book2 As New Book
book2.Id = 2
book2.Price = 8.5
book2.Genre = "Drama"
book2.Author = "Jessie Zeng"

Dim movie1 As New Movie
movie1.Id = 1
movie1.Price = 22.99
movie1.Genre = "Comedy"
movie1.Director = "Marissa Barnes"

Dim movie2 As New Movie
movie2.Id = 1
movie2.Price = 13.4
movie2.Genre = "Action"
movie2.Director = "Emmanuel Fernandez"

Dim items(3) As Item
items(0) = book1
items(1) = book2
items(2) = movie1
items(3) = movie2

' Query for items with price greater than 9.99.
Dim query = From i In items _
            Where i.Price > 9.99 _
            Order By i.Price _
            Select New With {i.Price, i.Genre}

Dim table As DataTable
table = query.CopyToDataTable()

BeispielExample

Im folgenden Beispiel wird eine Auflistung für Artikel abgefragt, deren Preis mehr als $ 9,99 beträgt, und anschließend werden die Ergebnisse dargestellt.The following example queries a collection for items of price greater than 9.99 and projects the results. Die zurückgegebene Sequenz anonymer Typen wird in eine bestehende Tabelle geladen.The returned sequence of anonymous types is loaded into an existing table.

// Create a sequence. 
Item[] items = new Item[] 
{ new Book{Id = 1, Price = 13.50, Genre = "Comedy", Author = "Gustavo Achong"}, 
  new Book{Id = 2, Price = 8.50, Genre = "Drama", Author = "Jessie Zeng"},
  new Movie{Id = 1, Price = 22.99, Genre = "Comedy", Director = "Marissa Barnes"},
  new Movie{Id = 1, Price = 13.40, Genre = "Action", Director = "Emmanuel Fernandez"}};

// Create a table with a schema that matches that of the query results.            
DataTable table = new DataTable();
table.Columns.Add("Price", typeof(int));
table.Columns.Add("Genre", typeof(string));

var query = from i in items
             where i.Price > 9.99
             orderby i.Price
             select new { i.Price, i.Genre };

query.CopyToDataTable(table, LoadOption.PreserveChanges);
Dim book1 As New Book()
book1.Id = 1
book1.Price = 13.5
book1.Genre = "Comedy"
book1.Author = "Gustavo Achong"

Dim book2 As New Book
book2.Id = 2
book2.Price = 8.5
book2.Genre = "Drama"
book2.Author = "Jessie Zeng"

Dim movie1 As New Movie
movie1.Id = 1
movie1.Price = 22.99
movie1.Genre = "Comedy"
movie1.Director = "Marissa Barnes"

Dim movie2 As New Movie
movie2.Id = 1
movie2.Price = 13.4
movie2.Genre = "Action"
movie2.Director = "Emmanuel Fernandez"

Dim items(3) As Item
items(0) = book1
items(1) = book2
items(2) = movie1
items(3) = movie2

' Create a table with a schema that matches that of the query results.            
Dim table As DataTable = New DataTable()
table.Columns.Add("Price", GetType(Integer))
table.Columns.Add("Genre", GetType(String))

' Query for items with price greater than 9.99.
Dim query = From i In items _
            Where i.Price > 9.99 _
            Order By i.Price _
            Select New With {i.Price, i.Genre}

query.CopyToDataTable(table, LoadOption.PreserveChanges)

BeispielExample

Im folgenden Beispiel wird eine Auflistung für Artikel abgefragt, deren Preis mehr als $ 9,99 beträgt, und anschließend werden die Ergebnisse dargestellt.The following example queries a collection for items of price greater than $9.99 and projects the results. Die zurückgegebene Sequenz anonymer Typen wird in eine bestehende Tabelle geladen.The returned sequence of anonymous types is loaded into an existing table. Das Tabellenschema wird automatisch erweitert, da die Typen Book und Movies vom Item-Typ abgeleitet sind.The table schema is automatically expanded because the Book and Movies types are derived from the Item type.

// Create a sequence. 
Item[] items = new Item[] 
{ new Book{Id = 1, Price = 13.50, Genre = "Comedy", Author = "Gustavo Achong"}, 
  new Book{Id = 2, Price = 8.50, Genre = "Drama", Author = "Jessie Zeng"},
  new Movie{Id = 1, Price = 22.99, Genre = "Comedy", Director = "Marissa Barnes"},
  new Movie{Id = 1, Price = 13.40, Genre = "Action", Director = "Emmanuel Fernandez"}};

// Load into an existing DataTable, expand the schema and
// autogenerate a new Id.
DataTable table = new DataTable();
DataColumn dc = table.Columns.Add("NewId", typeof(int));
dc.AutoIncrement = true;
table.Columns.Add("ExtraColumn", typeof(string));

var query = from i in items
             where i.Price > 9.99
             orderby i.Price
             select new { i.Price, i.Genre };

query.CopyToDataTable(table, LoadOption.PreserveChanges);
Dim book1 As New Book()
book1.Id = 1
book1.Price = 13.5
book1.Genre = "Comedy"
book1.Author = "Gustavo Achong"

Dim book2 As New Book
book2.Id = 2
book2.Price = 8.5
book2.Genre = "Drama"
book2.Author = "Jessie Zeng"

Dim movie1 As New Movie
movie1.Id = 1
movie1.Price = 22.99
movie1.Genre = "Comedy"
movie1.Director = "Marissa Barnes"

Dim movie2 As New Movie
movie2.Id = 1
movie2.Price = 13.4
movie2.Genre = "Action"
movie2.Director = "Emmanuel Fernandez"

Dim items(3) As Item
items(0) = book1
items(1) = book2
items(2) = movie1
items(3) = movie2

' Load into an existing DataTable, expand the schema and
' autogenerate a new Id.
Dim table As DataTable = New DataTable()
Dim dc As DataColumn = table.Columns.Add("NewId", GetType(Integer))
dc.AutoIncrement = True
table.Columns.Add("ExtraColumn", GetType(String))

Dim query = From i In items _
            Where i.Price > 9.99 _
            Order By i.Price _
            Select New With {i.Price, i.Genre}

query.CopyToDataTable(table, LoadOption.PreserveChanges)

BeispielExample

Im folgenden Beispiel wird eine Auflistung für Artikel abgefragt, deren Preis mehr als $ 9,99 beträgt, und eine Sequenz von Double zurückgegeben, die in eine neue Tabelle geladen wird.The following example queries a collection for items of price greater than $9.99 and returns a sequence of Double, which is loaded into a new table.

// Create a sequence. 
Item[] items = new Item[] 
{ new Book{Id = 1, Price = 13.50, Genre = "Comedy", Author = "Gustavo Achong"}, 
  new Book{Id = 2, Price = 8.50, Genre = "Drama", Author = "Jessie Zeng"},
  new Movie{Id = 1, Price = 22.99, Genre = "Comedy", Director = "Marissa Barnes"},
  new Movie{Id = 1, Price = 13.40, Genre = "Action", Director = "Emmanuel Fernandez"}};

// load sequence of scalars.
IEnumerable<double> query = from i in items
             where i.Price > 9.99
             orderby i.Price
             select i.Price;

DataTable table = query.CopyToDataTable();
Dim book1 As New Book()
book1.Id = 1
book1.Price = 13.5
book1.Genre = "Comedy"
book1.Author = "Gustavo Achong"

Dim book2 As New Book
book2.Id = 2
book2.Price = 8.5
book2.Genre = "Drama"
book2.Author = "Jessie Zeng"

Dim movie1 As New Movie
movie1.Id = 1
movie1.Price = 22.99
movie1.Genre = "Comedy"
movie1.Director = "Marissa Barnes"

Dim movie2 As New Movie
movie2.Id = 1
movie2.Price = 13.4
movie2.Genre = "Action"
movie2.Director = "Emmanuel Fernandez"

Dim items(3) As Item
items(0) = book1
items(1) = book2
items(2) = movie1
items(3) = movie2

Dim query = From i In items _
            Where i.Price > 9.99 _
            Order By i.Price _
            Select i.Price

Dim table As DataTable
table = query.CopyToDataTable()

Siehe auchSee also