【问题标题】:How to do sql joins in lambda?如何在 lambda 中进行 sql 连接?
【发布时间】:2016-04-27 06:54:18
【问题描述】:

我有时会偶然发现这个问题,即我使用了 lambda 连接的子集。鉴于我可以使用任何 LINQ 扩展,我应该如何实现以下连接:

为简单起见,表被定义为

CREATE TABLE [dbo].[TableA] (
    [Key]             INT            IDENTITY (1, 1) NOT NULL,
    [Value]           NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED ([Key] ASC)
);

CREATE TABLE [dbo].[TableB] (
    [Key]             INT            IDENTITY (1, 1) NOT NULL,
    [Value]           NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_TableB] PRIMARY KEY CLUSTERED ([Key] ASC)
);

或者如果您更喜欢代码优先

public class TableContext : DbContext
{
    public DbSet<B> TableB { get; set; }
    public DbSet<A> TableA { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(ConnectionString);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TableB>().Property(o => o.Key).UseSqlServerIdentityColumn();
        modelBuilder.Entity<TableA>().Property(o => o.Key).UseSqlServerIdentityColumn();
    }
}

public class B : IKeyValue
{
    public int Key { get; set; }
    public string Value { get; set; }
}

public class A : IKeyValue
{
    public int Key { get; set; }
    public string Value { get; set; }
}

public interface IKeyValue
{
    int Key { get; set; }
    string Value { get; set; }
}

尽我所能

((A intersect not B) union (A intersect B))

var leftOuterJoin = TableA
  .GroupJoin(
    TableB, 
    a => a.Key,
    b => b.Key,
    (x, y) => new { TableA = x, TableA = y })
  .SelectMany(
    x => x.TableB.DefaultIfEmpty(),
    (x, y) => new { TableA = x.TableA, TableB = y});

(A intersects B)

var innerJoin = TableA
  .Join(
    TableB, 
    a => a.Key,
    b => b.Key,
    (x, y) => x)

(A union B)

var fullOuterJoin = TableA
  .FullOuterJoin(
    TableB, 
    a => a.Key, 
    b => b.Key, 
    (x, y, Key) => new {x, y})

【问题讨论】:

  • 好吧,你尝试过任何东西了吗?做过研究吗?提示:LINQ Join 操作是内连接。
  • @JonSkeet 我曾考虑添加我的示例,但我认为它会平衡给出答案的方式。
  • 现在这个问题看起来很像“为我做作业”。我敢说这不是作业,但这不是一个好的堆栈溢出问题。
  • 您以正确的顺序使用 Join、Left Join、except 和 union 的组合。或者,如果您正在使用 IEnumerables,则可以对其中的大多数使用 github.com/morelinq/MoreLINQ

标签: c# sql linq lambda


【解决方案1】:

对你来说最重要的是知道如何执行INNER JOINOUTER JOIN

对于 INNER JOIN,您可以使用来自 LINQ 的 JOIN,如下所示:

var result = 
    TableA
    .Join(TableB, left => left.Id, right => right.ForeignKeyToTableA, 
       (left, right) => new { TableAColumns = left, TableBColumns = right });

您已经在示例中展示了 OUTER JOIN

现在你需要混合你所知道的,以获得想要的结果。

例如,要执行 FULL OUTER JOIN,请在 LINQ 中执行类似以下伪代码的操作:

SELECT TableA.*, TableB.* FROM TableA LEFT OUTER JOIN TableB
UNION
SELECT TableA.*, TableB.* FROM TableB LEFT OUTER JOIN TableA

这将在 LINQ 中如下所示:

var fullOuterJoin =
            (
                TableA
                .GroupJoin(TableB, 
                    left => left.Id, right => right.ForeignKeyId, 
                    (left, right) => new { TableA = left, TableB = right })
                .SelectMany(p => p.TableB.DefaultIfEmpty(), (x, y) => 
                    new { TableA = x.TableA, TableB = y })
            )
            .Union
            (
                TableB
                .GroupJoin(TableA, 
                    left => left.Id, right => right.ForeignKeyId, 
                    (left, right) => new { TableA = right, TableB = left })
                .SelectMany(p => p.TableA.DefaultIfEmpty(), (x, y) => 
                    new { TableA = y, TableB = x.TableB })
            );

您的图像的最后一个示例将是:

var fullOuterJoinOnlyWithNulls =
            fullOuterJoin
            .Where(p => p.TableA == null || p.TableB == null);

RIGHT OUTER JOIN 只不过是 LEFT OUTER JOIN,您可以在其中像这样交换结果列:

var rightOuterJoin =
            (
                TableB
                .GroupJoin(TableA,
                    left => left.Id, right => right.ForeignKeyId,
                    (left, right) => new { TableA = right, TableB = left })
                .SelectMany(p => p.TableA.DefaultIfEmpty(), (x, y) =>
                    new { TableA = y, TableB = x.TableB })
            );

这样,您可以构建所有示例场景。只需在需要时检查表中的 null

【讨论】:

    猜你喜欢
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    • 2020-02-17
    • 2017-11-16
    • 2020-08-23
    • 2010-10-31
    • 1970-01-01
    相关资源
    最近更新 更多