LinqToEntities在LEFT OUTER JOIN中使用小于(<)

时间:2012-10-08 13:56:54

标签: c# sql linq-to-entities left-join

我正在与同事合作,我们正尝试使用LinqToEntities(Entity Framework v4.0)重现以下SQL查询

SELECT t1.*
FROM [dbo].LocaleStringResource AS t1
  LEFT OUTER JOIN [dbo].LocaleStringResource AS t2
    ON (t1.ResourceName = t2.ResourceName AND t1.AccountId < t2.AccountId)
WHERE t2.ResourceName IS NULL;

基本上它只是说我们返回最高的AccountIds,其中有多个匹配的ResourceName。到目前为止我们已经得到了这个......

localeStringResource = from e1 in localeStringResource
  join e2 in localeStringResource
  on new { e1.ResourceName, e1.AccountId } equals new { e2.ResourceName, e2.AccountId }
  where e2.ResourceName == null
  select e1;

但我们似乎无法弄清楚如何在LEFT OUTER JOIN中实现等于小于(&lt;)的等价物?

ON (t1.ResourceName = t2.ResourceName AND t1.AccountId < t2.AccountId)

有人可以告诉我这是否可能,或者我们是否正在咆哮错误的树?我们试图使初始查询尽可能简单,希望它能使等效的LinqToEntities查询更容易构建。

注意:

AccountId不是唯一的。我们在Identity表上有一个Id LocalResourceString列。但是,AccountIdResourceName

都有唯一约束

2 个答案:

答案 0 :(得分:4)

&LT;编辑&gt; 看起来您真正想要做的是选择每个AccountId具有最大ResourceName的记录。如果我们假设AccountId是唯一的,那么:

localeStringResource =
    from e1 in localeStringResource
    group e1 by e1.ResourceName into grp
    select grp.Max(e => e.AccountID);

&LT; /编辑&gt;

这里有一个左外连接,所以你的LINQ需要一个GroupJoin - SelectMany - DefaultIfEmpty结构。 JoinGroupJoin被重置为相等,但您可以稍后在DefaultIfEmpty之前添加条件的其余部分:

localeStringResource =
    from e1 in localeStringResource
    join e2inner in localeStringResource
        on e1.ResourceName equals e2inner.ResourceName
        into grp
    from e2 in grp
        .Where(e => e1.AccountId < e.AccountId)
        .DefaultIfEmpty()
    where e2.ResourceName == null
    select e1;

这是方法语法,供参考。我使用Tuple来传递数据:

localeStringResource = localeStringResource
    .GroupJoin(
        localeStringResource,
        e1 => e1.ResourceName,
        e2 => e2.ResourceName,
        Tuple.Create)
    .SelectMany(pair => pair.Item2
        .Where(e2 => pair.Item1.AccountID < e2.AccountID)
        .DefaultIfEmpty()
        .Select( e2 => Tuple.Create(pair.Item1, e2)))
    .Where(pair => pair.Item2.ResourceName == null)
    .Select(pair => pair.Item1);

答案 1 :(得分:-1)

尝试使用ANSI-82语法将连接条件放在where子句中:

localeStringResource = from e1 in localeStringResource
                       from e2 in localeStringResource
                       where e1.ResourceName = e2.ResourceName &&
                            e1.AccountId < e2.AccountId
                       select e1;