tomasfabian / ksqlDB.RestApi.Client-DotNet

ksqlDb.RestApi.Client is a C# LINQ-enabled client API for issuing and consuming ksqlDB push and pull queries and executing statements.
MIT License
93 stars 24 forks source link

"Bad request" as response using InsertIntoAsync() #7

Closed vijaymandave closed 2 years ago

vijaymandave commented 2 years ago

Hi,

We are using below code to insert rows-

public class Order
{
public int Id { get; set; }
public long OrderTime { get; set; }
public int OrderType { get; set; }
public string Description { get; set; }
}

calling like- await Write<Order>(orderdata);

static async Task Write<T>(T model)
        {
            var httpClientFactory = new HttpClientFactory(new Uri(@"http:\\localhost:8088"));

            var responseMessage = await new KSqlDbRestApiClient(httpClientFactory).InsertIntoAsync<T>(model);
            Console.WriteLine(responseMessage.IsSuccessStatusCode);           
        }

We are getting response message as "Bad request"

tomasfabian commented 2 years ago

hi @vijaymandave what is the version of your ksqldb? Could you please try out to override the table (source) name in the following manner?

var props = new InsertProperties() { EntityName = "`order`"};
var responseMessage = await new KSqlDbRestApiClient(httpClientFactory).InsertIntoAsync<T>(model, props);

Try enclose the from item name (EntityName) with backticks. Entity name should correspond with your ksqldb table name. Some (older) versions of ksqlb are case sensitive.

Thx Tomas

tomasfabian commented 2 years ago

@vijaymandave I've just released v1.8.0-rc.1, could you please verify the generated insert statement with this method?

var rawInsert = restApiProvider.ToRawInsertStatement(model);

Do you have a better name for this method?

Could you also try it via ksqldb-cli and provide me the expected statement which works in your environment? thx

UPDATE: By default the entity name is pluralized. You can turn it off:

new InsertProperties() { ShouldPluralizeEntityName = false };

In case that nothing works include here also the CREATE FromItem ... statement please, too.

vijaymandave commented 2 years ago

Hi @tomasfabian,

As per your suggestions, we have tried both solutions like below and both worked- Solution-1:

public async Task InsertOrder(Order order)
{
    var hcf = new HttpClientFactory(new Uri(@"http:\\localhost:8088"));
    var restApiProvider= new KSqlDbRestApiClient(hcf);        
    var insertProp = new InsertProperties() { EntityName = "`kafka_table_order`",ShouldPluralizeEntityName = false};
    var responseMessage = await restApiProvider.InsertIntoAsync<Order>(order,insertProp);
}

Solution-2:

public async Task InsertOrder(Order order)
{
    var hcf = new HttpClientFactory(new Uri(@"http:\\localhost:8088"));
    var restApiClient = new KSqlDbRestApiClient(hcf);
    var insertProp = new InsertProperties() { ShouldPluralizeEntityName = false };
    var rawInsert = restApiClient.ToRawInsertStatement(order,insertProp);
    var responseMessage = await restApiClient.ExecuteStatementAsync(new KSqlDbStatement(rawInsert));
}

@tomasfabian, which solution is better to use in terms of performance? Please suggest.

Name for ToRawInsertStatement(), would like give name ToInsertQueryString().

Thanks, Vijay

tomasfabian commented 2 years ago

@vijaymandave, the performance should be exactly the same. The second option could be interesting in case of Bulk inserts. This should work, but I haven't tried it yet:

var statements = new KSqlDbStatement(rawInsert1 + rawInsert2);
var responseMessage = await restApiClient.ExecuteStatementAsync(statements));

I will rename ToRawInsertStatement() to ToInsertQueryString(), thx.

Tomas

tomasfabian commented 2 years ago

ouch it is actually not a query, I'll rename it to ToInsertStatement(), do you agree @vijaymandave?

vijaymandave commented 2 years ago

ok, fine.

tomasfabian commented 2 years ago

I tried the bulk insert. It works and in this case it requires only one round trip to the db, so it will be more performant.

var insert1 = restApiProvider.ToInsertStatement(Model1);
var insert2 = restApiProvider.ToInsertStatement(Model2);
var bulkStatement = new KSqlDbStatement(insert1.Sql + insert2.Sql);

var httpResponseMessage = await restApiProvider.ExecuteStatementAsync(bulkStatement);

var responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
var statementResponses = await httpResponseMessage.ToStatementResponsesAsync();

In case of single statements it doesn't matter, you can use also restApiProvider.InsertIntoAsync<TEntity>

vijaymandave commented 2 years ago

Hi @tomasfabian,

Bulk insert also working for me. Please release stable version.

Thank you, Vijay

tomasfabian commented 2 years ago

I released Kafka.DotNet.ksqlDB.1.8.0.

@vijaymandave in case that you are satisfied with the package, could you please Star the repository with your team members in return, please?

vijaymandave commented 2 years ago

Done. Appreciate your support. Thank you.