【问题标题】:How merge two sequences into one?如何将两个序列合并为一个?
【发布时间】:2013-11-26 14:09:18
【问题描述】:

我有一些从数据库中检索数据的工作代码。为我的解决方案获得一些更好的代码对我来说很有趣。有没有一些方法可以将两个查询组合成一个或类似的东西?

Dim customerTitlesAndIDs = contex.CustomerTable.Select(Function(row) New
                           With {.ID = row.ID, .CustomerTitle = row.Title}).ToList()

Dim cutomerIdPayment = contex.CustomerPayments.Select(Function(table) New 
                       With
                       {
                           .ID = table.CustomerID,
                           .Range = table.PaymentsRange,
                           .Values = table.Values
                       }).ToList()

Dim customerInfos As New List(Of SCustomerInfo)

For Each customer In customerTitlesAndIDs

    Dim cID As Integer = customer.ID
    customerInfo.Add(New SCustomerInfo(CreateCustomerTable(), cID, customer.CustomerTitle))

    For Each cutomerPayments In cutomerIdPayment

        If cutomerPayments.ID = cID Then
            Dim rangeValue(1) As Object
            rangeValue(0) = cutomerPayments.Range
            rangeValue(1) = cutomerPayments.Values
            Dim dtRow As DataRow = customerInfos.Last().PaymentTable.NewRow()
            dtRow.ItemArray = rangeValue
            customerInfos.Last().PaymentTable.Rows.Add(dtRow)
        End If
    Next
Next

Return customerInfos

与 C# 相同的代码(希望没有出现语法错误):

var customerTitlesAndIDs = contex.CustomerTable.Select(row => new
                           { .ID = row.ID, .CustomerTitle = row.Title }).ToList();

var cutomerIdPayment = contex.CustomerPayments.Select(table => new
                       {
                           .ID = table.CustomerID,
                           .Range = table.PaymentsRange,
                           .Values = table.Values
                       }).ToList();

List<SCustomerInfo> customerInfos = new List<SCustomerInfo>;

foreach (var customer in customerTitlesAndIDs)
{
    int cID = customer.ID;
    customerInfos.Add(new SCustomerInfo(CreateCustomerTable(), cID, customer.CustomerTitle));

    foreach (var cutomerPayments in cutomerIdPayment)
    {
        if (cutomerPayments.ID = cID)
        {
            object[] rangeValue = new object[1] {cutomerPayments.Range, cutomerPayments.Values};
            DataRow dtRow = customerInfos.Last().PaymentTable.NewRow();
            dtRow.ItemArray = rangeValue;

            customerInfos.Last().PaymentTable.Rows.Add(dtRow);
        }
    }
}

以下Structure表示的SCustomerInfo(代码已简化):

Public Structure SWindAltitude
    Public PaymentTableAs DataTable
    Public Title As String
    Public ID As Integer
End Structure

C# 和 VB.NET 解决方案都会有所帮助。

【问题讨论】:

  • 也许只有我一个人,但我觉得如果您接受 C# 答案,您也应该发布 C# 代码,因为我不精通 VB
  • 你认为将 C# 和 VB.net 代码放在一个问题中会很好吗?
  • C# 和 VBNET 可能会受到威胁,而两者都依赖于 .NET Framework,两种语言都可以在两者之间轻松翻译,如果有人同时要求 C#/VBNET 解决方案特定语言的 .NET 问题。但是有些……人们喜欢对那些愚蠢的事情投反对票或删除标签。
  • 使用 JOIN contex.CustomerTable.Join(contex.CustomerPayments, ...)
  • 你能展示一些示例代码吗?

标签: c# .net sql vb.net linq


【解决方案1】:

尝试这样的事情,利用导航属性(你可能不得不按摩它,因为我不知道你的数据结构的确切构成):

var customerQuery = context.CustomerTable.Select( ct => 
    new { 
        ct.ID, 
        ct.CustomerTitle, 
        // use nav property to get customer payments
        CustomerPayments = ct.CustomerPayments.Select( cp => 
            new { 
                Range = cp.Range, 
                Values = cp.Values } ) } );

return customerQuery.ToArray()
    .Select( cq => 
        {
            var retVal = new SCustomerInfo( CreateCustomerTable(), cq.ID, cq.CustomerTitle ); 

            foreach( var customerPayment in cq.CustomerPayments )
            {
                var dtRow = cq.PaymentTable.NewRow();

                dtRow.ItemArray = new object[] { customerPayment.Range, customerPayment.Values };

                retVal.PaymentTable.Rows.Add( dtRow );
            }

            return retVal;
        } );

【讨论】:

  • 为什么在Select之前打电话给ToArray
  • 枚举来自 DB 的结果 - 在 LINQ to Entities 选择语句中不能有带参数的构造函数。调用ToArray() 从数据库中获取结果,我们现在使用IEnumerable&lt;T&gt;.Select(...)。如果没有.ToArray(),我们仍然会使用 L2E IQueryable&lt;T&gt;
  • SCustomerInfo 的构造函数和 CreateCustomerTable() 函数可能会被重构为与 L2E 一起使用,具体取决于它们所做的事情。
  • 我有兴趣学习如何,@pseudocoder。它使用非无参数构造函数实例化客户端对象。我很确定这在 L2E 中是不可能的——你会得到一个“只允许无参数构造函数”的异常消息
  • @Moho 我的意思是有可能只使用无参数的构造函数和对象初始化器来完成工作,“具体取决于它们做什么”。很显然,我们没有看到源头就无法判断。
【解决方案2】:

如果我在 c# 中用 linq 理解正确,它会是这样的

var customerInfos = customerTitlesAndIDs.Select((c)=>{
                        var ci = new SCustomerInfo(CreateCustomerTable(), c.ID, customer.CustomerTitle);
                        ci.PaymentTable = ci.PaymentTable.AsEnumerable().Union(
                                          cutomerIdPayment.Where(j=>j.ID == c.ID)
                                                          .Select(j=>{
                                                              var dtRow = ci.PaymentTable.NewRow();
                                                              dtRow.ItemArray = new object[] {
                                                                  customerPayment.Range,
                                                                  customerPayment.Values 
                                                              };
                                                              return dtRow;
                                          })).CopyToDataTable();
                        return ci;
                    }).ToList();

【讨论】:

  • 我怀疑 new SCustomerInfo(x,x,x) 可以从 LINQ to Entities 查询中调用,就像您在这里一样;请参阅@Moho 答案。
【解决方案3】:

我认为您可以使用 Linq 提供的函数 Sequence.concat(),如下所述:http://msdn.microsoft.com/en-us/library/vstudio/bb386979(v=vs.100).aspx

【讨论】:

    猜你喜欢
    • 2013-01-23
    • 2010-10-26
    • 1970-01-01
    • 2014-04-01
    • 1970-01-01
    • 2011-11-24
    • 2014-01-27
    相关资源
    最近更新 更多