如何通过ProGaudi.Tarantool.Client调用Lua函数并获取返回结果
问题根源与解决方案
1. 修复Lua函数中的空间名错误
你创建的空间是messages,但Lua函数里写的是box.space.my_space:get(key),这会导致找不到空间时返回字符串'Key not found',而找到数据时返回tuple,客户端无法处理这种混合返回类型,直接触发序列化异常。
修正后的Lua函数:
lua_code = [[ function(key) local result = box.space.messages:get(key) if result then return result else return nil -- 返回nil而非字符串,保持返回类型统一 end end]] box.schema.func.create('get_message_by_id', { language = 'LUA', body = lua_code })
2. 统一返回类型,避免混合结构
客户端的序列化器预期的是数组/ tuple结构,如果返回字符串(比如'Key not found'),会直接触发SerializationException。必须让Lua函数始终返回tuple或nil,不要返回字符串类型。
3. 调整.NET客户端代码
方式一:使用实体类接收结果
确保你的MessageEntityMessagePack类正确配置,并且调用Call时指定正确的泛型参数:
// 建议用await避免.Result死锁 var box = await Box.Connect("localhost:3301"); var tuple = TarantoolTuple.Create(3L); // 用long匹配Tarantool的integer类型 // 调用时,输入参数是TarantoolTuple<long>,返回是MessageEntityMessagePack数组 var result = await box.Call<TarantoolTuple<long>, MessageEntityMessagePack[]>( "get_message_by_id", tuple ); // 处理结果 if (result.Data.Length > 0) { var message = result.Data[0]; // 使用message的属性 } else { // 处理找不到数据的情况 }
方式二:使用值元组接收
如果不想用实体类,确保值元组的类型和Tarantool空间的字段完全匹配:
var box = await Box.Connect("localhost:3301"); var result = await box.Call<TarantoolTuple<long>, (long, string, string, long, DateTime, string)[]>( "get_message_by_id", TarantoolTuple.Create(3L) );
4. 配置DateTime序列化适配
Tarantool的datetime类型在MsgPack中是特定格式,确保客户端的序列化配置正确:
var config = new TarantoolClientConfig { SerializerOptions = MessagePackSerializerOptions.Standard .WithResolver(TarantoolResolver.Instance) }; var box = await Box.Connect("localhost:3301", config);
关键注意事项
- Tarantool的
integer类型对应.NET的long,不要用int,避免类型不匹配导致序列化错误。 - 不要混合返回类型(tuple和字符串),必须保持返回值结构一致。
- 避免使用
.Result同步调用异步方法,容易引发死锁,改用await。
内容的提问来源于stack exchange,提问作者Vladislav Filatov
相关产品推荐
相关产品推荐

