2010-12-09 32 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指出的逗号,将不起作用。