如何合并两个Linq查询的输出结果?

3
我正在尝试合并这两个对象,但不确定该如何操作。你能帮我合并这两个结果对象吗?
 //
 // Create Linq Query for all segments in "CognosSecurity"
 //
 var userListAuthoritative = (from c in ctx.CognosSecurities
                             where (c.SecurityType == 1 || c.SecurityType == 2)
                             select new {c.SecurityType, c.LoginName , c.SecurityName}).Distinct();
 //
 // Create Linq Query for all segments in "CognosSecurity"
 //
 var userListAuthoritative3 = (from c in ctx.CognosSecurities
                              where c.SecurityType == 3 || c.SecurityType == 0
                              select new {c.SecurityType , c.LoginName }).Distinct();

我想我知道该如何处理这个问题...但为了回答这个问题,对象的类型分别是intstringstring,分别对应于SecurityTypeLoginNameSecurityName
如果您想知道为什么我将它们分成这样,那是因为我想在执行去重操作时忽略其中一列。以下是我要转换为SQL的SQL查询语句。
  select distinct SecurityType, LoginName, 'Segment'+'-'+SecurityName
FROM [NFPDW].[dbo].[CognosSecurity]
where SecurityType =1

  select distinct SecurityType, LoginName, 'Business Line'+'-'+SecurityName
FROM [NFPDW].[dbo].[CognosSecurity]
where SecurityType =2

   select distinct SecurityType, LoginName, SecurityName
FROM [NFPDW].[dbo].[CognosSecurity]
where SecurityType in (1,2)

你不能直接这样做,因为它们是不同的类型,第二组结果的“SecurityName”会是什么? - Nick Craver
我的更新答案是否正确? - StriplingWarrior
5个回答

5
由于类型不同(第一个具有结果类型中的3个属性,第二个具有2个),因此您无法加入这些内容。
如果您可以容忍将第二个查询的第三个结果放置为null值,则会有所帮助。然后建议您只需执行userListAuthoritative.concat(userListAuthoritative3 ),但我认为这不起作用,因为linq生成的匿名类型将不是相同的类,即使结构相同。要解决此问题,可以定义CustomType来封装元组,并在两个查询中使用select new CustomType{ ... }或以类似方式使用select()对结果进行后处理。
实际上,后面的select()方法也允许您通过实现带有null参数的选择器来解决参数计数不匹配的问题,以进行自定义类型的后处理。
编辑:根据下面的评论,一旦结构相同,匿名类型将是相同的。

1
如果结构相同,并且它们在同一个程序集中,则匿名类型将是相同的,concat 将起作用。 - StriplingWarrior
@StriplingWarrior - 这里不是真的,匿名类型不同...它们具有不同数量的属性... - Nick Craver
我不知道,修改以反映。 - Mike Q
@Nick - 这就是我说“如果结构相同”的原因。Mike最初的回答表明,即使他确保匿名类型具有相同的类型和字段名称,他也认为它们不起作用。 - StriplingWarrior
1
@Nick,我认为SW的意思是,如果按照我在第一段建议的那样修改结构,那么连接就会很好地工作。 - Mike Q
显示剩余2条评论

1

我假设您希望保持结果不同:

var merged = userListAuthoritative.Concat(userListAuthoritative3).Distinct();

而且正如Mike Q所指出的那样,您需要确保您的类型匹配,可以通过给匿名类型相同的签名来实现,或者创建一个自己的POCO类专门用于此目的。
编辑
如果我理解您的编辑正确,您希望您的Distinct忽略SecurityName列。是这样吗?
var userListAuthoritative = from c in ctx.CognosSecurities
                            where new[]{0,1,2,3}.Contains(c.SecurityType)
                            group new {c.SecurityType, c.LoginName, c.SecurityName}
                                by new {c.SecurityType, c.LoginName}
                            select g.FirstOrDefault();

我想要在SecurityType == 0或3时忽略securityName列(用于去重),因此这可能不是答案... - makerofthings7

0

编辑:这里假设它们是相同的类型——但事实并非如此。

userListAuthoritative.Concat(userListAuthoritative3);

你只能连接相同类型的集合,请查看返回的内容 :) - Nick Craver
@Nick,啊,你说得对,一开始我也觉得它们看起来一样,但是很好地发现了。 - Kirk Woll

0

我不太确定你所说的“合并”是什么意思,因为每个都返回不同(匿名)类型。以下方式为何不能满足您的要求?

var userListAuthoritative = (from c in ctx.CognosSecurities
                         where (c.SecurityType == 1 || c.SecurityType == 2 || c.SecurityType == 3 || c.SecurityType == 0)
                         select new {c.SecurityType, c.LoginName , c.SecurityName}).Distinct();

我无法这样做,因为每次运行需要在不同的一组对象上进行不同的工作。 - makerofthings7

0

试试下面的代码,你可能需要在你的 ctx 类型中实现 IEqualityComparer<T> 接口。

var merged = userListAuthoritative.Union(userListAuthoritative3);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接