0

我从服务提供商处获得了一个以竖线分隔的平面文件提要,其中包含发票、行项目和分配信息,它们都合并为一个。但是,我处理这些信息的对象模型是标准化的。

我有一个(简化的)对象模型,如下所示:

public class Invoice
{
    public int InvoiceId {get; set;}
    public decimal Amount {get; set;}
    public virtual ICollection<LineItem> LineItems {get; set;}
}

public class LineItem
{
    public virtual Invoice Invoice {get; set}
    public int SequenceNumber {get; set;}
    public decimal Quantity {get; set;}
    public decimal PricePerUnit {get; set;}
    public virtual ICollection<Allocation> Allocations {get; set;}
}

public class Allocation
{
    public virtual LineItem LineItem {get; set;}
    public string Account {get; set;}
    public decimal Distribution {get; set;}
}

我的提要文件类似于:

InvoiceId|Amount|LineItemSequenceNumber|Quantity|PricePerUnit|Account|Distribution
1|100.00|1|1.0|50.00|1234567890|25.00
1|100.00|1|1.0|50.00|1111111111|25.00
1|100.00|2|50.0|1.00|1234567890|50.00
2|50.00|1|1.0|50.00|1234567890|50.00

在这个例子中,Invoice1 有两个LineItems,LineItem1 有 2 个Allocation

我已将提要文件加载到变量recordsas 中IList<string[]>,并在管道处拆分。

如何在单个 Linq 语句中将其构建为图形?看起来它应该相对简单,但是当我失去对相关records变量的引用时,我会迷失在第二级。

4

2 回答 2

1
var invoices = (from r in input.Split(new [] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Split('|'))
                let invoiceId = int.Parse(r[0], CultureInfo.InvariantCulture)
                let amount = decimal.Parse(r[1], CultureInfo.InvariantCulture)
                let itemSequenceNumber = int.Parse(r[2], CultureInfo.InvariantCulture)
                let quantity = decimal.Parse(r[3], CultureInfo.InvariantCulture)
                let pricePerUnit = decimal.Parse(r[4], CultureInfo.InvariantCulture)
                let account = r[5]
                let distribution = decimal.Parse(r[6], CultureInfo.InvariantCulture)
                group new { amount, itemSequenceNumber, quantity, pricePerUnit, account, distribution } by invoiceId into g
                select new Invoice() {
                    InvoiceId = g.Key,
                    Amount = g.First().amount,
                    LineItems = (from i in g
                                 group i by i.itemSequenceNumber into g2
                                 select new LineItem() {
                                     SequenceNumber = g2.Key,
                                     Quantity = g2.First().quantity,
                                     PricePerUnit = g2.First().pricePerUnit,
                                     Allocations = (from a in g2
                                                    select new Allocation() {
                                                        Account = a.account,
                                                        Distribution = a.distribution
                                                    }).ToList()
                                 }).ToList()
                }).ToList();

它不设置导航属性。毕竟,您必须使用另一个查询或循环来设置它们,例如

foreach(var i in invoices)
{
    foreach(var l in i.LineItems)
    {
        l.Invoice = i;
        foreach(var a in l.Allocations)
        {
            a.LineItem = l;
        }
    }
}
于 2013-11-08T16:48:49.053 回答
0

试试这个,看看它是否有效:

var records = new List<string[]>();

var invoices = new List<Invoice>();

// load records from file

foreach (var record in records)
{
    var id = Convert.ToInt32(record[0]);
    var myInvoice = invoices.SingleOrDefault(i => i.Id == id);
    if (myInvoice == null)
    {
        myInvoice = new Invoice();
        myInvoice.Id = id;
        myInvoice.Amount = Convert.ToDecimal(record[1]);
        myInvoice.LineItems = new ICollection<LineItem>();
        invoices.Add(myInvoice);
    }

    var sequenceNumber = Convert.ToInt32(record[2]);
    var myLineItem = myInvoice.LineItems.SingleOrDefault(li => li.SequenceNumber == sequenceNumber);
    if (myLineItem == null)
    {
        myLineItem = new LineItem();
        myLineItem.SequenceNumber = sequenceNumber;
        myLineItem.Quantity = Convert.ToDecimal(record[3]);
        myLineItem.PricePerUnit = Convert.ToDecimal(record[4]);
        myLineItem.Allocations = new ICollection<Allocation>();
        myInvoice.LineItems.Add(myLineItem);
    }

    var myAllocation = new Allocation();
    myAllocation.Account = record[5];
    myAllocation.Distribution = Convert.ToDecimal(record[6]);
    myLineItem.Allocations.Add(myAllocation);
}
于 2013-11-08T17:09:17.020 回答