progaudi / progaudi.tarantool

.net connector for Tarantool NoSql database.
MIT License
48 stars 16 forks source link

Executing stored procedures with List type input #150

Open enescaglar opened 4 years ago

enescaglar commented 4 years ago

Hi,

I am trying to call a function on tarantool which inserts given list into a space. Function looks like below, it gets list, loop over records and inserts into tester space. When I call the function within tarantool like the following, it works as expected and inserts records into the space.

tarantool> lst = {{1,'Test',1}, {2, 'Test2', 2}} tarantool> batch_insert_tester(lst)

When I try to call the function through the library, it fails with the following error.

System.AggregateException: 'One or more errors occurred. (Tarantool returns an error for request with id: 31, code: 0x00008020 and message: [string "function batch_insert_tester(list)..."]:4: attempt to index local 'record' (a number value). )' ArgumentException: Tarantool returns an error for request with id: 31, code: 0x00008020 and message: [string "function batch_insert_tester(list)..."]:4: attempt to index local 'record' (a number value).

This is the code I have been using, as an input I am sending list of value tuples (tester space has 3 fields). How can I call a function with a list input like this?

using var tarantoolClient = await Box.Connect("..."); ValueTuple<int, string, int>[] test = new ValueTuple<int, string, int>[] { new ValueTuple<int, string, int>(4, "TEST4", 4), new ValueTuple<int, string, int>(5, "TEST5", 5) }; await tarantoolClient.Call("batch_insert_tester", test);

Here is the function defined on tarantool:

function batch_inserttester(list) box.begin() for , record in ipairs(list) do box.space.tester:replace{record[1], record[2], record[3]} end box.commit() end

VsevolodGus commented 1 year ago

I have a similar problem with different collection I`m trying to call function in the tarantool

await box.Call("save",  (
                    id: (ulong)item.PriceListItemDataID,
                    supplier_code: item.SupplierCode,
                    updated_at: item.UpdatedAt.ToString("yyyy-MM-dd hh:mm:ss.fffff"),
                    count: item.Quantity,
                    price: item.SupplierPrice,
                    product_id: item.ProductID,
                    price_list_id: item.PriceListID
                    ));

But I got an error with message:

System.ArgumentException: Tarantool returns an error for request with id: 31, code: 0x00008020  and message: ...e/gus/repos/tarantool/app/price-list/binary_protocol.lua:71: attempt to index local 'price_list' (a number value). 
   at ProGaudi.Tarantool.Client.LogicalConnection.SendRequestImpl[TRequest](TRequest request, Nullable`1 timeout)
   at ProGaudi.Tarantool.Client.LogicalConnection.SendRequest[TRequest,TResponse](TRequest request, Nullable`1 timeout)
   at ProGaudi.Tarantool.Client.LogicalConnectionManager.SendRequest[TRequest,TResponse](TRequest request, Nullable`1 timeout)
   at ProGaudi.Tarantool.Client.Box.Call[TTuple,TResponse](String functionName, TTuple parameters)
   at ProGaudi.Tarantool.Client.Box.Call[TTuple](String functionName, TTuple parameters)
   at Tarantool.Connecter.Senders.SenderBinary.SendAsync(PriceListItemData[] data, CancellationToken cancellationToken) in /home/gus/RiderProjects/Tarantool/Tarantool.Connecter/Senders/SenderBinary.cs:line 52

In tarantool function I have so code:

function save(price_list)
    log.info('Start save')
    log.info('price_list: %d', price_list)
    log.info('product_id: %s', price_list.product_id)
.....
end

I looks in the logs and see so picture:

tarantool.router | 2023-11-24 22:28:21.066 [23321] main/162/main/app.price-list.binary_protocol I> Start save
tarantool.router | 2023-11-24 22:28:21.066 [23321] main/162/main/app.price-list.binary_protocol I> price_list: 1

I try find attributes in projects, but I didn`t found

Also I try send object with need Attributes, but I have exception

Converter not found for type Tarantool.Connecter.Models.SendData

Model SendData

[MsgPackArray]
[MsgPackMap]
public class SendData
{
    [MsgPackMapElement("id")]
    [MsgPackArrayElement(0)]
    public ulong ID { get; set; }

    [MsgPackMapElement("supplier_code")]
    [MsgPackArrayElement(1)]
    public string SupplierCode { get; set; }

    [MsgPackMapElement("updated_at")]
    [MsgPackArrayElement(2)]
    public string UpdatedAt { get; set; }

    [MsgPackMapElement("count")]
    [MsgPackArrayElement(3)]
    public string Count { get; set; }

    [MsgPackArrayElement(4)]
    [MsgPackMapElement("price")]
    public string Price { get; set; }

    [MsgPackMapElement("product_id")]
    [MsgPackArrayElement(5)]
    public int ProductID { get; set; }

    [MsgPackMapElement("price_list_id")]
    [MsgPackArrayElement(6)]
    public int PriceListID { get; set; }
}

Sending code

foreach (var item in data)
            {
                var a = new SendData()
                {
                    ID = (ulong)item.PriceListItemDataID,
                    SupplierCode = item.SupplierCode,
                    UpdatedAt = item.UpdatedAt.ToString("yyyy-MM-dd hh:mm:ss.fffff"),
                    Count = item.Quantity,
                    Price = item.SupplierPrice,
                    ProductID = item.ProductID,
                    PriceListID = item.PriceListID
                };

                await box.Call("save",  a);    
            }

I see example from tests

And I have class MapContext similar with class from your tests

public class MapContext
{
    public MsgPackContext Context { get; protected set; }

    public MapContext()
    {
        Context = new MsgPackContext();
        Context.RegisterConverter(new SendDataConverter());
        Context.GetConverter<SendData>();
        Context.DiscoverConverters<SendData>();
    }
}

And I write my own implementation for converter SendDataConverter

I use OS: Ubuntu 20.04 .Net Version: .NET 8