C# 在实体框架中选择不同的行

C# 在实体框架中选择不同的行,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我正在尝试使用Entity Framework查询SQL Server视图,并且只返回基于多列的不同行 我尝试了一个基于(GroupBy然后Select(g=>g.FirstOrDefault())的解决方案,但仍然得到重复的行 表结构(这在实际数据库中是一个相当复杂的视图,但最终输出的结构与本例类似): 创建表示例( 我是个大人物, ID_B BIGINT, ID_C BIGINT, A型NVARCHAR(50), B型NVARCHAR(50), ID_Z BIGINT, 富纳查(200),

我正在尝试使用Entity Framework查询SQL Server视图,并且只返回基于多列的不同行

我尝试了一个基于(
GroupBy
然后
Select(g=>g.FirstOrDefault())
的解决方案,但仍然得到重复的行

表结构(这在实际数据库中是一个相当复杂的视图,但最终输出的结构与本例类似):

创建表示例(
我是个大人物,
ID_B BIGINT,
ID_C BIGINT,
A型NVARCHAR(50),
B型NVARCHAR(50),
ID_Z BIGINT,
富纳查(200),
酒吧女服务员(200)
)
示例数据:

插入示例(ID_A、ID_B、ID_C、Type_A、Type_B、ID_Z、Foo、Bar)
值(1,1,1,'TypeA1','TypeB1',1,'foo1','bar1'),--此行和下一行表示连接到不同“Z”记录(1和2)的相同主记录(1)
(1,1,1,'TypeA1','TypeB1',2,'foo1','bar1'),
(2,1,2,'TypeA2','TypeA2',1,'foo2','bar2'),--此行和下两行表示连接到不同“Z”记录(1,2和3)的相同主记录(2)
(2,1,2,'TypeA2','TypeA2',2,'foo2','bar2'),
(2,1,2,'TypeA2','TypeA2',3,'foo2','bar2')
实体类:

公共类示例实体
{
[关键]
公共长ID_A{get;set;}
公共长ID_B{get;set;}
公共长ID_C{get;set;}
公共字符串类型_A{get;set;}
公共字符串类型_B{get;set;}
公共long?ID_Z{get;set;}
公共字符串Foo{get;set;}
公共字符串条{get;set;}
实体配置:

public类示例EntityConfiguration:EntityTypeConfiguration
{
公共示例EntityConfiguration()
{
//性质
this.Property(t=>t.ID\u A)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
//表和列映射
本表为ToTable(“示例”);
this.Property(t=>t.ID_A).HasColumnName(“ID_A”);
this.Property(t=>t.ID_B).HasColumnName(“ID_B”);
this.Property(t=>t.ID_C).HasColumnName(“ID_C”);
this.Property(t=>t.Type_A).HasColumnName(“Type_A”);
this.Property(t=>t.Type_B).HasColumnName(“Type_B”);
this.Property(t=>t.ID_Z).HasColumnName(“ID_Z”);
this.Property(t=>t.Foo).HasColumnName(“Foo”);
this.Property(t=>t.Bar).HasColumnName(“Bar”);
}
}
ID\u A
ID\u B
ID\u C
Type\u A
Type\u B
标识“主”实体和
ID\u Z
标识连接的“Z”实体。
Foo
Bar
是需要包含在最终结果中的非唯一数据列

对于主ID/类型值的每个组合,可以有多个
ID_Z
值。我需要按
ID_Z
值进行筛选,然后返回不同的主实体值(基于ID/类型值)

我尝试了如下查询:

//要筛选的'ID_Z'值
var-zIDs=新列表{1,2};
var result=context.Set()
其中(e=>zIDs.Contains(e.ID_Z))
.GroupBy(e=>new{e.ID_A,e.ID_B,e.ID_C,e.Type_A,e.Type_B})
.Select(g=>g.FirstOrDefault())
.ToList();
这将导致以下SQL:

选择
[Limit1]。[ID_A]作为[ID_A],
[Limit1]。[ID_B]作为[ID_B],
[Limit1]。[ID_C]作为[ID_C],
[Limit1]。[Type_A]作为[Type_A],
[Limit1]。[Type_B]作为[Type_B],
[Limit1]。[ID_Z]作为[ID_Z],
[Limit1][Foo]作为[Foo],
[Limit1].[Bar]作为[Bar]
从(
选择[Extent1].[ID_A]作为[ID_A],[Extent1].[ID_B]作为[ID_B],[Extent1].[ID_C]作为[ID_C],[Extent1].[Type_A]作为[Type_A],[Extent1].[Type_B]作为[Type_B]
来自[dbo]。[Example]作为[Extent1]使用(NOLOCK)
哪里
([Extent1].[ID_Z]IN(cast(1作为bigint),cast(2作为bigint)))和([Extent1].[ID_Z]不为NULL)
)AS[Filter1]
外敷(
选择顶部(1)
[extend2]。[ID_A]作为[ID_A],
[extend2]。[ID_B]作为[ID_B],
[extend2]。[ID_C]作为[ID_C],
[Extent2]。[Type_A]作为[Type_A],
[Extent2]。[Type_B]作为[Type_B],
[extend2]。[ID_Z]作为[ID_Z],
[extend2].[Foo]作为[Foo],
[extend2].[Bar]作为[Bar]
来自[dbo]。[Example]作为[Extent2]使用(NOLOCK)
哪里
([Extent2].[ID_Z]IN(cast(1作为bigint),cast(2作为bigint)))和([Extent2].[ID_Z]不为NULL)以及
([Filter1].[ID_A]=[Extent2].[ID_A])和
([Filter1].[ID_B]=[Extent2].[ID_B])和
([Filter1].[ID_C]=[Extent2].[ID_C])和
(([Filter1].[Type_A]=[Extent2].[Type_A])或([Filter1].[Type_A]为空)和([Extent2].[Type_A]为空))以及
(([Filter1].[Type_B]=[Extent2].[Type_B])或([Filter1].[Type_B]为NULL)和([Extent2].[Type_B]为NULL)))
)AS[Limit1]
但这似乎会返回与
Z_ID
过滤器匹配的所有行(导致重复的“main”值),而不是仅返回每组“main”ID/类型值的第一行

如果我直接在
GroupBy
之后实现(
ToList
)查询,我似乎得到了正确的分组;但我希望在数据库中运行这一切,并避免使用LINQ to Objects查询

如何创建此查询?

(因为显然这从未完成,所以我将下面的注释复制为“答案”)


正如我所料,该问题是由实体的PK定义引起的。通过将ID_A标记为PK,本质上就是告诉EF该字段是唯一的,因此它将假定包括该字段在内的任何字段组合都是唯一的,并将删除正常的GroupBy/Distinct运算符。您确实需要将真正的唯一键定义为PK该实体。最终包括所有字段,但这不适用于可为空的字段。最好扩展数据库视图,以包括行号或基于NEWID的计算列,并映射它