我从服务提供商那里获得一个以竖线分隔的平面文件供稿,其中包含所有合并为一个的发票,行项目和分配信息。但是,我处理此信息的对象模型已标准化。
我有一个(简化的)对象模型如下:
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;}
}
我的Feed文件类似于:
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
在此示例中,Invoice
1有两个LineItem
s,LineItem
1有2个Allocation
s。
我已将Feed文件作为records
加载到变量IList<string[]>
中,并在管道处拆分。
如何在单个Linq语句中将其构建为图形?看起来它应该相对简单,但是当我丢失对相关records
变量的引用时,我会在第二级丢失。
答案 0 :(得分: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;
}
}
}
答案 1 :(得分: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);
}