Apache Ignite .NET执行SqlFieldsQuery时System.DateTime解析失败求助
Apache Ignite SQL查询DateTime列抛出BinaryInvalidTypeException的解决方案
问题根源
你用C#写入System.DateTime类型数据到缓存,但Java端QueryEntity配置的字段类型是java.sql.Timestamp,Ignite执行SQL查询时,Java节点无法解析.NET的DateTime类型,导致类型转换异常。数据能保存是因为二进制存储不强制类型校验,但SQL查询需要两端类型映射完全匹配。
解决方案
1. 调整Java端QueryEntity的字段类型
将java.sql.Timestamp改为java.util.Date——Ignite中.NET System.DateTime默认映射到Java java.util.Date,而非Timestamp,修改XML配置的fields部分:
<map> <entry key="ID" value="java.lang.Long"/> <entry key="DATE" value="java.util.Date"/> </map>
2. 显式处理C#端的DateTime转换(可选,若坚持用Timestamp)
如果必须保留java.sql.Timestamp配置,写入数据时要将DateTime转换为Java兼容的Timestamp类型:
// 替换原有的DateTime.Now写入逻辑 objectBuilder.SetField("DATE", new Timestamp(DateTime.Now.Ticks / 10000));
3. 提前加载Binary元数据同步节点
在C#代码启动Ignite后,先加载缓存的Binary类型元数据,确保Java节点能获取到完整的类型信息:
using (IIgnite ignite = Ignition.Start("RemoteDevServer.config")) { // 提前加载BinaryType,同步元数据到集群节点 ignite.GetBinary().GetBinaryType(cacheName); // 后续缓存操作代码不变 }
完整修改后的C#代码示例
string cacheName = "TEST"; try { using (IIgnite ignite = Ignition.Start("RemoteDevServer.config")) { ignite.GetBinary().GetBinaryType(cacheName); var cache = ignite.GetCache<long, IBinaryObject>(cacheName).WithKeepBinary<long, IBinaryObject>(); var objectBuilder = ignite.GetBinary().GetBuilder(cacheName); long Id = 100; objectBuilder.SetField("ID", Id); objectBuilder.SetField("DATE", DateTime.Now); cache[Id] = objectBuilder.Build(); var sqlp = new SqlFieldsQuery("select ID, DATE from TEST "); using (var cursor = cache.Query(sqlp)) { foreach (var row in cursor) { Console.WriteLine(row[0] + "---" + row[1]); } } } } catch (Exception ex) { throw ex; }
额外说明
- Ignite跨平台类型映射遵循默认规则:.NET
System.DateTime↔ Javajava.util.Date,java.sql.Timestamp需要显式转换才能匹配。 - 若使用实体类而非
IBinaryObject,可以通过[QuerySqlField(Type = typeof(Date))]注解指定类型映射,避免配置文件和代码的不一致。
内容的提问来源于stack exchange,提问作者Justin Mathew
相关产品推荐
相关产品推荐

