如何在Linq(C#)中连接多个文件,其中一个连接是左连接

时间:2017-04-01 21:39:12

标签: c# sql entity-framework linq

我的下面的Sql工作得很好,但现在我想加入另一个有共同密钥的文件。我想加入的文件可能有一对多记录,任何建议

这是我的代码:

 var regPoints = (from x in db.CertPoints
                                 join y in db.CommunityPts on x.PointId equals y.PointId into z
                                 from t in
                                     (from r in z
                                      where r.CommunityId == id select r).DefaultIfEmpty()
                                 where x.TypeId == 1 
                                 select new Points
                                 {
                                     pointId = x.PointId,
                                     pointsDescription = x.PointDescription,
                                     points = x.Points,
                                     dateApplied = t.DateApplied,
                                     pointsEarned = t.PointsEarned,
                                     pointsPending = t.Pending ? true : false,
                                     pointsApproved = t.Approved ? true : false,
                                     notes = t.Notes

                                 }).AsEnumerable();

新连接将是一对多记录,其中CommunityPts中的密钥是Id,我想要加入的文件是文件链接列表" CommunityPtsDocs"用外键CommnunityPtId。我如何将它添加到上面的上述sql语句中?

2 个答案:

答案 0 :(得分:1)

以下修改将有助于实现任务,虽然我更喜欢Fluent语法,因为在我看来实现相同的更清晰,尽管我没有在Select语句中选择CommunityPtsDocs中的任何列

var regPoints = (from x in CertPoints
                 join y in CommunityPts on x.PointId equals y.PointId
                 join s in CommunityPtsDocs on y.Id equals s.CommnunityPtId into k
                 from t in (from r in k where r.CommunityId == id select r).DefaultIfEmpty()
                 where x.TypeId == 1 
                                 select new Points
                                 {
                                     pointId = x.PointId,
                                     pointsDescription = x.PointDescription,
                                     points = x.Points,
                                     dateApplied = t.DateApplied,
                                     pointsEarned = t.PointsEarned,
                                     pointsPending = t.Pending ? true : false,
                                     pointsApproved = t.Approved ? true : false,
                                     notes = t.Notes

                                 }).AsEnumerable();

答案 1 :(得分:1)

有时我觉得我是导航属性的传道者(幸运的是,我不是唯一一个)。

你接受的答案是好的,它完成了这项工作。但是使用任何ORM(如Entity Framework或LINQ-to-SQL),您应尽可能避免使用join语句。它冗长且容易出错。它会导致重复的代码,并且错误地加入错误的属性太容易了。

您的班级CertPoint可以有0..1-n导航属性CommunityPts(列表),CommunityPt可以有1-n导航属性CommunityPtsDocs(也是一个清单)。如果您正在使用LINQ-to-SQL,那么他们可能已经存在但您还没有意识到它们。如果您首先使用实体​​框架代码,则应自行添加它们。

拥有这些导航属性后,您的代码将如下所示:

from cert in CertPoints
from comm in cert.CommunityPts.DefaultIfEmpty()
from doc in comm.CommunityPtsDocs
where comm.CommunityId == id && cert.TypeId == 1 
select new Points
{
    pointId = cert.PointId,
    pointsDescription = cert.PointDescription,
    points = cert.Points,
    dateApplied = comm.DateApplied,
    pointsEarned = comm.PointsEarned,
    pointsPending = comm.Pending ? true : false,
    pointsApproved = comm.Approved ? true : false,
    notes = comm.Notes,
    something = doc.Something
})

现在,ORM将使用正确的连接将其转换为SQL,并且您的代码看起来更清晰(请注意,我也更喜欢更有意义的范围变量名称)。