Linq To SQL Указанное приведение не является допустимой ошибкой с объединением - PullRequest
3 голосов
/ 02 ноября 2011

У меня есть следующий код, который использует Linq to SQL в .NET 4.0 против сервера SQL Server 2008 R2:

    public void Patients()
    {
        var documents = GetEMRDocumentsByPatientId("231966");
        if (documents.Count() > 0)
        {
            foreach (var doc in documents)
            {
                Console.WriteLine(doc.PatientId);
            }
        }
    }

    public static IQueryable<EMRDocument> GetEMRDocumentsByPatientId(string inPatientId)
    {
        return GetEMRDocuments().Where(d => String.Equals(d.PatientId, inPatientId));
    }

    public static IQueryable<EMRDocument> GetEMRDocuments()
    {
        var dataContext = InitializeDataContext();
        IQueryable<EMRDocument> retVal = null;

        retVal = (from e in dataContext.EMREvaluations
                  select new EMRDocument
                  {
                      PatientId = e.PatientId,
                      IsDeleted = e.Deleted,
                  }).Union(
                 from e2 in dataContext.EMRPatientDailyNotes
                 select new EMRDocument
                 {
                     PatientId = e2.PatientID,
                     IsDeleted = false,
                 });
        return retVal;
    }

При запуске приложения вызывается Patients (); Я получаю «Ссылка на объект не установлена ​​для экземпляра объекта» «Указанное приведение неверно» в строке foreach в Patients () в первый раз. Documents.Count () работает правильно и возвращает правильное количество записей из базы данных. Я также могу взять сгенерированный SQL документов и запустить его в SSMS, и результаты вернутся правильно.

В выполняемом запросе select из dataContext.EMRPatientDailyNotes не возвращает записей, поскольку в этой таблице нет записи для PatientId 231966.

В GetEMRDocuments (), если я закомментирую IsDeleted = e.Deleted и IsDeleted = false в обоих вариантах выбора, весь код ниже будет выполнен без ошибок. Если я изменю IsDeleted = e.Deleted на IsDeleted = false, то код выполняется без ошибок. Если я удаляю весь Союз и просто запускаю следующее ...

retVal = (from e in dataContext.EMREvaluations
          select new EMRDocument
          {
              PatientId = e.PatientId,
              IsDeleted = e.Deleted,
          });

... тогда этот код выполняется без ошибок. Кроме того, e.Deleted - это bool из базы данных, а не bool? (Nullable bool), а IsDeleted - это bool. Кто-нибудь видел этот тип проблемы раньше? Я понятия не имею, что делать, чтобы это исправить. Кроме того, я ранее использовал Linq To Entities с тем же запросом и не получил эту ошибку. Любая помощь будет принята с благодарностью.

Спасибо, Dan

EDIT: Вот трассировка стека. У меня был какой-то другой код, который, казалось, скрывал фактическую ошибку:

[InvalidCastException: Specified cast is not valid.]
System.Data.SqlClient.SqlBuffer.get_Boolean() +5057281
System.Data.SqlClient.SqlDataReader.GetBoolean(Int32 i) +38
Read_EMRDocument(ObjectMaterializer`1 ) +313
System.Data.Linq.SqlClient.ObjectReader`2.MoveNext() +32
ATI.TherapyConnect.Service.Patients() in C:\SVN\Application\branches\dan.cagney\ATI.TherapyConnect\Service.asmx.cs:57
ATI.TherapyConnect.Content.UserControls.Shared.Patients.MyPatientsList.BindGrid(String inSortExpression, Int32 inCurrentPage) in C:\SVN\Application\branches\dan.cagney\ATI.TherapyConnect\Content\UserControls\Shared\Patients\MyPatientsList.ascx.cs:129
ATI.TherapyConnect.Content.UserControls.Shared.Patients.MyPatientsList.Page_Load(Object sender, EventArgs e) in C:\SVN\Application\branches\dan.cagney\ATI.TherapyConnect\Content\UserControls\Shared\Patients\MyPatientsList.ascx.cs:68
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +91
System.Web.UI.Control.LoadRecursive() +74
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207

Итак, по-видимому, существует проблема приведения в значение bool IsDeleted. Может ли быть так, что он пытается отобразить нулевое значение в IsDeleted of Union, поскольку нет никаких результатов, возвращаемых dataContext.EMRPatientDailyNotes? Я не думаю, что это будет проблемой, так как если я просто изменю IsDeleted = e.Deleted на IsDeleted = false, ошибки не будет. Итак, кажется, что e.Deleted возвращает не-bool значение. Но как это возможно, если e.Deleted определяется как bool из кода, сгенерированного Linq To SQL, и это битовое, а не нулевое поле в базе данных SQL?

Ответы [ 3 ]

2 голосов
/ 03 ноября 2011

Я наконец смог заставить это работать, однако я не знаю, почему мои изменения были необходимы. Вот что я изменил свой запрос:

retVal = (from e in dataContext.EMREvaluations 
              select new EMRDocument 
              { 
                  PatientId = e.PatientId, 
                  IsDeleted = e.Deleted == null ? false : e.Deleted, 
              }).Union( 
             from e2 in dataContext.EMRPatientDailyNotes 
             select new EMRDocument 
             { 
                 PatientId = e2.PatientID, 
                 IsDeleted = false, 
             }); 

Я модифицировал

IsDeleted = e.Deleted 

до

IsDeleted = e.Deleted == null ? false : e.Deleted

однако я понятия не имею, зачем это нужно, потому что e.Deleted указан в базе данных как bool (не нуль), так как же e.Deleted может иметь значение null? Я отмечаю это как ответ на данный момент, однако, если кто-то может сказать мне, почему это изменение кода было необходимо или как я могу обойтись без этого изменения кода, я отмечу это как ответ.

Спасибо, Dan

0 голосов
/ 07 апреля 2015

Принятый ответ не работал для меня, так как мне нужно было сохранить нулевые значения.

Я обнаружил, что переключение порядка объединения решило проблему, просто не спрашивайте меня, почему:

retVal = 
    (
        from e2 in dataContext.EMRPatientDailyNotes 
        select new EMRDocument 
        { 
            PatientId = e2.PatientID, 
            IsDeleted = (bool?)false
        }
    )
    .Union(
        from e in dataContext.EMREvaluations 
        select new EMRDocument 
        { 
            PatientId = e.PatientId, 
            IsDeleted = e.Deleted
        }
    ); 
0 голосов
/ 11 января 2012

У меня была похожая проблема в приведенной ниже функции. Он отлично работает в dev, но не работает с «Указанным приведением неверно» в рабочей версии на той же версии SQL Server.

public IQueryable<Contract> AllContracts()
    {
        IQueryable<Contract> contracts =
            from c in DbDw().Contracts
            select c;
        return contracts;
    }

DbDw () - это DataContext Linq To Sql

После долгих промахов, проб и ошибок я изменил это так:

public IQueryable<Contract> AllContracts()
    {
         return DbDw().Contracts;
    }

И тогда это сработало ... Иди разберись.

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