LINQ根据LEFT JOIN过滤行

时间:2015-01-27 10:35:57

标签: c# linq

我希望LINQ查询有两个行为,取决于参数。

如果param = -1,则返回所有行

如果param> -1,返回选择行

这是我尝试过的。它模拟我如何在SQL服务器中编写它(如果param> -1,则使用where子句将其强制转换为内连接的左连接),但它的行为不同。它总是返回已过滤的行,就像RTA连接是内连接一样。

                // Get attributes filtered to the template (-1 = all)
            var result2 = from RA in ent.ReportAttributes 
                          join FT in ent.FilterTypes on RA.FilterTypeID equals FT.FilterTypeID
                          join DS in ent.DataSources on RA.DataSourceID equals DS.DataSourceID
                          join RTA in ent.ReportTemplateAttributes.DefaultIfEmpty() on RA.AttributeID equals RTA.AttributeID
                          where templateID == -1 || (templateID != -1 && RTA.TemplateID == templateID)
                          select new HRFWeb.Models.ReportAttributeModel()
                         {
                             AttributeGroupID = RA.AttributeGroupID,
                             AttributeID = RA.AttributeID,
                             ParentID = RA.ParentID,
                             Name = RA.Name,
                             Alias = RA.Alias,
                             IsCalculated = RA.IsCalculated,
                             FilterTypeID = RA.FilterTypeID,
                             FilterType = FT.Name,
                             DataSourceID = RA.DataSourceID,
                             DBName = DS.DBName,
                             ServerName = DS.ServerName,
                             ServerIP = DS.ServerIP,
                             DataSourceTable = RA.DataSourceTable,
                             LogiDataType = RA.LogiDataType
                         };

为了进一步演示,这里是等效的SQL:


DECLARE @TemplateID INT = -1
-- Returns 53 rows (correct)
SELECT * FROM dbo.ReportAttribute RA
JOIN dbo.FilterType FT ON FT.FilterTypeID = RA.FilterTypeID
JOIN dbo.DataSource DS ON DS.DataSourceID = RA.DataSourceID
LEFT JOIN dbo.ReportTemplateAttribute RTA ON RTA.AttributeID = RA.AttributeID
WHERE @TemplateID = -1 OR (@TemplateID > -1 AND RTA.TemplateID = @TemplateID)


SET @TemplateID = 0
-- Returns 32 rows (correct)
SELECT * FROM dbo.ReportAttribute RA
JOIN dbo.FilterType FT ON FT.FilterTypeID = RA.FilterTypeID
JOIN dbo.DataSource DS ON DS.DataSourceID = RA.DataSourceID
LEFT JOIN dbo.ReportTemplateAttribute RTA ON RTA.AttributeID = RA.AttributeID
WHERE @TemplateID = -1 OR (@TemplateID > -1 AND RTA.TemplateID = @TemplateID)

2 个答案:

答案 0 :(得分:0)

试试这个。想法是在加入后过滤ReportTemplateAttributes。要进行左连接,需要into groupselect xxx from group.DefaultIfEmpty()的组合。

var result2 = from RA in ent.ReportAttributes 
                          join FT in ent.FilterTypes on RA.FilterTypeID equals FT.FilterTypeID
                          join DS in ent.DataSources on RA.DataSourceID equals DS.DataSourceID
                          join RTA in ent.ReportTemplateAttributes on RA.AttributeID equals RTA.AttributeID into g1
                          from g in g1 
                          select new HRFWeb.Models.ReportAttributeModel()
                          {
                             AttributeGroupID = RA.AttributeGroupID,
                             AttributeID = RA.AttributeID,
                             ParentID = RA.ParentID,
                             Name = RA.Name,
                             Alias = RA.Alias,
                             IsCalculated = RA.IsCalculated,
                             FilterTypeID = RA.FilterTypeID,
                             FilterType = FT.Name,
                             DataSourceID = RA.DataSourceID,
                             DBName = DS.DBName,
                             ServerName = DS.ServerName,
                             ServerIP = DS.ServerIP,
                             DataSourceTable = RA.DataSourceTable,
                             LogiDataType = RA.LogiDataType,
                             TemplateID = g.TemplateID
                           };

   if (FilterTemplateId != -1) {
     result2 = from r in result2
               where r.TemplateID == FilterTemplateID
               select r;
     }

答案 1 :(得分:0)

var result2 = from RA in ent.ReportAttributes 
                      join FT in ent.FilterTypes on RA.FilterTypeID equals FT.FilterTypeID
                      join DS in ent.DataSources on RA.DataSourceID equals DS.DataSourceID               
                      where templateID == -1 || (RA.TemplateAttributes != null && RA.TemplateAttributes.Any(rt=> rt.TemplateID == templateID))
                      select new HRFWeb.Models.ReportAttributeModel()
                     {
                         AttributeGroupID = RA.AttributeGroupID,
                         AttributeID = RA.AttributeID,
                         ParentID = RA.ParentID,
                         Name = RA.Name,
                         Alias = RA.Alias,
                         IsCalculated = RA.IsCalculated,
                         FilterTypeID = RA.FilterTypeID,
                         FilterType = FT.Name,
                         DataSourceID = RA.DataSourceID,
                         DBName = DS.DBName,
                         ServerName = DS.ServerName,
                         ServerIP = DS.ServerIP,
                         DataSourceTable = RA.DataSourceTable,
                         LogiDataType = RA.LogiDataType
                     };

通过使用导航属性...第二次检查templateID!= -1似乎是多余的