2013-06-04 2 views
0

У меня есть запрос LINQ, который вызывает исключение InvalidOperationException во время выполнения при вызове ToList(), и я пытаюсь найти способ обойти его, если это возможно, без необходимости разбивать соединение в отдельные пункты.InvalidOperationException при присоединении к составному ключу

Указанные линии представляют собой 3 и 4 в приведенном ниже примере. loan_id не является нулевым типом десятичного числа, ti_disb_id не является нулевым типом. Когда я разделяю их на отдельные утверждения, нет исключения при вызове ToList(). Тем не менее, это, кажется, имеет больше смысла, поэтому, если есть решение, я бы хотел его услышать. :)

 var baseQuery = (from a in context.ti_disbursements 
         join b in context.disbursement_schedule 
          on new {a.loan_id, a.ti_disb_id} equals 
           new {b.loan_id, b.ti_disb_id} into ab 
          from b in ab.DefaultIfEmpty() 
         join c in context.business_associates 
          on a.ba_id equals c.ba_id into ac 
          from c in ac.DefaultIfEmpty() 
         join d in context.investor_loan 
          on b.loan_id equals d.loan_id into ad 
          from d in ad.DefaultIfEmpty() 
         join e in context.loan_information 
          on d.loan_id equals e.loan_id into ae 
          from e in ae.DefaultIfEmpty() 
         join f in context.loan_balances 
          on e.loan_id equals f.loan_id into af 
          from f in af.DefaultIfEmpty() 
         join g in context.ti_information 
          on e.loan_id equals g.loan_id into ag 
          from g in ag.DefaultIfEmpty() 
         select new 
         { 
          loan_id = a.loan_id, 
          ti_disb_id = a.ti_disb_id, 
          ti_freq_id = a.ti_freq_id, 
          ti_disbursements_stop_code = a.ti_stop_code, 
          tax_account_number = a.tax_account_number, 
          ti_disb_due_dt = b.ti_disb_due_dt, 
          ti_expire_dt = b.ti_expire_dt, 
          ti_disb_amt = b.ti_disb_amt, 
          schedule_id = b.schedule_id, 
          ba_name = c.ba_name, 
          inv_bank_cd = d.inv_bank_cd, 
          inv_cd = d.inv_cd, 
          inv_group_cd = d.inv_group_cd, 
          loan_name = e.loan_name, 
          prin_bal = f.prin_bal, 
          ti_bal = f.ti_bal, 
          ti_information_stop_code = g.ti_stop_cd, 
          non_escrowed_type = a.non_escrowed_type, 
          ba_type_id = a.ba_type_id, 
          bill_received_dt = a.bill_received_dt, 
         }); 

Сообщение об исключении:

InvalidOperation Исключение было необработанное кодом пользователя

Актерский к типу значения 'Int16' не удалось, потому материализованная значение равно нулю. Либо общий параметр типа результата, либо запрос должны использовать тип с нулевым значением.

Большое спасибо!

+0

Запустите запрос в базе данных, чтобы увидеть результат, а какие столбцы - null. Это должно дать вам подсказку о том, где находится нуль. –

+0

@GarrisonNeely исключение уже предоставило всю эту информацию (предполагая, что она фактически выбрасывается из строки 3 или 4 этого запроса), она говорит об одном из 'ti_disb_id' значения равны нулю. – evanmcdonnal

+0

@evanmcdonnal Это смешно, ни одно из значений на самом деле не равно нулю. Я просмотрел значения базы данных и даже использовал запрос, который должен быть сгенерирован _supposed_. Будь то _actually_ использует этот запрос, я еще не понял. –

ответ

0

Итак, длинный рассказ, после значительной отладки, я обнаружил, что проблема в том, что я использовал поведение LEFT JOIN вместо поведения INNER JOIN.

В частности, вызовы DefaultIfEmpty() создавали строки, которые приводили к нулевым значениям для sched_id, который имел тип short-short (Int16), вызывающий исключение. Выбрав эти вызовы DefaultIfEmpty(), плохие строки не были включены, и проблема была решена, так как sched_id никогда не получит нулевое значение.

1

Продолжая комментарий Гаррисона, я предлагаю использовать свойство контекстного журнала. Откройте StreamWriter и назначьте context.Log. Он даст вам точный SQL-запрос, который запускается в базе данных, и вы можете запустить его и посмотреть, где проблема.

+1

Исключением является то, что одно из значений ti_dsib_id равно null, нет необходимости смотреть на запрос. – evanmcdonnal

+0

спасибо за исправление. – kobigurk

+0

@kobigurk Все еще выясняет, как захватить SQL, но вот что у меня есть до сих пор: System.Data.Objects.ObjectQuery'1 [<> f__AnonymousType13'20 [System.Decimal, System.Int16, System.Int32, System .Nullable'1 [System.Int16], System.String, System.Nullable'1 [System.DateTime], System.Nullable'1 [System.DateTime], System.Nullable'1 [System.Decimal], System.Int16 , System.String, System.String, System.String, System.String, System.String, System.Nullable'1 [System.Decimal], System.Nullable'1 [System.Decimal], System.Nullable'1 [System .Int16], System.String, System.Nullable'1 [System.Int16], System.Nullable'1 [System.DateTime]]] –

1

Возможно, вам понадобится второй взгляд на вашу базу данных. Исключением является то, что один из этих шорт возвращается как null (a.ti_disb_id или a.ti_disb_id). При необходимости вы можете поместить заявление if в запрос или использовать оператор нулевого коалесцирования.

Я думаю, что изменение new {a.loan_id, a.ti_disb_id} на new { loan = a.loan_id, disb = a.ti_disb_id ?? 0} решит ваши проблемы. Оператор нулевого коалесцирования в основном говорит, что если это значение равно нулю, тогда используйте предоставленное значение по умолчанию. Чтобы использовать его, требуется назначение (я попробовал просто сделать a.ti_disb_id ?? 0, но он не будет компилироваться), поэтому я ввел имена свойств. Справочный документ - here.

+0

Просто попробовал это. По какой-то причине он не будет компилироваться с использованием оператора нуль-коалесцирования ??, поэтому я изменил его на использование тернарного оператора? и заменить на 0, если null. Протестировано как на ti_disb_id, так и на credit_id, но исключение все равно бросается. В любом случае, они не имеют значения NULL, поэтому они не должны иметь нулевые значения. Самое странное. –

+0

@MacSigler, который неудачен. Вы уверены, что ошибка исходит от одной из этих строк? Я полагаю, что любая попытка использования этого стиля инициализации завершится неудачно, если у вас есть значение «null». Компилятор должен вывести типы и не может вывести тип для null. Я думаю, что если бы я все еще пытался отладить это, я бы лично начал смотреть на инструкцию select. Он также создает анонимный тип, поэтому присвоение нулем также приведет к сбою. – evanmcdonnal

+0

Выключает это sched_id, а не ti_disb_id, вызывая исключение. Заглядывая в нее дальше. –

Смежные вопросы