我下面有一个查询,该查询应按ID,EntityName,DocType,管辖区对结果进行分组。对于每个组,查询还返回ProductList项目。
目前,如果该组包含一个或多个产品,那么我可以看到结果给出了一个包含Id,EntityName,DocType,Jurisdiction和ProductList组合的组,但是,如果结果中不包含某个产品特定的组我完全看不到该组。我想做的是显示分组,即使该分组中没有任何产品。因此,如果ProductList的计数为零,我想设置 ProductList =新列表NettingAgreementProductDto。任何输入将不胜感激。
var result = from nae in nettingAgreementEntities.Result
join no in nettingOpinions.Result
on nae.EntityId equals no.EntityId
join np in nettingProducts.Result
on no.ProductId equals np.Id
group np by new
{ nae.EntityId,
nae.EntityName,
nae.DocType,
nae.Jurisdiction
} into g
select new NettingAgreementEntityDto
{
Id = g.Key.EntityId,
EntityName = g.Key.EntityName,
DocType = g.Key.DocType,
Jurisdiction = g.Key.Jurisdiction,
ProductList = g.Select(x => new
NettingAgreementProductDto
{
Id = x.Id,
Name = x.Name
}).ToList()
};
答案 0 :(得分:2)
要回顾评论,当前您的查询使用Inner Join来将NettingAgreementEntity
与NettingAgreementProduct
关联。这不仅会乘以结果集(因此需要您在之后使用GroupBy
),而且还会过滤掉NettingAgreementEntity
而没有NettingAgreementProduct
的情况。
您可以通过切换到Group Join(或Left Outer Join + GroupBy
)来实现目标。
但是为什么要输入所有这些并发症呢? EF导航属性使您几乎无需考虑手动联接,还可以轻松查看多重性,从而了解是否需要对结果进行分组。
所以我建议将当前缺少的集合导航属性添加到您的NettingAgreementEntity
类中:
public class NettingAgreementEntity
{
// ...
public virtual ICollection<NettingOpinion> Opinions { get; set; }
}
(可选)对NettingAgreementProduct
执行相同的操作,以防将来您需要类似的产品(这是多对多关系,应该可以从双方查询)。
我还要将NettingOpinion
类导航属性NettingAgreementProductNavigation
和NettingAgreementEntityNavigation
重命名为较短的名称,例如Product
和Entity
。这些名称(以及集合导航属性的名称)不会影响数据库架构,但是IMHO具有更好的可读性。
有了这些,您将看到所需的LINQ查询是一个简单的Select
事务,它将实体类转换为DTO,并让EF查询翻译器为您生成必要的联接:
var result = db.Set<NettingAgreementEntity>()
.Selec(nae => new NettingAgreementEntityDto
{
Id = nae.EntityId,
EntityName = nae.EntityName,
DocType = nae.DocType,
Jurisdiction = nae.Jurisdiction,
ProductList = nae.Opinions
.Select(no => new NettingAgreementProductDto
{
no.Product.Id,
no.Product.Name,
}).ToList(),
});
答案 1 :(得分:0)
以下是我到目前为止尝试过的。我认为该查询在此阶段还不太正确,因为它仍然忽略了没有产品的组。
NettingOpinion实体
CREATE TABLE Table1 (a int,
b numeric(12,2),
c datetime2(0),
d date,
e varchar(20),
f sysname,
g varbinary);
CREATE TABLE Table2 (a int,
b numeric(12,2),
c datetime2(0),
d date);
GO
DECLARE @SQL nvarchar(MAX);
SET @SQL = STUFF((SELECT NCHAR(13) + NCHAR(10) +
N'ALTER TABLE Table2 ADD ' + QUOTENAME(T1.name) + N' ' + T1.system_type_name + N';'
FROM sys.dm_exec_describe_first_result_set(N'SELECT * FROM Table1',NULL, NULL) T1
WHERE NOT EXISTS(SELECT 1
FROM sys.dm_exec_describe_first_result_set(N'SELECT * FROM Table2',NULL, NULL) T2
WHERE T1.[name] = T2.[name])
ORDER BY T1.column_ordinal
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,2,N'');
PRINT @SQL;
EXEC sp_executesql @SQL;
GO
SELECT *
FROM dbo.Table2;
GO
DROP TABLE dbo.Table2;
DROP TABLE dbo.Table1;
NettingAgreementProduct实体
[Table("NettingOpinion",Schema = "dbo")]
public class NettingOpinion
{
[Key]
[Column("NettingOpinionID")]
public int NettingOpinionId { get; set; }
[Column("ProductID")]
public int ProductId { get; set; }
[Column("EntityID")]
public int EntityId { get; set; }
[ForeignKey("ProductId")]
public virtual NettingAgreementProduct NettingAgreementProductNavigation { get; set; }
[ForeignKey("EntityId")]
public virtual NettingAgreementEntity NettingAgreementEntityNavigation { get; set; }
}
NettingAgreementEntity
public class NettingAgreementProduct
{
public NettingAgreementProduct()
{
NettingAgreementDefaults = new HashSet<NettingAgreementDefaults>();
}
[Column("ProductID")]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
[Column("ProductName")]
[StringLength(255)]
public string Name { get; set; }
public virtual ICollection<NettingAgreementDefaults> NettingAgreementDefaults { get; set; }
}
实际查询
[Table("NettingAgreementEntity")]
public class NettingAgreementEntity
{
[Key]
[Column("EntityID")]
public int EntityId { get; set; }
[MaxLength(50,ErrorMessage = "DocType Cannot be more than 50 characters")]
[Required]
public string DocType { get; set; }
[Column("Jurisdiction")]
[MaxLength(2, ErrorMessage = "Jurisdiction Cannot have more than two characters")]
[Required]
public string Jurisdiction { get; set; }
[MaxLength(255,ErrorMessage = "EntityName Cannot have more than 255 characters")]
[Required]
public string EntityName { get; set; }
[ForeignKey("DocType")]
public virtual DocType DocTypeNavigation { get; set; }
}