Объединение LINQ со столбцом BIT, приводящее к указанной ошибке. - PullRequest
2 голосов
/ 08 марта 2011

У меня сложное соединение между несколькими таблицами, но мне удалось воспроизвести ошибку с помощью linqpad и небольших таблиц ниже. Между столбцом COLNAME и столбцом YAXIS, а также между COLNAME и XAXIS есть явные ссылки, которые явно не определены.

Ошибка «Указанное преобразование недопустимо», что изначально я потратил впустую время, думая, что проблема заключалась в преобразовании данных, возвращаемых моему объекту в VS 2010, но ошибка также происходит в linqpad без определенного объекта. Кажется безумным, что битовый столбец может вызвать эту проблему. Если я изменю тип столбца на VARCHAR, он будет работать нормально. Если я запускаю сгенерированный SQL из linqpad или sql profiler, это также возвращает нормально.

Что происходит?

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 здесь

1 Ответ

3 голосов
/ 08 марта 2011

Сгенерированный sql содержит следующую строку, где @ p4 соответствует строке Blahblahblah=false в вашей проекции:

DECLARE @p4 Int = 0

И int, который возвращается из запроса, не может быть преобразован в bool. Я не знаю, является ли это ошибкой linq to sql (похоже), но есть обходной путь. Обычно вам нужно удалить Blahblahblah=false из проецируемого анонимного типа, затем .ToList() или .ToArray() результат и, наконец, добавить поле bool в linq для проекции объектов:

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, а не к одному.

EDIT

Кроме того, Distinct () может быть опущен, так как объединение не включает дубликаты. Я должен был на самом деле прочитать код, который я скопировал и вставил!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...