VB.NET LINQ到数据集(SQL';左外联接';可选)
我想连接两个数据表,并根据结果创建第三个数据表。结果数据表应具有三列:VB.NET LINQ到数据集(SQL';左外联接';可选),vb.net,linq,dataset,Vb.net,Linq,Dataset,我想连接两个数据表,并根据结果创建第三个数据表。结果数据表应具有三列: 身份证 名字 出生年份 我的编译选项: 选项显式:On 选项严格:On 选项比较:二进制 选项推断:关闭 Dim dr As DataRow REM Dt1 Dim Dt1 As New DataTable Dt1.Columns.Add("ID", GetType(Integer)) Dt1.Columns.Add("Name", GetType(String)) dr = Dt1.NewRow dr("ID")
- 身份证
- 名字
- 出生年份
- 选项显式:On
- 选项严格:On
- 选项比较:二进制
- 选项推断:关闭
Dim dr As DataRow REM Dt1 Dim Dt1 As New DataTable Dt1.Columns.Add("ID", GetType(Integer)) Dt1.Columns.Add("Name", GetType(String)) dr = Dt1.NewRow dr("ID") = 1 dr("Name") = "Peter" Dt1.Rows.Add(dr) dr = Dt1.NewRow dr("ID") = 2 dr("Name") = "Anna" Dt1.Rows.Add(dr) dr = Dt1.NewRow dr("ID") = 3 dr("Name") = "John" Dt1.Rows.Add(dr) REM End Dt1 REM Dt2 Dim Dt2 As New DataTable Dt2.Columns.Add("ID", GetType(Integer)) Dt2.Columns.Add("YearOfBirth", GetType(Integer)) dr = Dt2.NewRow dr("ID") = 1 dr("YearOfBirth") = 1970 Dt2.Rows.Add(dr) dr = Dt2.NewRow dr("ID") = 2 dr("YearOfBirth") = 1980 Dt2.Rows.Add(dr) REM End Dt2 Dim Dt3 As New DataTable Dim query As IEnumerable(Of DataRow) = From dr1 In Dt1.AsEnumerable() Group Join dr2 In Dt2.AsEnumerable() On dr1.Field(Of Integer)("ID") Equals dr2.Field(Of Integer)("ID") Into joined = Group From j In joined.DefaultIfEmpty() Select New With { .ID = dr1.Field(Of Integer)("ID"), .Name = dr1.Field(Of String)("Name"), .YearOfBirth = j.Field(Of Integer)("YearOfBirth") } Dt3 = query.CopyToDataTable
“IEnumerable(匿名类型:ID为整数,Name为字符串,YearOfBirth为整数)”无法转换为“IEnumerable(Of DataRow)”,因为“匿名类型:ID为整数,Name为字符串,YearOfBirth为整数”不是从“DataRow”派生的,这是“接口IEnumerable(Of Out T)”中的“Out”泛型参数“T”所必需的。”
选择New
而不指定类名,因为查询结果将返回匿名类型(如IEnumerable(属于匿名类型)
),并引发异常,因为IEnumerable(属于匿名类型)
无法直接转换为IEnumerable(属于数据行)
因此,您需要使用额外的Select
方法将匿名类型转换为DataRow
,该方法迭代IEnumerable(匿名类型)
内容并返回DataRow
(使用准备好的DataTable
,其中包括列名作为结果集):
参考:
(C#version)除非您的列表中包含您没有的
数据行,否则您不能调用CopyToDataTable
。您需要自己创建DataTable
,然后循环查询结果,为每个项目添加DataRow
。谢谢,但我在查询中有一些错误。如果有人能为我编写正确的代码部分(Dim query…),这将对我非常有帮助。您的代码是可以的,但只是在条件下,数据表Dt1和Dt2都有ID为1、2和3的3行。如果数据表Dt2只有两行ID为1和2(没有ID 3),我会得到错误:“System.ArgumentNullException:'值不能为null。参数名称:row'”。我刚刚发现出生年份
仅包含2行(对于ID 3,它设置为无任何内容)。与2个参数一起使用,检查Nothing
,如果DataRow
中有Nothing
值,则返回默认整数值。如果使用row(“出生年份”)=如果(r.YearOfBirth,0)
,则查询不正确。我在错误列表中看到此错误:错误BC33107:二进制“If”表达式中的第一个操作数必须是可空的或引用类型。如果我在代码.YearOfBirth=j.Field(of Integer)(“YearOfBirth”)
对象的部分中使用,而不是Integer
,则查询在形式上是可以的,但在启动后会出现错误:“System.ArgumentNullException:'值不能为null。参数名称:行”。如果我使用Try…Catch
,我会看到错误出现在Select New With
行上。好吧,我在错误的位置对Nothing
进行了检查。如您所说,它应该放在选择New With
中,并由确认。很抱歉有任何误解。现在查询非常好。你帮了我很多。非常感谢。
' joined DataTable columns
Dim JoinedDT As New DataTable
JoinedDT.Columns.Add("ID", GetType(Integer))
JoinedDT.Columns.Add("Name", GetType(String))
JoinedDT.Columns.Add("YearOfBirth", GetType(Integer))
' other stuff
Dim query As IEnumerable(Of DataRow) = (From dr1 In Dt1.AsEnumerable() _
Group Join dr2 In Dt2.AsEnumerable() _
On dr1.Field(Of Integer)("ID") Equals dr2.Field(Of Integer)("ID") _
Into joined = Group _
From j In joined.DefaultIfEmpty() _
Select New With
{
.ID = dr1.Field(Of Integer)("ID"),
.Name = dr1.Field(Of String)("Name"),
.YearOfBirth = If(j IsNot Nothing, j.Field(Of Integer)("YearOfBirth"), 0)
}).Select(Function(r)
' use `DataTable.NewRow` here
Dim row As DataRow = JoinedDT.NewRow()
row("ID") = r.ID
row("Name") = r.Name
row("YearOfBirth") = r.YearOfBirth
Return row
End Function)
Dt3 = query.CopyToDataTable()