我有一张我想要退回的发票DTO,其中包含发票项目列表,其中InvoiceLines是联结表格。
我的WebApi控制器代码:
var screenset =
from inv in context.Invoices where inv.InvoiceId == invoiceID
join line in context.InvoiceLines on inv.InvoiceId equals line.InvoiceId
join track in context.Tracks on line.TrackId equals track.TrackId into T
select new InvoiceDTO
{
InvoiceId = inv.InvoiceId,
InvoiceDate = inv.InvoiceDate,
CustomerId = inv.CustomerId,
CustomerFullName = inv.Customer.LastName + ", " + inv.Customer.FirstName,
CustomerPhoneNumber = inv.Customer.Phone,
BillingAddress = inv.BillingAddress,
BillingCity = inv.BillingCity,
BillingState = inv.BillingState,
BillingCountry = inv.BillingCountry,
BillingPostalCode = inv.BillingPostalCode,
Tracks = T.Select(t => new InvoiceTrackDTO
{
InvoiceLineId = line.InvoiceLineId,
TrackId = t.TrackId,
TrackName = t.Name,
Artist = t.Album.Artist.Name,
UnitPrice = line.UnitPrice,
Quantity = line.Quantity
})
};
var result = screenset.SingleOrDefault();
var response = Request.CreateResponse(HttpStatusCode.OK, result);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return response;
我的DTO定义如下:
public class InvoiceDTO
{
public int InvoiceId { get; set; }
public DateTime InvoiceDate { get; set; }
public int CustomerId { get; set; }
public string CustomerFullName { get; set; }
public string CustomerPhoneNumber { get; set; }
public string BillingAddress { get; set; }
public string BillingCity { get; set; }
public string BillingState { get; set; }
public string BillingCountry { get; set; }
public string BillingPostalCode { get; set; }
public IEnumerable<InvoiceTrackDTO> Tracks { get; set; }
}
public class InvoiceTrackDTO
{
public int InvoiceLineId { get; set; }
public int TrackId { get; set; }
public string TrackName { get; set; }
public string Artist { get; set; }
public decimal UnitPrice { get; set; }
public int Quantity { get; set; }
}
我的消费者代码是:
message = new HttpClient().GetMessage(host, path, q).Result;
invoice = message.GetObjectFromMessage<InvoiceDTO>().Result;
tracks = invoice.Tracks as IEnumerable<InvoiceTrackDTO>;
我的问题是,如果使用.ToList()调用ApiController,则会出错:
var result = screenset.ToList();
如果ApiController以.SingleOrDefault()返回,则它会成功返回发票,但发票项目不能超过一个。
var result = screenset.SingleOrDefault();
我正在尝试根据其ID获取单一发票,但发票中包含发票项目列表。
这可能吗?
提前致谢。
修改
如果我在消费者中这样做:
message = new HttpClient().GetMessage(host, path, q).Result;
invoice = message.GetObjectFromMessage<InvoiceDTO>().Result;
Debug.WriteLine("Invoice: " + invoice.ToJsonString());
tracks = invoice.Tracks as IEnumerable<InvoiceTrackDTO>;
Debug.WriteLine("Tracks: " + tracks.ToJsonString());
其中ToJsonString
是我将任何对象转换为Json字符串的扩展方法。我可以获得发票,但不能获得跟踪作为发票项目的曲目。
我得到的输出和错误如下:
发票:{&#34; InvoiceId&#34;:0,&#34; InvoiceDate&#34;:&#34; 0001-01-01T00:00:00&#34;,&#34; CustomerId&#34 ;:0,&#34; CustomerFullName&#34;:空,&#34; CustomerPhoneNumber&#34;:空,&#34; BillingAddress&#34;:空,&#34;结算城市&#34;:空,&# 34; BillingState&#34;:空,&#34; BillingCountry&#34;:空,&#34; BillingPostalCode&#34;:空,&#34;曲目&#34;:空}
曲目:null
抛出异常:&#39; System.ArgumentOutOfRangeException&#39;在System.Windows.Forms.dll
中
编辑2: 好的,只是为了清理一点。
我正在将内连接与组连接进行比较,如下所示:
Parent
Id Value
1 A
2 B
3 C
Child
Id ChildValue
1 a1
1 a2
1 a3
2 b1
2 b2
from p in Parent
join c in Child on p.Id equals c.Id
select new { p.Value, c.ChildValue }
Result
Value ChildValue
A a1
A a2
A a3
B b1
B b2
from p in Parent
join c in Child on p.Id equals c.Id into g
select new { Parent = p, Children = g }
Result
Value ChildValues
A [a1, a2, a3]
B [b1, b2]
C []
使用LINQ从Entity Framework返回时,内部联接可以工作,但不能进行组连接。
将像内连接一样返回组连接。
希望澄清我的问题:)
答案 0 :(得分:0)
好的,我意识到了这个问题。实体框架最终基于Linq生成SQL。在SQL中,没有包含子对象列表的父对象的概念。返回的记录数将是重复父列的子对象数。
我最初很匆忙,忘了简单的浏览器或Fiddler输出会显示原来的ApiController方法会返回这个:
所以修改你的DTO:
public class InvoiceAndItemsDTO
{
// Invoice
public int InvoiceId { get; set; }
public DateTime InvoiceDate { get; set; }
public int CustomerId { get; set; }
public string CustomerFullName { get; set; }
public string CustomerPhoneNumber { get; set; }
public string BillingAddress { get; set; }
public string BillingCity { get; set; }
public string BillingState { get; set; }
public string BillingCountry { get; set; }
public string BillingPostalCode { get; set; }
// Track
public int InvoiceLineId { get; set; }
public int TrackId { get; set; }
public string TrackName { get; set; }
public string Artist { get; set; }
public decimal UnitPrice { get; set; }
public int Quantity { get; set; }
}
并修改你的ApiController方法:
var screenset =
from inv in context.Invoices where inv.InvoiceId == invoiceID
join line in context.InvoiceLines on inv.InvoiceId equals line.InvoiceId
join track in context.Tracks on line.TrackId equals track.TrackId
select new InvoiceAndItemsDTO
{
InvoiceId = inv.InvoiceId,
InvoiceDate = inv.InvoiceDate,
CustomerId = inv.CustomerId,
CustomerFullName = inv.Customer.LastName + ", " + inv.Customer.FirstName,
CustomerPhoneNumber = inv.Customer.Phone,
BillingAddress = inv.BillingAddress,
BillingCity = inv.BillingCity,
BillingState = inv.BillingState,
BillingCountry = inv.BillingCountry,
BillingPostalCode = inv.BillingPostalCode,
InvoiceLineId = line.InvoiceLineId,
TrackId = track.TrackId,
TrackName = track.Name,
Artist = track.Album.Artist.Name,
UnitPrice = line.UnitPrice,
Quantity = line.Quantity
};
和您的消费者一样:
message = new HttpClient().GetMessage(host, path, q).Result;
tracks = message.GetObjectFromMessage<List<InvoiceAndItemsDTO>>().Result;
if (tracks != null)
{
invoice = tracks.First();
}