#c# #linq-to-sql
#c# #linq-to-sql
Вопрос:
У меня есть следующий код, который использует Linq для 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() в первый раз. Документы.Count() работает корректно и возвращает правильное количество записей из базы данных. Я также могу взять сгенерированный SQL документов и запустить его в SSMS, и результаты вернутся правильно.
В выполняемом запросе выберите из DataContext.EMRPatientDailyNotes, не возвращает записей, потому что в этой таблице нет записи для идентификатора пациента 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?(обнуляемый bool) и IsDeleted — это bool . Кто-нибудь видел этот тип проблемы раньше? Я понятия не имею, что делать, чтобы исправить это. Кроме того, я ранее использовал Linq для объектов с этим же запросом и не получил эту ошибку. Любая помощь будет с благодарностью.
Спасибо, Дэн
Редактировать:Вот трассировка стека. У меня был какой-то другой код, который, казалось, скрывал фактическую ошибку:
[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:SVNApplicationbranchesdan.cagneyATI.TherapyConnectService.asmx.cs:57
ATI.TherapyConnect.Content.UserControls.Shared.Patients.MyPatientsList.BindGrid(String inSortExpression, Int32 inCurrentPage) in C:SVNApplicationbranchesdan.cagneyATI.TherapyConnectContentUserControlsSharedPatientsMyPatientsList.ascx.cs:129
ATI.TherapyConnect.Content.UserControls.Shared.Patients.MyPatientsList.Page_Load(Object sender, EventArgs e) in C:SVNApplicationbranchesdan.cagneyATI.TherapyConnectContentUserControlsSharedPatientsMyPatientsList.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 объединения, поскольку из DataContext не возвращаются результаты.EMRPatientDailyNotes? Я не думаю, что это было бы проблемой, поскольку, если я просто изменю IsDeleted = e.Deleted на IsDeleted = false, ошибки не будет. Итак, похоже, что e.Deleted возвращает значение, отличное от bool. Но как это было бы возможно, если e.Deleted определяется как bool из сгенерированного кода Linq To SQL, и это поле bit, а не null в базе данных SQL?
Ответ №1:
Я, наконец, смог заставить это работать, однако я не знаю, зачем потребовалось мое изменение. Вот на что я изменил свой запрос:
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 (не null), так как же e.Deleted может иметь значение null? На данный момент я отмечаю это как ответ, однако, если кто-нибудь может сказать мне, зачем понадобилось это изменение кода или как я могу обойтись без этого изменения кода, я отмечу это как ответ.
Спасибо, Дэн
Комментарии:
1. Это ошеломляет. У меня был тот же сценарий, и это также устранило мою проблему.
Ответ №2:
У меня была аналогичная проблема в приведенной ниже функции. Это отлично работало бы в dev, но сбой с «Указанное приведение недопустимо» в рабочей среде на той же версии SQL Server.
public IQueryable<Contract> AllContracts()
{
IQueryable<Contract> contracts =
from c in DbDw().Contracts
select c;
return contracts;
}
DbDw() — это ссылка на Sql DataContext
После долгих размышлений, проб и ошибок я изменил его на это:
public IQueryable<Contract> AllContracts()
{
return DbDw().Contracts;
}
И тогда это сработало… Поди разберись.
Ответ №3:
Принятый ответ не сработал для меня, так как мне нужно было сохранить значения null.
Я обнаружил, что переключение порядка объединения решило проблему, просто не спрашивайте меня, почему:
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
}
);