指定的转换无效 Linq 查询

8
你好,我想根据主键查询表格。
我已经尝试了两种方法:
var deviceDetails = (from d in db.Devices
                     where d.DeviceId == pointDetails.DeviceId
                     select d).ToList();  

编辑 d.DeviceId
var deviceDetails = db.Devices.Single(d => d.DeviceId == pointDetails.DeviceId)

我知道这些返回不同的类型,但现在不是问题所在。
这个语句会抛出一个 InvalidCastException 异常,我不知道为什么。PointDetails.DeviceId 明显是一个有效的 int。即使我用一个硬编码的 int 替换它,异常也会被抛出。
以下是堆栈跟踪的相关部分。
 at System.Data.SqlClient.SqlBuffer.get_Int32()
 at System.Data.SqlClient.SqlDataReader.GetInt32(Int32 i)
 at Read_Device(ObjectMaterializer`1 )
 at        System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
 at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
 at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

任何帮助都会被欣然接受,因为我已经没有想法了。

类定义和模式 这是设备的类定义。

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Devices")]
public partial class Device : INotifyPropertyChanging, INotifyPropertyChanged
{

    private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);

    private int _DeviceId;
    private int _DeviceTypeId;  
    private string _DeviceName; 
    private string _DeviceMACAddress;   
    private string _DeviceIPAddress;    
    private string _DeviceSubnetMask;
    private string _DeviceGatewayAddress;
    private int _ZoneId;
    private int _TelevisionTypeId;      
    private int _DeviceStatusId;        
    private byte _DeviceIsModified;     
    private int _DeviceSetupBaudRate;       
    private int _DeviceConfigId;        
    private byte _DeviceSetupIsInputInternalPower;      
    private int _DeviceBedSensorInput;      
    private int _DeviceEnsuiteSensorInput;      
    private int _DeviceRoomSensorInput;     
    private string _DeviceSetupString1;     
    private string _DeviceSetupString2;     
    private string _DeviceSetupString3;     
    private string _DeviceSetupString4;     
    private byte _DeviceSetupIsWiegand;     
    private int _DeviceSetupOptionId;       
    private byte _DeviceSetupIsLightMomentary;      
    private string _DeviceTestDateTime;     
    private string _DeviceTestResults;    

这里是SQL设计。
编辑已经确认了引起问题的列。
我逐个选择列以查找引起转换异常的列,发现是DeviceStatusId。在SQL中tinyInt类型的约束是什么?有没有建议可以使转换正确?

看起来你的数据库中有一个“DeviceId”为null,但是你的模型不知道它是可空的。 - Mike Christensen
我可以确认表中没有空的DeviceId,因为这是该表的主键。 - Paperwaste
这些中哪一个会抛出异常?where子句非常不同。可以推测,至少在语义上,d.devices不是整数,而是某种集合。如果是这样的话,我很惊讶它甚至能够编译通过。 - David
@David,两者都会抛出相同的异常。如果我使用 db.Devices.Where(d => d.devices == pointDetails.DeviceId);,仍然会抛出异常。 - Paperwaste
1
我猜问题并不在于主键,而是你选择的另一列。尝试将 select d 改为 select d.DeviceId,我敢打赌它会起作用 - 虽然结果对你没有任何用处!- 但这样你就可以确定了。 - Stephen Byrne
显示剩余8条评论
2个回答

14

我认为错误不一定在你的where条件语句中,而很可能在你的select语句中(至少是间接的)。数据库中的某个列(不一定是DeviceId列)与编译后的C#代码中的属性类型可能不同。可能只是一个列是可空的(并且包含空值),而代码中的属性是不可空的。

请注意异常发生的位置。这行代码表明,异常发生在结果被枚举时,而不是在where子句被评估时(调用"ToList"):

System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

这一行暗示了它是在实例被构造时(或者更确切地说,在“对象”被“实体化”时)发生的:

Read_Device(ObjectMaterializer`1 )

就像这个(对构造函数的调用)一样:

System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
基本上,至少有一列与代码不匹配,至少有一条记录利用了这种差异。 当发生这种情况时,正在构建的对象的构造函数会抛出异常,因为它无法理解接收到的数据。

基本上,至少有一列与代码不匹配,至少有一条记录利用了这种差异。当发生这种情况时,正在构建的对象的构造函数会抛出异常,因为它无法理解接收到的数据。


你说得对,现在我只需要找到让我困扰的那一列。 - Paperwaste
我将该列标识为DeviceStatusId。您有任何想法该如何修复它吗? - Paperwaste
@Paperwaste:我认为最好的方法是重新生成数据库上下文。这看起来像Linq to Sql,对吗?您应该能够更新DbContext文件或仅删除它并从数据库中重新创建它。在那一点上,代码本身中的任何类型错误都将(应该)变成编译时错误,这样更容易识别和纠正。 - David
2
private int _DeviceStatusId; -> 这在你的数据库架构中被指定为 "tinyint"。这可能是问题所在,因为将byte转换为int时,此属性的强制转换失败了吗? - Stephen Byrne
2
我在dbml文件中重新生成了表格,现在查询正常工作了。非常感谢StephenByrne和David的帮助,他们是我的救命恩人。今天我也学到了不少东西。 - Paperwaste
参考@StephenByrne,重新生成的DeviceStatusId现在是一个字节。所以你是正确的。 - Paperwaste

0

有时候在更新DataBase中的表格时,可能不会在DBML文件中进行更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接