在使用 ThenInclude() 时从列表 属性 中包含一个子项
Including One Subitem From A List property while Making use of ThenInclude()
我有一个功能,目的是通过它的 id 从数据库中提取拍卖并包括它的最高出价和最高出价的类型。
我能够使用这条线路获得最高出价
var result = _context.Auctions.
Include(a => a.AuctionBids.OrderByDescending(b => b.BidAmount).Take(1)).
FirstOrDefault(a => a.AuctionId == id);
当我添加其余部分以包括我使用的出价类型时
var result = _context.Auctions.
Include(a => a.AuctionBids.OrderByDescending(b => b.BidAmount).Take(1)).ThenInclude(b => b.AuctionBidType).AsNoTracking().
FirstOrDefault(a => a.AuctionId == id);
但是我得到一个错误
Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid column name 'AuctionBidTypeID'.
Invalid column name 'AuctionBidID'.
Invalid column name 'AuctionBidTypeID'.
Invalid column name 'BidAmount'.
Invalid column name 'BidDate'.
Invalid column name 'ExternalUserLoginID'.
删除 .Take(1)
按预期返回所有出价。我试过移动 .Take(1)
但我只是得到一个空响应或编译器错误。任何能给我指明正确方向的东西都会受到赞赏
我也检查过使用 First()
代替 Take(1)
它给出了这个错误
System.InvalidOperationException: The expression 'a.AuctionBids.AsQueryable().OrderByDescending(b => b.BidAmount).First()' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, use casting ('t => ((Derived)t).MyProperty') or the 'as' operator ('t => (t as Derived).MyProperty'). Collection navigation access can be filtered by composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take operations. For more information on including related data, see http://go.microsoft.com/fwlink/?LinkID=746393.
简化类
这些是我模型的简化版本
public partial class Auction
{
public Auction()
{
AuctionBids = new HashSet<AuctionBid>();
}
public long AuctionId { get; set; }
public long AuctionTypeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string LongDescription { get; set; }
public decimal BidIncrement { get; set; }
public decimal BidWarningCap { get; set; }
public decimal Reserve { get; set; }
public int CreatedById { get; set; }
public DateTime CreatedDate { get; set; }
public virtual AuctionType AuctionType { get; set; }
public virtual ICollection<AuctionBid> AuctionBids { get; set; }
}
public partial class AuctionBid
{
public long AuctionBidId { get; set; }
public long AuctionId { get; set; }
public int ExternalUserLoginId { get; set; }
public long AuctionBidTypeId { get; set; }
public DateTime BidDate { get; set; }
public decimal BidAmount { get; set; }
public virtual Auction Auction { get; set; }
public virtual AuctionBidType AuctionBidType { get; set; }
}
public partial class AuctionBidType
{
public AuctionBidType()
{
AuctionBids = new HashSet<AuctionBid>();
}
public long AuctionBidTypeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<AuctionBid> AuctionBids { get; set; }
}
这似乎是 EF-core 5 中的一个错误。生成的 SQL 查询(使用 SQL 服务器)在一行中有不正确的别名:
SELECT [t].[AuctionId], [t].[AuctionTypeId], [t].[BidIncrement], [t].[BidWarningCap], [t].[CreatedById], [t].[CreatedDate], [t].[Description], [t].[LongDescription], [t].[Name], [t].[Reserve], [t1].[AuctionBidId], [t1].[AuctionBidTypeId], [t1].[AuctionId], [t1].[BidAmount], [t1].[BidDate], [t1].[ExternalUserLoginId], [t1].[AuctionBidTypeId0], [t1].[Description], [t1].[Name]
FROM (
SELECT TOP(1) [a].[AuctionId], [a].[AuctionTypeId], [a].[BidIncrement], [a].[BidWarningCap], [a].[CreatedById], [a].[CreatedDate], [a].[Description], [a].[LongDescription], [a].[Name], [a].[Reserve]
FROM [Auctions] AS [a]
WHERE [a].[AuctionId] = CAST(1 AS bigint)
) AS [t]
OUTER APPLY (
-- Wrong aliases in line below. [t] should be [t0]
SELECT [t].[AuctionBidId], [t].[AuctionBidTypeId], [t].[AuctionId], [t].[BidAmount], [t].[BidDate], [t].[ExternalUserLoginId], [a1].[AuctionBidTypeId] AS [AuctionBidTypeId0], [a1].[Description], [a1].[Name]
FROM (
SELECT TOP(1) [a0].[AuctionBidId], [a0].[AuctionBidTypeId], [a0].[AuctionId], [a0].[BidAmount], [a0].[BidDate], [a0].[ExternalUserLoginId]
FROM [AuctionBid] AS [a0]
WHERE [t].[AuctionId] = [a0].[AuctionId]
ORDER BY [a0].[BidAmount] DESC
) AS [t0] -- This alias
INNER JOIN [AuctionBidType] AS [a1] ON [t].[AuctionBidTypeId] = [a1].[AuctionBidTypeId]
) AS [t1]
ORDER BY [t].[AuctionId], [t1].[BidAmount] DESC, [t1].[AuctionBidId], [t1].[AuctionBidTypeId0]
当我在不同的数据库模型上尝试类似的查询时,使用了正确的别名,但我无法断定查询中的哪一部分或 class/property 名称混淆了 EF。
幸运的是你可以使用 work-around(至少,我可以使用你的模型):
var result = _context.Auctions.AsNoTracking()
.Include(a => a.AuctionBids.OrderByDescending(b => b.BidAmount).Take(1))
.ThenInclude(b => b.AuctionBidType)
.Where(a => a.AuctionId == id)
.AsEnumerable()
.FirstOrDefault();
看来 FirstOrDefault(a => a.AuctionId == id)
是混淆查询生成器的部分。用 Where
替换它会使查询 运行。那么这只是切换到 in-memory 评估 (.AsEnumerable()
) 并在那里应用 .FirstOrDefault()
的问题。
在 EF-core 6 中,此错误已修复。别名 [t1]
用于上面的查询具有 [t]
和 [t0]
.
的地方
我有一个功能,目的是通过它的 id 从数据库中提取拍卖并包括它的最高出价和最高出价的类型。
我能够使用这条线路获得最高出价
var result = _context.Auctions.
Include(a => a.AuctionBids.OrderByDescending(b => b.BidAmount).Take(1)).
FirstOrDefault(a => a.AuctionId == id);
当我添加其余部分以包括我使用的出价类型时
var result = _context.Auctions.
Include(a => a.AuctionBids.OrderByDescending(b => b.BidAmount).Take(1)).ThenInclude(b => b.AuctionBidType).AsNoTracking().
FirstOrDefault(a => a.AuctionId == id);
但是我得到一个错误
Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid column name 'AuctionBidTypeID'.
Invalid column name 'AuctionBidID'.
Invalid column name 'AuctionBidTypeID'.
Invalid column name 'BidAmount'.
Invalid column name 'BidDate'.
Invalid column name 'ExternalUserLoginID'.
删除 .Take(1)
按预期返回所有出价。我试过移动 .Take(1)
但我只是得到一个空响应或编译器错误。任何能给我指明正确方向的东西都会受到赞赏
我也检查过使用 First()
代替 Take(1)
它给出了这个错误
System.InvalidOperationException: The expression 'a.AuctionBids.AsQueryable().OrderByDescending(b => b.BidAmount).First()' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, use casting ('t => ((Derived)t).MyProperty') or the 'as' operator ('t => (t as Derived).MyProperty'). Collection navigation access can be filtered by composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take operations. For more information on including related data, see http://go.microsoft.com/fwlink/?LinkID=746393.
简化类
这些是我模型的简化版本
public partial class Auction
{
public Auction()
{
AuctionBids = new HashSet<AuctionBid>();
}
public long AuctionId { get; set; }
public long AuctionTypeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string LongDescription { get; set; }
public decimal BidIncrement { get; set; }
public decimal BidWarningCap { get; set; }
public decimal Reserve { get; set; }
public int CreatedById { get; set; }
public DateTime CreatedDate { get; set; }
public virtual AuctionType AuctionType { get; set; }
public virtual ICollection<AuctionBid> AuctionBids { get; set; }
}
public partial class AuctionBid
{
public long AuctionBidId { get; set; }
public long AuctionId { get; set; }
public int ExternalUserLoginId { get; set; }
public long AuctionBidTypeId { get; set; }
public DateTime BidDate { get; set; }
public decimal BidAmount { get; set; }
public virtual Auction Auction { get; set; }
public virtual AuctionBidType AuctionBidType { get; set; }
}
public partial class AuctionBidType
{
public AuctionBidType()
{
AuctionBids = new HashSet<AuctionBid>();
}
public long AuctionBidTypeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<AuctionBid> AuctionBids { get; set; }
}
这似乎是 EF-core 5 中的一个错误。生成的 SQL 查询(使用 SQL 服务器)在一行中有不正确的别名:
SELECT [t].[AuctionId], [t].[AuctionTypeId], [t].[BidIncrement], [t].[BidWarningCap], [t].[CreatedById], [t].[CreatedDate], [t].[Description], [t].[LongDescription], [t].[Name], [t].[Reserve], [t1].[AuctionBidId], [t1].[AuctionBidTypeId], [t1].[AuctionId], [t1].[BidAmount], [t1].[BidDate], [t1].[ExternalUserLoginId], [t1].[AuctionBidTypeId0], [t1].[Description], [t1].[Name]
FROM (
SELECT TOP(1) [a].[AuctionId], [a].[AuctionTypeId], [a].[BidIncrement], [a].[BidWarningCap], [a].[CreatedById], [a].[CreatedDate], [a].[Description], [a].[LongDescription], [a].[Name], [a].[Reserve]
FROM [Auctions] AS [a]
WHERE [a].[AuctionId] = CAST(1 AS bigint)
) AS [t]
OUTER APPLY (
-- Wrong aliases in line below. [t] should be [t0]
SELECT [t].[AuctionBidId], [t].[AuctionBidTypeId], [t].[AuctionId], [t].[BidAmount], [t].[BidDate], [t].[ExternalUserLoginId], [a1].[AuctionBidTypeId] AS [AuctionBidTypeId0], [a1].[Description], [a1].[Name]
FROM (
SELECT TOP(1) [a0].[AuctionBidId], [a0].[AuctionBidTypeId], [a0].[AuctionId], [a0].[BidAmount], [a0].[BidDate], [a0].[ExternalUserLoginId]
FROM [AuctionBid] AS [a0]
WHERE [t].[AuctionId] = [a0].[AuctionId]
ORDER BY [a0].[BidAmount] DESC
) AS [t0] -- This alias
INNER JOIN [AuctionBidType] AS [a1] ON [t].[AuctionBidTypeId] = [a1].[AuctionBidTypeId]
) AS [t1]
ORDER BY [t].[AuctionId], [t1].[BidAmount] DESC, [t1].[AuctionBidId], [t1].[AuctionBidTypeId0]
当我在不同的数据库模型上尝试类似的查询时,使用了正确的别名,但我无法断定查询中的哪一部分或 class/property 名称混淆了 EF。
幸运的是你可以使用 work-around(至少,我可以使用你的模型):
var result = _context.Auctions.AsNoTracking()
.Include(a => a.AuctionBids.OrderByDescending(b => b.BidAmount).Take(1))
.ThenInclude(b => b.AuctionBidType)
.Where(a => a.AuctionId == id)
.AsEnumerable()
.FirstOrDefault();
看来 FirstOrDefault(a => a.AuctionId == id)
是混淆查询生成器的部分。用 Where
替换它会使查询 运行。那么这只是切换到 in-memory 评估 (.AsEnumerable()
) 并在那里应用 .FirstOrDefault()
的问题。
在 EF-core 6 中,此错误已修复。别名 [t1]
用于上面的查询具有 [t]
和 [t0]
.