LINQ外用类似的声明

时间:2018-12-28 15:30:31

标签: linq

我有一个这样的主表工作区:

Description    Date         Timespend
TH work x      2018-12-28   3 hrs
NL work y      2018-12-28   2 hrs
UK work z      2018-12-30   5 hrs

和一张带客户的桌子

CustomerNo     SearchTerms
C0001          Germany DEU DE
C0002          Netherlands NLD NL
C0003          United Kingdom UK

现在,我想为我的报告编写一个linq查询,该查询将显示带有customerNo的主表(如果可以找到的话)。 在SQL中,我会写类似

SELECT workspend.*,CustomerNo FROM workspend w
OUTER APPLY (SELECT top 1 * from customers c
WHERE c.SearchTerms LIKE '% ' + SUBSTRING(w.Description,1,2)) x
WHERE w.Date BETWEEN '2018-12-28' AND '2018-12-29'

结果将是

Description    Date         Timespend    CustomerNo     SearchTerms
TH work x      2018-12-28   3 hrs        NULL           NULL
NL work y      2018-12-28   2 hrs        C0002          Netherlands NLD NL 

在linq中可能吗? 预先感谢

2 个答案:

答案 0 :(得分:0)

希望我已正确理解您的问题。您可以将GroupJoin与“自定义比较器”结合使用以实现结果。

例如,对于数据

var listMain = new List<MainTable>{
    new MainTable{Description = "TH work x", Date = new DateTime(2018,12,28), TimeSpend = "3 hrs"},
    new MainTable{Description = "NL work x", Date = new DateTime(2018,12,29), TimeSpend = "2 hrs"},
    new MainTable{Description = "UK work x", Date = new DateTime(2018,12,30), TimeSpend = "5 hrs"},
    };


var listCustomers = new List<Customers>
    {
    new Customers{CustomerNo="C0001", SearchTerms = "Germany DEU DE"},
    new Customers{CustomerNo="C0002", SearchTerms = "Netherlands NLD NL"},
    new Customers{CustomerNo="C0003", SearchTerms = "United Kingdom UK"},
    };

MainTable和Customer定义为

public class MainTable
{
    public string Description{get;set;}
    public DateTime Date{get;set;}
    public string TimeSpend {get;set;}
}


public class Customers
{
    public string CustomerNo{get;set;}
    public string SearchTerms{get;set;}
}

您可以使用Linq作为查询

var result = listMain.Where(x=>x.Date >= new DateTime(2018,12,28) && x.Date<new DateTime(2018,12,30)).GroupJoin(listCustomers,
                    x=>x.Description,
                    y=>y.SearchTerms,
                    (x,y)=> new {Main= x, Customers = y},
                    new ContainsEqualityComparer())
                    .Select(g=> new 
                    {
                       Description = g.Main.Description, 
                       Date=g.Main.Date,
                       TimeSpend=g.Main.TimeSpend,
                       CustomerNo=g.Customers.Any() ? g.Customers.First().CustomerNo: null,
                       SearchTerms=g.Customers.Any() ? g.Customers.First().SearchTerms:null
                    });

CustomEqualityComparer定义为

class ContainsEqualityComparer: IEqualityComparer<string>
{
    public bool Equals(string right, string left) 
    { 
    return right.Contains(left.Substring(0,2)); 
    }
    public int GetHashCode(string obj) { return 0; }
}

输出如下所示

enter image description here

答案 1 :(得分:0)

这是我的翻译。 LINQ to SQL会将其转换为OUTER APPLY

var ans = from w in workspend
          where DateTime.Parse("2018-12-28") <= w.Date && w.Date <= DateTime.Parse("2018-12-29")
          from c in (from cs in customers where cs.SearchTerms.LastIndexOf(w.Description.Substring(0, 2)) == cs.SearchTerms.Length-2 select cs).Take(1).DefaultIfEmpty()
          select new {
              w,
              c.CustomerNo
          };

不幸的是,如果您使用服务器值(很容易输入),LINQ to SQL / Entities无法转换ContainsEndsWith,因此必须使用{{1} }进行伪造。

您还可以使用子查询,该子查询将转换为LastIndexOf中的SQL子查询:

SELECT