2010-12-09 20 views
1

Zuvor habe ich eine Frage zum Abrufen von Daten aus zwei Tabellen, wo ich eine Zeile in einer Tabelle und verbinden Sie es mit mehreren Zeilen in einer anderen Tabelle. Hier ist der Link zu dieser Diskussion: SQL Select data from two tables (one row -> multiple rows)So erhalten Sie Daten aus zwei SQL-Tabellen in. NET

Hier ist mein SQL-Code:

SELECT 
    customer.fName, customer.lName, phone.phoneNumber 
FROM 
    Customers customer 
     INNER JOIN phoneNumbers phone ON 
      customer.customerId = phone.customerId 

Was Ich mag würde jetzt wissen, ist: Was ist der beste Weg, diese Daten in .net organisiert zu bekommen?

Nehmen wir an, ich eine C# -Klasse, wie folgend haben:

public class CustomerDetails 
{ 
    int customerId; 
    string fname; 
    string lName; 
    List<string> phoneNumbers; 
} 

Aus Gründen der Diskussion nehmen wir an, dass die obige SQL-Abfrage gibt das folgende Ergebnis:

fname, lname, phonenumber
"John", "Smith", "111-111"
"Jane", "Doe", "222-1111"
"Jane", "Doe", "222-2222"

Auf einen Blick sehe ich, dass ich zwei Kunden habe; einer hat eine Telefonnummer und der andere zwei Telefonnummern. Wie kann ich Code schreiben, um dies effizient in C# zu analysieren?

+0

Führen Sie ADO oder Linq aus? – guildsbounty

+1

Woher weißt du, dass Jane Doe und Jane Doe nicht 2 getrennte Leute sind? –

+1

Ich weiß, dass Jane Doe und Jane Doe die gleiche Person sind, weil dies ein künstliches Beispiel ist :-). Meine realen Daten sind komplizierter. –

Antwort

3

Eine Möglichkeit ist die Verwendung von LINQ zum Erstellen einer Instanz der CustomerDetails-Klasse.

Lassen Sie mich wissen, wenn Sie ein Beispiel möchten.

Beispiel 1:

List<CustomerDetails> customers = db.Customers.Select(c => new CustomerDetails(){ 
                    customerId = c.customerID, 
                    fname = c.fName, 
                    lName = c.lName, 
                    phoneNumbers = (from p in db.PhoneNumbers where p.customerID == c.customerID select p.phoneNumber1).ToList<String>()}); 

Beispiel 2:

List<CustomerDetails> custs = (from c in db.Customers 
         select new CustomerDetails() 
         { 
          customerId = c.customerID, 
          fname = c.fName, 
          lName = c.lName, 
          phoneNumbers = (from p in db.PhoneNumbers where p.customerID == c.customerID select p.phoneNumber1).ToList<String>() 
         }).ToList<CustomerDetails>(); 
+0

Beispiel, bitte :-) –

0

Iterate über das Ergebnis für jede Zeile überprüfen, ob es in der Liste der Kunden ist, wenn nicht, fügen eine neue, wenn ja, fügen Sie die Telefonnummer der bestehenden hinzu.

Natürlich sollten Sie nicht die Zeichenfolge verwenden geeignete Klassen für den Zugriff auf die Datenbank, wie Ado.net.

+0

Ich habe tatsächlich etwas Code geschrieben, um zu iterieren, aber es scheint aufgebläht und klobig. Ich hatte gehofft, dass es einen effizienteren und saubereren Weg geben könnte. –

1

Ich verstehe, dass Sie für ORM Objekt-relationales Mapping suchen. In .NET kann ich IBatis.net oder LINQ empfehlen.

1

Lösung 1:
Ich gehe davon aus, dass die Datensätze mit Namen in den Ergebnissen der SQL-Abfrage sortiert werden und dass Sie auch die customerID wählen. Das Anfügen von "ORDER BY customer.fName, customer.lName" an Ihre ursprüngliche Abfrage wird den Trick tun.

Ich gehe davon aus, dass Sie Ihr Ergebnis in einem Datareader bekommen, so können Sie wie folgt vorgehen:

// Lets start by declaring a collection for our records 
List<CustomerDetails> myRecords = new List<CustomerDetails>(); 

// Iterate all records from the results and fill our collection 
while (yourReader.Read()) 
{ 
    int customerID = int.Parse(yourReader["customerID"]); 
    int nrRecords = myRecords.Count; 

    if (nrRecords > 0 && myRecords[nrRecords - 1].customerId == customerID) 
    { 
     myRecords[nrRecords - 1].phoneNumbers.Add(yourReader["phoneNumber"]); 
    } 
    else 
    { 
     CustomerDetails newCustomerDetails = new CustomerDetails(); 
     newCustomerDetails.customerId = customerID; 
     newCustomerDetails.fName = yourReader["fName"]; 
     newCustomerDetails.lName = yourReader["lName"]; 

     List<string> phoneNumberList = new List<string>(); 
     phoneNumberList.Add(yourReader["phoneNumber"]); 
     newCustomerDetails.phoneNumbers = phoneNumberList; 

     myRecords.Add(newCustomerDetails); 
    } 
} 

P. S. Wenn das Bestellen der Liste keine Option ist, dann können Sie nicht nur die zuletzt hinzugefügten Datensätze von customer id überprüfen, sondern müssen stattdessen die myRecords-Liste durchlaufen und nach deren Existenz suchen. Dies kann auf viele Arten geschehen, einschließlich mit myRecords.Contains() oder mit einer foreach.




Lösung 2:
die Telefonnummer Sie direkt von SQL Gruppierung. Erstellen Sie eine Funktion zum Auswählen einer durch Komma getrennte Zeichenfolge mit allen Telefonnummern eines bestimmten Kunden:

CREATE FUNCTION [dbo].[GetCommaSeparatedPhoneNumbers] 
(
    @customerID int 
) 
RETURNS varchar(max) 
AS 
BEGIN 
    declare @output varchar(max) 
    select @output = COALESCE(@output + ', ', '') + phoneNumbers 
    from phoneNumbers 
    where customerId = @customerID 

    return @output 
END 
GO 

Dann sind Sie schön die Liste aller Kunden auswählen können Sie wollen:

SELECT customerId, dbo.GetCommaSeparatedPhoneNumbers(customerId) 
FROM Customers 
GROUP BY customerId 

Dies wird zurückkehren:

"John", "Smith", "111-111" 
"Jane", "Doe", "222-1111,222-2222" 

Jetzt ist es alles eine Frage der die Ergebnisse mit einer foreach oder while-Schleife Parsen, aber keine Prüfung für existance benötigt wird. Teilen Sie die Zeichenfolge einfach in ',' und fügen Sie die Werte in die Liste ein. Wenn es eine Chance gibt, dass es für einige Kunden keine Telefonnummern gibt, können Sie dieses Feld für null filtern.

PS. Funktioniert nicht, wenn ein Komma wie in BQ in seinem Kommentar angegeben ist.

+0

-1. Diese Antwort setzt voraus, dass eine Telefonnummer kein Komma enthält. Kommas werden üblicherweise verwendet, um eine 2-Sekunden-Pause anzuzeigen, bevor die Nebenstellennummer gewählt wird. Darüber hinaus gibt es keinen Grund, die Datensätze in der Datenbank zu kombinieren, um zurückgegeben zu werden. –

Verwandte Themen