linq / lambda查询中的双内连接?

时间:2017-05-11 11:51:03

标签: c# mysql sql-server linq lambda

我得到了这个我想要转换为Linq的SQL查询。 这就是背景:

我正在制作一个需要从3个不同的表中返回值的asp.net api

CREATE TABLE Locatie (
   locatieId            INT IDENTITY(1,1)    not null,
   postcode             VARCHAR(10)          not null,
   huisnummer           INT                  not null,
   adres                VARCHAR(50)          not null,
   plaats               VARCHAR(50)          not null,




CREATE TABLE Vereniging (
   verenigingId         INT IDENTITY(1,1)    not null,
   locatieId            INT                  not null,
   naam                 VARCHAR(50)          not null,
   facebookGroupId      BIGINT               null,


CREATE TABLE Saldo (
   saldoId              INT IDENTITY(1,1)    not null,
   lidId                INT                  not null,
   verenigingId         INT                  not null,
   bedrag               SMALLMONEY           not null,

我遗漏了所有的外国钥匙和小学生。这只是为了澄清我想要的东西。我的问题是,我有一个需要从几个表返回信息的函数。 sql查询看起来像这个=

Select v.verenigingId, l.postcode, l.huisnummer, l.adres,l.plaats,v.naam,v.facebookGroupId 
from Vereniging v inner join Saldo s
on v.verenigingId = s.verenigingId
inner join Locatie l
on v.locatieId=l.locatieId
where s.lidId = 1;

我从lidid = 1获得所有“verenigingen”,并在表格位置显示“verenigingen”的所有信息。

但是当我尝试使用linq / lambda这样做时,它会出错; 我的功能看起来像这样:

public class LibraryRepository : ILibraryRepository
{
    private LibraryContext _context;

    public LibraryRepository(LibraryContext context)
    {
        _context = context;
    }

    public bool Save()
    {
        return (_context.SaveChanges() >= 0);
    }

    public IEnumerable<Verenigingmodel> GetVerenigingenperLid(int lidId)
    {
        return _context.Vereniging
            .Join(
                _context.Saldo.Where(b => b.lidId == lidId),
            ver => ver.verenigingId,
                sal => sal.verenigingId,
                (ver, sal) => new Viewmodel { Vereniging = ver, Saldo = sal })
            .Join(
                _context.Locatie,
                verr => verr.Vereniging.locatieId,
                loca => loca.locatieId,
                (vr, loca) => new Viewmodel { Locatie = loca });
                //this returns wrong sql information
    }

}

我的vereniging模型看起来像这样:

public class Verenigingmodel
{
    public int verenigingId { get; set; }
    public string postcode { get; set; }
    public int huisnummer { get; set; }
    public string adres { get; set; }
    public string plaats { get; set; }
    public string naam { get; set; }
    public int facebookGroupId { get; set; }
}

我的库上下文如下所示:

public class LibraryContext : DbContext
{
    public LibraryContext(DbContextOptions<LibraryContext> options)
       : base(options)
    {
        Database.Migrate();
    }

    public DbSet<Gebruiker> Gebruiker { get; set; }
    public DbSet<Lid> Lid { get; set; }
    public DbSet<Vereniging> Vereniging { get; set; }
    public DbSet<Saldo> Saldo { get; set; }
    public DbSet<Locatie> Locatie { get; set; }
}

我想要实现的是,我将所有不同的信息放在vereniging模型中,并从那里把它作为我的休息api的输出:

    [HttpGet("api/Vereniging/{lidId}")]

    public IActionResult FindVereniGingenPerLid(int lidId)
    {
        var verenigingFromRepo = vlibraryRepository.GetVerenigingenperLid(lidId);

        return new JsonResult(verenigingFromRepo);

    }

2 个答案:

答案 0 :(得分:3)

我会做的功能有点不同。像这样:

public IEnumerable<Verenigingmodel> GetVerenigingenperLid(int lidId)
{
    return (
        from v in _context.Vereniging
        join s in _context.Saldo
            on v.verenigingId equals s.verenigingId
        join l in _context.Locatie
            on v.locatieId equals l.locatieId
        select new Verenigingmodel()
        {
            verenigingId= v.verenigingId,
            postcode=l.postcode,
            huisnummer=l.huisnummer,
            adres=l.adres,
            naam=v.naam,
            facebookGroupId=v.facebookGroupId,
            plaats=l.plaats
        }
     ).ToList();
}

我个人觉得更容易看到这样的连接并将结果合并到一个对象

答案 1 :(得分:1)

要实现与sql查询相同的行为,您应该按如下方式修改代码:

return _context.Vereniging
    .Join(
        _context.Saldo.Where(b => b.lidId == lidId),
        v => v.verenigingId,
        s => s.verenigingId,
        (v, s) => new { Vereniging = v, Saldo = s })
    .Join(
        _context.Locatie,
        v => v.Vereniging.locatieId,
        l => l.locatieId,
        (v, l) => 
        new Verenigingmodel 
        {
            verenigingId = v.Vereniging.id,
            postcode = l.postcode,
            huisnummer = l.huisnummer,
            adres = l.adres,
            plaats = l.plaats,
            naam = v.Vereniging.naam,
            facebookGroupId = v.Vereniging.facebookGroupId
        });

或使用内联linq方法,如Arion建议的那样。他的版本更具可读性,我的版本适合那些真正喜欢lambdas,匿名类型等的人。