C# 导致指定强制转换的位列的LINQ并集无效错误
我在几个表之间有一个复杂的连接,但我已经使用linqpad和下面的小表成功地复制了错误。COLNAME列和YAXIS列之间以及COLNAME和XAXIS之间存在未明确定义的引用 错误是“指定的强制转换无效”,最初我认为问题是转换VS 2010中返回到我的对象的数据,这浪费了时间,但是错误也发生在没有定义对象的linqpad中。一个bit列会导致这个问题,这似乎很疯狂。如果我将列类型更改为VARCHAR,它就可以正常工作。如果我从linqpad或SQL分析器运行生成的SQL,也会返回fine 发生了什么事C# 导致指定强制转换的位列的LINQ并集无效错误,c#,asp.net,linq,sql-server-2008,.net-4.0,C#,Asp.net,Linq,Sql Server 2008,.net 4.0,我在几个表之间有一个复杂的连接,但我已经使用linqpad和下面的小表成功地复制了错误。COLNAME列和YAXIS列之间以及COLNAME和XAXIS之间存在未明确定义的引用 错误是“指定的强制转换无效”,最初我认为问题是转换VS 2010中返回到我的对象的数据,这浪费了时间,但是错误也发生在没有定义对象的linqpad中。一个bit列会导致这个问题,这似乎很疯狂。如果我将列类型更改为VARCHAR,它就可以正常工作。如果我从linqpad或SQL分析器运行生成的SQL,也会返回fine 发生
CREATE TABLE TEST_QUERY
([ID] INT IDENTITY(1,1) PRIMARY KEY,
blah VARCHAR(20))
CREATE TABLE TEST_QUERY_COLS
(QUERYID INT NOT NULL,
COLNAME VARCHAR(20) NOT NULL,
otherblah VARCHAR(20),
PRIMARY KEY(QUERYID,COLNAME))
CREATE TABLE TEST_CHART
(CHARTID INT IDENTITY(1,1) PRIMARY KEY,
QUERYID INT NOT NULL REFERENCES TEST_QUERY([ID]),
XAXIS VARCHAR(20) NOT NULL,
blahblah VARCHAR(20))
CREATE TABLE TEST_CHART_SERIES
(CHARTID INT NOT NULL REFERENCES TEST_CHART(CHARTID),
YAXIS VARCHAR(20) NOT NULL,
blahblahblah BIT NOT NULL,
PRIMARY KEY(CHARTID,YAXIS))
INSERT INTO TEST_QUERY(blah) VALUES('xxx')
INSERT INTO TEST_QUERY_COLS(QUERYID,COLNAME,otherblah) VALUES(1,'col1','xxx')
INSERT INTO TEST_QUERY_COLS(QUERYID,COLNAME,otherblah) VALUES(1,'col2','yyy')
INSERT INTO TEST_CHART(QUERYID,XAXIS,blahblah) VALUES(1,'col1','xxx')
INSERT INTO TEST_CHART_SERIES(CHARTID,YAXIS,blahblahblah) VALUES(1,'col2',1)
这是linq声明:
((from ch in TEST_CHARTs
join a in TEST_CHART_SERIES on ch.CHARTID equals a.CHARTID into a_join
from cs in a_join.DefaultIfEmpty()
join ycols in TEST_QUERY_COLS on new { key1 = cs.YAXIS, key2 = ch.QUERYID } equals new { key1 = ycols.COLNAME, key2 = ycols.QUERYID }
where ch.CHARTID == 1
select new
{
ch.CHARTID,
POSITION = 0,
ycols.QUERYID,
ycols.Otherblah,
cs.Blahblahblah
})
.Union(from ch in TEST_CHARTs
join xcol in TEST_QUERY_COLS on new { key1 = ch.XAXIS, key2 = ch.QUERYID } equals new { key1 = xcol.COLNAME, key2 = xcol.QUERYID }
where ch.CHARTID == 1
select new
{
ch.CHARTID,
POSITION = 0,
xcol.QUERYID,
xcol.Otherblah,
Blahblahblah = false
})).Distinct()
编辑:我向microsoft提交了一个bug生成的sql包含以下行,其中@p4对应于投影中的
Blahblahblah=false
行:
DECLARE @p4 Int = 0
var one =
(from ch in TEST_CHARTs
join a in TEST_CHART_SERIES on ch.CHARTID equals a.CHARTID into a_join
from cs in a_join.DefaultIfEmpty()
join ycols in TEST_QUERY_COLS on new { key1 = cs.YAXIS, key2 = ch.QUERYID } equals new { key1 = ycols.COLNAME, key2 = ycols.QUERYID }
where ch.CHARTID == 1
select new
{
ch.CHARTID,
POSITION = 0,
ycols.QUERYID,
ycols.Otherblah,
Blahblahblah = cs.Blahblahblah
}).ToList();
var two =
(from ch in TEST_CHARTs
join xcol in TEST_QUERY_COLS on new { key1 = ch.XAXIS, key2 = ch.QUERYID } equals new { key1 = xcol.COLNAME, key2 = xcol.QUERYID }
where ch.CHARTID == 1
select new
{
ch.CHARTID,
POSITION = 0,
xcol.QUERYID,
xcol.Otherblah
}).ToList();
var three =
from x in two
select new
{
x.CHARTID,
x.POSITION,
x.QUERYID,
x.Otherblah,
Blahblahblah = false
};
var four = one.Union(three).Distinct();
查询返回的int不能转换为bool。我不知道这是否是一个LINQtoSQL错误(似乎是这样),但有一个解决方法。基本上,您需要从投影的匿名类型中删除Blahblahblah=false
,然后.ToList()
或.ToArray()
结果,最后在linq to objects投影中添加bool字段:
DECLARE @p4 Int = 0
var one =
(from ch in TEST_CHARTs
join a in TEST_CHART_SERIES on ch.CHARTID equals a.CHARTID into a_join
from cs in a_join.DefaultIfEmpty()
join ycols in TEST_QUERY_COLS on new { key1 = cs.YAXIS, key2 = ch.QUERYID } equals new { key1 = ycols.COLNAME, key2 = ycols.QUERYID }
where ch.CHARTID == 1
select new
{
ch.CHARTID,
POSITION = 0,
ycols.QUERYID,
ycols.Otherblah,
Blahblahblah = cs.Blahblahblah
}).ToList();
var two =
(from ch in TEST_CHARTs
join xcol in TEST_QUERY_COLS on new { key1 = ch.XAXIS, key2 = ch.QUERYID } equals new { key1 = xcol.COLNAME, key2 = xcol.QUERYID }
where ch.CHARTID == 1
select new
{
ch.CHARTID,
POSITION = 0,
xcol.QUERYID,
xcol.Otherblah
}).ToList();
var three =
from x in two
select new
{
x.CHARTID,
x.POSITION,
x.QUERYID,
x.Otherblah,
Blahblahblah = false
};
var four = one.Union(three).Distinct();
请注意,这将导致两个sql查询,而不是一个
编辑
另外,Distinct()可以省略,因为union不包含重复项。我真的应该读我复制粘贴的代码 @Filip:我们公司的标准做法是将所有DB列和表名都用大写字母表示。另外,我总是在sql中大写关键字:)我不记得曾经在LINQtoSQL中使用过bit。。。sql server位是否直接映射到.net布尔值?如果没有,则在尝试合并这两个结果时肯定会出现问题。@jlnorsworthy它将其转换为布尔值。适用于其他位列:)