2010-12-09 61 views
1

以前,我問了一個關於從兩個表中獲取數據的問題,我在表中取一行,並將其與另一個表中的多行進行連接。這裏的鏈接到討論:SQL Select data from two tables (one row -> multiple rows)如何從兩個SQL表中獲取數據到.net

這裏是我的SQL代碼:

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

我現在想知道的是:是什麼讓在.NET舉辦這個數據的最佳方式?

讓我們假設我有一個C#類如下:

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

爲了討論方便,我們假設上面的SQL查詢將返回以下結果:

FNAME,LNAME,phoneNumber的
「約翰」, 「史密斯」, 「111-111」
「簡」, 「李四」, 「222-1111」
「簡」, 「李四」, 「222-2222」

一目瞭然,我看到我有兩個客戶;一個有一個電話號碼,另一個有兩個電話號碼。我如何編寫代碼來在C#中有效地解析此代碼?

+0

您是由ADO還是Linq執行? – guildsbounty 2010-12-09 15:23:00

+1

你怎麼知道Jane Doe和Jane Doe不是兩個獨立的人? – 2010-12-09 16:02:17

+1

我知道Jane Doe和Jane Doe是同一個人,因爲這是一個人爲的例子:-)。我的真實數據更復雜。 – 2010-12-09 17:16:06

回答

3

一個選擇是使用LINQ創建CustomerDetails類的一個實例。

讓我知道你是否想要一個例子。

例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>()}); 

例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

例如,請:-) – 2010-12-09 15:23:16

0

遍歷結果,對於每一行檢查它是否在您的costumers的列表中,如果沒有,添加一個新的,如果是,將電話號碼添加到現有的。

當然,你不應該解析字符串使用合適的類訪問數據庫,如ado.net。

1

我知道您正在尋找ORM對象關係映射。在.NET中,我可以推薦IBatis.net或LINQ。

1

解決方案1:
我假定記錄由在SQL查詢的結果名稱排序,您還要選擇在客戶。將"ORDER BY customer.fName, customer.lName"附加到您的原始查詢將會有所斬獲。

我假設你得到的結果在一個DataReader,這樣你就可以做到以下幾點:

// 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); 
    } 
} 

附:如果訂購該清單不是一個選項,那麼您不能只檢查最新添加的記錄customerid - 而是需要遍歷myRecords列表並搜索它的存在。這可以通過許多方式完成,包括使用myRecords.Contains()或foreach。




解決方案2:
做的電話號碼直接從SQL分組。選擇一個逗號分隔的字符串與特定客戶的所有電話號碼創建一個功能:

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 

然後你就可以很好地選擇所有客戶的列表中選擇所需:

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

這將返回:

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

現在,它的解析與一個foreach或while循環的結果的所有問題,但需要對所有腦幹任何檢查。只需將字符串拆分爲','並將值插入列表中。如果有機會,某些客戶將沒有電話號碼,則可以將該字段過濾爲空。

PS。如果在他的評論中有BQ指出的逗號,將不起作用。