SQL数据表加载到DataView时出现System.InvalidCastException错误排查
问题描述
我用以下SQL语句创建了数据表:
CREATE TABLE AAPL_1day ( [INDEX] INT IDENTITY(1,1) PRIMARY KEY, [DateTime] SMALLDATETIME NOT NULL, [MonthNr] FLOAT NOT NULL, [DayNr] FLOAT NOT NULL, [roc_1] FLOAT, [roc_2] FLOAT, [hypo_upordown7days] FLOAT );
尝试用ML.NET将表数据加载到data变量时,调用data.Preview()抛出错误:
System.InvalidCastException: 'Specified cast is not valid.'
数据库连接验证正常,表中目标列均为FLOAT类型,对应C#实体类的属性也定义为float,但即使仅读取单个列,错误依然触发。相关C#代码如下:
void loadInData() { // Set up MLContext var mlContext = new MLContext(); // Define database connection parameters string databaseName = "AAPL"; string connectionString = "Server=localhost;Database=" + databaseName + ";Trusted_Connection=True;"; var tableName = "AAPL_1day"; var loader = mlContext.Data.CreateDatabaseLoader<AAPLData>(); var source = new DatabaseSource(SqlClientFactory.Instance, connectionString, $"SELECT * FROM {tableName}"); var data = loader.Load(source); var preview = data.Preview(); // 触发System.InvalidCastException string dummy_breakpoint = ""; // 断点位置 } public class AAPLData { [LoadColumn(2)] public float MonthNr; [LoadColumn(3)] public float DayNr; [LoadColumn(4)] public float roc_1; [LoadColumn(5)] public float roc_2; [LoadColumn(6), ColumnName("Label")] public float hypo_upordown7days; }
解决方案
1. 修正类型匹配问题
SQL Server中的FLOAT默认是双精度浮点型(FLOAT(53)),对应C#的double而非float(单精度)。将实体类中的所有float改为double即可解决类型转换错误:
public class AAPLData { [LoadColumn(2)] public double MonthNr; [LoadColumn(3)] public double DayNr; [LoadColumn(4)] public double roc_1; [LoadColumn(5)] public double roc_2; [LoadColumn(6), ColumnName("Label")] public double hypo_upordown7days; }
2. 优化查询语句(可选)
避免使用SELECT *,明确指定需要加载的列,减少不必要的数据读取,同时确保列顺序与LoadColumn索引对应:
var source = new DatabaseSource(SqlClientFactory.Instance, connectionString, $"SELECT MonthNr, DayNr, roc_1, roc_2, hypo_upordown7days FROM {tableName}");
此时需将LoadColumn的索引调整为从0开始:
public class AAPLData { [LoadColumn(0)] public double MonthNr; [LoadColumn(1)] public double DayNr; [LoadColumn(2)] public double roc_1; [LoadColumn(3)] public double roc_2; [LoadColumn(4), ColumnName("Label")] public double hypo_upordown7days; }
3. 使用列名映射替代索引(更可靠)
通过ColumnName属性直接绑定数据库列名,无需依赖列顺序,避免索引错误:
public class AAPLData { [ColumnName("MonthNr")] public double MonthNr; [ColumnName("DayNr")] public double DayNr; [ColumnName("roc_1")] public double roc_1; [ColumnName("roc_2")] public double roc_2; [ColumnName("hypo_upordown7days"), ColumnName("Label")] public double hypo_upordown7days; }
此时查询语句保持SELECT MonthNr, DayNr, roc_1, roc_2, hypo_upordown7days FROM {tableName}即可,无需指定LoadColumn索引。
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

