当事先不知道有多少列时,在 Linq-to-SQL 查询中加入多列
Join multiple columns in a Linq-to-SQL query when not knowing how many columns there are beforehand
假设我有以下 table 名为 TableSomeWords
:
然后另一个 table 叫 SomePerson
(这是主要的 table)
我要实现的是下面的结果(所以所有的世界组合起来形成一个句子):
唯一的问题是无法预先知道 TableSomeWords
中会有多少个单词。这是我目前拥有的:
var storedProcedure =
from hdr in SomePerson
join cl in TableSomeWords on hdr.No_ equals cl.No_
group new { hdr, cl } by new { hdr.No_ } into tcl
let firstgroupby = tcl.FirstOrDefault()
let hdr = firstgroupby.hdr
let cl = firstgroupby.cl
join wml in lManLine on new { X1 = hdr.Document_Type, X2 = hdr.Business_Type, X3 = hdr.No_ } equals new { X1 = wml.Document_Type, X2 = wml.Business_Type, X3 = wml.Document_No_ }
join v in lVendor on wml.Carrier_No_ equals v.No_
where
wml.Service_Type == 3 &&
wml.Location_Code == locationCode &&
(
(hdr.Document_Type == 1 && hdr.Task_Date < DateTime.Now.AddYears(-100)) ||
(new int[] { 1, 5 }.Contains(hdr.Document_Type) && (hdr.Task_Date.Date >= fromDate.Date && hdr.Task_Date < fromDate.AddDays(7)))
)
select new
{
//ID = ...
//Code = ...
//Name = ...
Words= string.Join(" ", TableSomeWords.Where(x => x.No_ == hdr.No_ && x.Code == "CompanyX").OrderBy(x => x.No_).ThenBy(x => x.Line_No_).GroupBy(t => t.No_).ToList()),
}
PS:我的代码不起作用,但至少它解释了我的目标。我也不能将最后一个 .Where
放在上面的 where 子句中,因为那将 return 我只有 code = CompanyX 的行,但我希望显示所有人。
编辑:
基本上,CompanyX (x.Code
) 是每个单词都有的代码。所以基本上我有很多单词和很多代码,但我只想组合代码为 CompanyX 的单词。另一个像 C001 这样的代码是另一个我可以用 (hdr.No_
)
分组的代码
查看下面的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication132
{
class Program
{
static void Main(string[] args)
{
DataTable tableSomeWords = new DataTable();
tableSomeWords.Columns.Add("id", typeof(int));
tableSomeWords.Columns.Add("code", typeof(string));
tableSomeWords.Columns.Add("lineNr", typeof(int));
tableSomeWords.Columns.Add("words", typeof(string));
tableSomeWords.Rows.Add(new object[] { 1, "C001", 1, "Foo" });
tableSomeWords.Rows.Add(new object[] { 2, "C001", 2, "Bar" });
tableSomeWords.Rows.Add(new object[] { 3, "C002", 1, "Hello" });
tableSomeWords.Rows.Add(new object[] { 4, "C002", 2, "Big Blue" });
tableSomeWords.Rows.Add(new object[] { 5, "C002", 3, "World" });
DataTable somePerson = new DataTable();
somePerson.Columns.Add("id", typeof(int));
somePerson.Columns.Add("code", typeof(string));
somePerson.Columns.Add("name", typeof(string));
somePerson.Rows.Add(new object[] { 1, "C002", "John"});
somePerson.Rows.Add(new object[] { 2, "C001", "Sam" });
var results = (from person in somePerson.AsEnumerable()
join words in tableSomeWords.AsEnumerable() on person.Field<string>("code") equals words.Field<string>("code")
select new { words = words, person = person })
.GroupBy(x => x.person.Field<string>("code"))
.ToList();
DataTable tableCombineWords = new DataTable();
tableCombineWords.Columns.Add("id", typeof(int));
tableCombineWords.Columns.Add("code", typeof(string));
tableCombineWords.Columns.Add("name", typeof(string));
tableCombineWords.Columns.Add("words", typeof(string));
foreach (var result in results)
{
tableCombineWords.Rows.Add(new object[] {
result.FirstOrDefault().person.Field<int>("id"),
result.FirstOrDefault().person.Field<string>("code"),
result.FirstOrDefault().person.Field<string>("name"),
string.Join(" ",result.Select(x => x.words.Field<string>("words")))
});
}
}
}
}
您需要使用的是 LINQ GroupJoin 运算符 - 这会创建一组来自联接的所有匹配记录。使用查询语法,
var ans = from p in SomePerson
join w in TableSomeWords on p.Code equals w.code into wj
select new {
p.Id,
p.Code,
p.Name,
words = String.Join(" ", wj.Select(w => w.words))
};
使用Fluent/lambda语法,
var ans2 = SomePerson.GroupJoin(TableSomeWords, p => p.Code, w => w.code,
(p, wj) => new { p.Id, p.Code, p.Name, words = String.Join(" ", wj.Select(w => w.words)) });
假设我有以下 table 名为 TableSomeWords
:
然后另一个 table 叫 SomePerson
(这是主要的 table)
我要实现的是下面的结果(所以所有的世界组合起来形成一个句子):
唯一的问题是无法预先知道 TableSomeWords
中会有多少个单词。这是我目前拥有的:
var storedProcedure =
from hdr in SomePerson
join cl in TableSomeWords on hdr.No_ equals cl.No_
group new { hdr, cl } by new { hdr.No_ } into tcl
let firstgroupby = tcl.FirstOrDefault()
let hdr = firstgroupby.hdr
let cl = firstgroupby.cl
join wml in lManLine on new { X1 = hdr.Document_Type, X2 = hdr.Business_Type, X3 = hdr.No_ } equals new { X1 = wml.Document_Type, X2 = wml.Business_Type, X3 = wml.Document_No_ }
join v in lVendor on wml.Carrier_No_ equals v.No_
where
wml.Service_Type == 3 &&
wml.Location_Code == locationCode &&
(
(hdr.Document_Type == 1 && hdr.Task_Date < DateTime.Now.AddYears(-100)) ||
(new int[] { 1, 5 }.Contains(hdr.Document_Type) && (hdr.Task_Date.Date >= fromDate.Date && hdr.Task_Date < fromDate.AddDays(7)))
)
select new
{
//ID = ...
//Code = ...
//Name = ...
Words= string.Join(" ", TableSomeWords.Where(x => x.No_ == hdr.No_ && x.Code == "CompanyX").OrderBy(x => x.No_).ThenBy(x => x.Line_No_).GroupBy(t => t.No_).ToList()),
}
PS:我的代码不起作用,但至少它解释了我的目标。我也不能将最后一个 .Where
放在上面的 where 子句中,因为那将 return 我只有 code = CompanyX 的行,但我希望显示所有人。
编辑:
基本上,CompanyX (x.Code
) 是每个单词都有的代码。所以基本上我有很多单词和很多代码,但我只想组合代码为 CompanyX 的单词。另一个像 C001 这样的代码是另一个我可以用 (hdr.No_
)
查看下面的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication132
{
class Program
{
static void Main(string[] args)
{
DataTable tableSomeWords = new DataTable();
tableSomeWords.Columns.Add("id", typeof(int));
tableSomeWords.Columns.Add("code", typeof(string));
tableSomeWords.Columns.Add("lineNr", typeof(int));
tableSomeWords.Columns.Add("words", typeof(string));
tableSomeWords.Rows.Add(new object[] { 1, "C001", 1, "Foo" });
tableSomeWords.Rows.Add(new object[] { 2, "C001", 2, "Bar" });
tableSomeWords.Rows.Add(new object[] { 3, "C002", 1, "Hello" });
tableSomeWords.Rows.Add(new object[] { 4, "C002", 2, "Big Blue" });
tableSomeWords.Rows.Add(new object[] { 5, "C002", 3, "World" });
DataTable somePerson = new DataTable();
somePerson.Columns.Add("id", typeof(int));
somePerson.Columns.Add("code", typeof(string));
somePerson.Columns.Add("name", typeof(string));
somePerson.Rows.Add(new object[] { 1, "C002", "John"});
somePerson.Rows.Add(new object[] { 2, "C001", "Sam" });
var results = (from person in somePerson.AsEnumerable()
join words in tableSomeWords.AsEnumerable() on person.Field<string>("code") equals words.Field<string>("code")
select new { words = words, person = person })
.GroupBy(x => x.person.Field<string>("code"))
.ToList();
DataTable tableCombineWords = new DataTable();
tableCombineWords.Columns.Add("id", typeof(int));
tableCombineWords.Columns.Add("code", typeof(string));
tableCombineWords.Columns.Add("name", typeof(string));
tableCombineWords.Columns.Add("words", typeof(string));
foreach (var result in results)
{
tableCombineWords.Rows.Add(new object[] {
result.FirstOrDefault().person.Field<int>("id"),
result.FirstOrDefault().person.Field<string>("code"),
result.FirstOrDefault().person.Field<string>("name"),
string.Join(" ",result.Select(x => x.words.Field<string>("words")))
});
}
}
}
}
您需要使用的是 LINQ GroupJoin 运算符 - 这会创建一组来自联接的所有匹配记录。使用查询语法,
var ans = from p in SomePerson
join w in TableSomeWords on p.Code equals w.code into wj
select new {
p.Id,
p.Code,
p.Name,
words = String.Join(" ", wj.Select(w => w.words))
};
使用Fluent/lambda语法,
var ans2 = SomePerson.GroupJoin(TableSomeWords, p => p.Code, w => w.code,
(p, wj) => new { p.Id, p.Code, p.Name, words = String.Join(" ", wj.Select(w => w.words)) });