writing a query in plain text  Topic is solved

Discussions relating to the REST API of Jiwa 7.

writing a query in plain text

Postby JuiceyBrucey » Tue Mar 02, 2021 3:04 pm

Is there any way that I can just write a query directly into the Db object in plain text something like this :

return new DebtorGetAllSpecificPricesResponse() { DebtorPriceList = Db.Select("SELECT * FROM IN_DebtorSpecificPrice as Prices WHERE Prices.DebtorID=="request.DebtorID)} ;

Instead of this:

var query = Db.From<IN_DebtorSpecificPrice>().Where<IN_DebtorSpecificPrice>((Prices)=>Prices.DebtorID == request.DebtorID);
return new DebtorGetAllSpecificPricesResponse() { DebtorPriceList = Db.Select(query)} ;

ORMLite is doing my head in. Things would be so easy if I could just write the SQL myself. I am just not sure of how to inject the SQL straight in.
Cheers
JuiceyBrucey
Frequent Contributor
Frequent Contributor
 
Posts: 132
Joined: Tue Aug 18, 2020 7:19 pm
Topics Solved: 1

Re: writing a query in plain text

Postby Mike.Sheen » Tue Mar 02, 2021 5:53 pm

JuiceyBrucey wrote:Is there any way that I can just write a query directly into the Db object in plain text something like this :

return new DebtorGetAllSpecificPricesResponse() { DebtorPriceList = Db.Select("SELECT * FROM IN_DebtorSpecificPrice as Prices WHERE Prices.DebtorID=="request.DebtorID)} ;

Instead of this:

var query = Db.From<IN_DebtorSpecificPrice>().Where<IN_DebtorSpecificPrice>((Prices)=>Prices.DebtorID == request.DebtorID);
return new DebtorGetAllSpecificPricesResponse() { DebtorPriceList = Db.Select(query)} ;

ORMLite is doing my head in. Things would be so easy if I could just write the SQL myself. I am just not sure of how to inject the SQL straight in.
Cheers


Yep - several ways to do it - You could leverage AutoQuery as that's already there - and you get magic pagination, filtering and so on - I've mentioned that before in response to one of your other posts, but if REALLY want just direct SQL which is protected from SQL Injection attacks - it looks like this:

In the Configure method, add the route:
Code: Select all
AppHost.Routes.Add(typeof(MyGetDebtorSpecificPricesRequest), "/Custom/GetDebtorSpecificPrice/{DebtorID}", "GET", "Retrieves a list of debtor specific prices for a given debtor.", "");


Define a request:
Code: Select all
[ApiResponse(200, "Records retrieved OK")]
[ApiResponse(401, "Not authenticated")]
[ApiResponse(404, "No debtor with the DebtorID provided was found")]
public class MyGetDebtorSpecificPricesRequest : IReturn<MyGetDebtorSpecificPricesResponse>
{
   public string DebtorID { get; set; }      
}   


Define a response:
Code: Select all
public class MyGetDebtorSpecificPricesResponse : List<IN_DebtorSpecificPrice>
{
}


And the service:
Code: Select all
public class CustomServices : Service
{
   [Authenticate]
   
   public MyGetDebtorSpecificPricesResponse Get(MyGetDebtorSpecificPricesRequest request)
   {
      return Db.SqlList<IN_DebtorSpecificPrice>("SELECT * FROM IN_DebtorSpecificPrice WHERE DebtorID = @DebtorID", new { DebtorID = request.DebtorID}).ConvertTo<MyGetDebtorSpecificPricesResponse>();         
   }
}   
Mike Sheen
Chief Software Engineer
Jiwa Financials

If I do answer your question to your satisfaction, please mark it as the post solving the topic so others with the same issue can readily identify the solution
User avatar
Mike.Sheen
Overflow Error
Overflow Error
 
Posts: 2444
Joined: Tue Feb 12, 2008 11:12 am
Location: Perth, Republic of Western Australia
Topics Solved: 756

Re: writing a query in plain text

Postby JuiceyBrucey » Fri Mar 05, 2021 5:40 pm

thank you for your reply.
This is working. I have specified the fields as well and that is working.
return Db.SqlList<IN_DebtorSpecificPrice>("SELECT RecID, InventoryID, DebtorID, Amount, ItemNo FROM IN_DebtorSpecificPrice WHERE DebtorID = @DebtorID",

So now I need to introduce two new variables from the request URL and use them in the SQL so that the URL looks like this:
/Custom/GetDebtorSpecificPrice/{DebtorID}/{StartPosition}/{EndPosition}

And the SQL looks something like this:
return Db.SqlList<IN_DebtorSpecificPrice>("SELECT RecID, InventoryID, DebtorID, Amount, ItemNo FROM IN_DebtorSpecificPrice WHERE DebtorID = @DebtorID LIMIT @StartPosition, @EndPosition",

I have done some searching around and have found that there is no "LIMIT" filter in MS-SQL. But apparently, I can use something like this instead of a SQL LIMIT :
ORDER BY RecID OFFSET @StartPosition ROWS FETCH NEXT @EndPosition ROWS ONLY;

Any ideas on how I would do this?
I have looked at autoquery, but am not liking it because is looks like I will have to learn a whole new language almost, just so it can write SQL for me that I can already write. I just dont get it.
But if it is the best solution, I will have to.
If you think AutoQuery is my best solution to this and future problems I am likely to encounter, could you please point me to the best tutorial for it?
I have looked a few so far, but it is looking like I have to enter a whole new world just to write SQL.
Cheers
JuiceyBrucey
Frequent Contributor
Frequent Contributor
 
Posts: 132
Joined: Tue Aug 18, 2020 7:19 pm
Topics Solved: 1

Re: writing a query in plain text

Postby JuiceyBrucey » Fri Mar 05, 2021 5:51 pm

This works correctly:

return Db.SqlList<IN_DebtorSpecificPrice>("SELECT RecID, InventoryID, DebtorID, Amount, ItemNo FROM IN_DebtorSpecificPrice WHERE DebtorID = @DebtorID ORDER BY RecID OFFSET 1 ROWS FETCH NEXT 20 ROWS ONLY;",

But I need to introduce the variables from the URL so that I have this:
return Db.SqlList<IN_DebtorSpecificPrice>("SELECT RecID, InventoryID, DebtorID, Amount, ItemNo FROM IN_DebtorSpecificPrice WHERE DebtorID = @DebtorID ORDER BY RecID OFFSET @StartPosition ROWS FETCH NEXT @EndPosition ROWS ONLY;",

I have this:
new { DebtorID = request.DebtorID}).ConvertTo<MyGetDebtorSpecificPricesResponse>();
But not sure how to add in the two new variables.
Cheers
JuiceyBrucey
Frequent Contributor
Frequent Contributor
 
Posts: 132
Joined: Tue Aug 18, 2020 7:19 pm
Topics Solved: 1

Re: writing a query in plain text

Postby Mike.Sheen » Sat Mar 06, 2021 12:22 pm

JuiceyBrucey wrote:But I need to introduce the variables from the URL so that I have this:
return Db.SqlList<IN_DebtorSpecificPrice>("SELECT RecID, InventoryID, DebtorID, Amount, ItemNo FROM IN_DebtorSpecificPrice WHERE DebtorID = @DebtorID ORDER BY RecID OFFSET @StartPosition ROWS FETCH NEXT @EndPosition ROWS ONLY;",

I have this:
new { DebtorID = request.DebtorID}).ConvertTo<MyGetDebtorSpecificPricesResponse>();
But not sure how to add in the two new variables.
Cheers


Change

Code: Select all
new { DebtorID = request.DebtorID}


to

Code: Select all
new { DebtorID = request.DebtorID, StartPosition = request.StartPosition, EndPosition  = request.EndPosition  }


You've defined the variables in the SQL with the @DebtorID, @StartPosition and @EndPosition - so the new { DebtorID = request.DebtorID... is creating a new dynamic object with a property named DebtorID, and setting the contents to be request.DebtorID. Db.SqlList will magically replace the tokens in the SQL string with the property values of matching property names of the dynamic object passed in.

You might want to also rename EndPosition in the request and SQL variable - right now it's not really an EndPosition, it's being treated as the number of rows to fetch - if you really do want consumers of the route to provide an EndPosition, then perhaps something like the following would be more appropriate:

Code: Select all
return Db.SqlList<IN_DebtorSpecificPrice>("SELECT RecID, InventoryID, DebtorID, Amount, ItemNo FROM IN_DebtorSpecificPrice WHERE DebtorID = @DebtorID ORDER BY RecID OFFSET @StartPosition ROWS FETCH NEXT @NumberRows ROWS ONLY;",
new { DebtorID = request.DebtorID, StartPosition = request.StartPosition, NumberRows = request.EndPosition - request.StartPosition }


But, I suspect you DO want the consumer of the route to provide StartPosition and the number of rows - as this is commonly expected for paging through data - in which case rename EndPosition to NumberRows in your request:

Code: Select all
return Db.SqlList<IN_DebtorSpecificPrice>("SELECT RecID, InventoryID, DebtorID, Amount, ItemNo FROM IN_DebtorSpecificPrice WHERE DebtorID = @DebtorID ORDER BY RecID OFFSET @StartPosition ROWS FETCH NEXT @NumberRows ROWS ONLY;",
new { DebtorID = request.DebtorID, StartPosition = request.StartPosition, NumberRows = request.NumberRows }
Mike Sheen
Chief Software Engineer
Jiwa Financials

If I do answer your question to your satisfaction, please mark it as the post solving the topic so others with the same issue can readily identify the solution
User avatar
Mike.Sheen
Overflow Error
Overflow Error
 
Posts: 2444
Joined: Tue Feb 12, 2008 11:12 am
Location: Perth, Republic of Western Australia
Topics Solved: 756

Re: writing a query in plain text

Postby JuiceyBrucey » Sat Mar 06, 2021 4:24 pm

Thank you very much Mike.
This has worked.
From the questions that you have seen me ask so far, what is the thing that I should put the most focus into learning so that I can keep ploughing ahead?
Thank you.
Cheers
JuiceyBrucey
Frequent Contributor
Frequent Contributor
 
Posts: 132
Joined: Tue Aug 18, 2020 7:19 pm
Topics Solved: 1

Re: writing a query in plain text

Postby JuiceyBrucey » Sat Mar 06, 2021 5:32 pm

Using the above as a template, I have tried to make a similar one, but am getting a 404 handler not found.
This is the code:
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using JiwaFinancials.Jiwa;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Drawing;
using ServiceStack;
using ServiceStack.DataAnnotations;
using ServiceStack.Model;
using JiwaFinancials.Jiwa.JiwaServiceModel.Tables;
using ServiceStack.Auth;
using System.Linq;
using ServiceStack.OrmLite; // Db

namespace JiwaFinancials.Jiwa.JiwaServiceModel
{
public class RESTAPIPlugin : System.MarshalByRefObject, JiwaFinancials.Jiwa.JiwaApplication.IJiwaRESTAPIPlugin
{
public void Configure(JiwaFinancials.Jiwa.JiwaApplication.Plugin.Plugin Plugin, ServiceStack.ServiceStackHost AppHost, Funq.Container Container, JiwaApplication.Manager JiwaApplicationManager)
{
AppHost.RegisterService<CustomServices>();
AppHost.Routes.Add(typeof(InventoryLimitFieldsRequest), "/Custom/InventoryLimitFields/{StartPosition}/{NumberRows}", "GET", "Retrieves inventory with limited fields, end and start specified.", "");
}
}

#region "Requests"
[ApiResponse(200, "Records retrieved OK")]
[ApiResponse(401, "Not authenticated")]
[ApiResponse(404, "Handler for Request not found")]
public class InventoryLimitFieldsRequest : IReturn<InventoryLimitFieldsResponse>
{
public int StartPosition { get; set; }
public int NumberRows { get; set; }
}
#endregion

#region "Responses"
[Serializable()]
public class InventoryLimitFieldsResponse : List<IN_Main>
{
}
#endregion

#region "Services"
public class CustomServices : Service
{
[Authenticate]
public InventoryLimitFieldsResponse Get(InventoryLimitFieldsRequest request)
{
return Db.SqlList<IN_Main>("SELECT LastSavedDateTime, InventoryID, PartNo, Description, Status, DefaultPrice, RRPPrice, Aux2, BackOrderable FROM IN_Main ORDER BY InventoryID OFFSET @StartPosition ROWS FETCH NEXT @NumberRows ROWS ONLY;",
new { StartPosition = request.StartPosition, NumberRows = request.NumberRows}).ConvertTo<InventoryLimitFieldsResponse>();
}
}
#endregion
}

It compiles not problem in the JIWA system. But I keep getting errors.
Any ideas?
Cheers
JuiceyBrucey
Frequent Contributor
Frequent Contributor
 
Posts: 132
Joined: Tue Aug 18, 2020 7:19 pm
Topics Solved: 1

Re: writing a query in plain text

Postby JuiceyBrucey » Wed Mar 10, 2021 9:42 am

can anyone help with this one?
JuiceyBrucey
Frequent Contributor
Frequent Contributor
 
Posts: 132
Joined: Tue Aug 18, 2020 7:19 pm
Topics Solved: 1

Re: writing a query in plain text

Postby Scott.Pearce » Wed Mar 10, 2021 11:57 am

Moved to appropriate forum.
Scott Pearce
Senior Analyst/Programmer
Jiwa Financials
User avatar
Scott.Pearce
Senpai
Senpai
 
Posts: 742
Joined: Tue Feb 12, 2008 11:27 am
Location: New South Wales, Australia
Topics Solved: 221

Re: writing a query in plain text

Postby Mike.Sheen » Wed Mar 10, 2021 12:13 pm

Hi Bruce,

If you want to provide a plugin for us to help you, the best way is to export the plugin to XML and attach that to your post.

In Jiwa exporting plugins to XML is done via the Plugin Maintenance form and on the Utilities tab of the Ribbon select the "XML Export" button
Plugin - Export to XML.png


Then on your forum post, you can attach the file using the upload attachment function below the body of your post.
Forums Attach File.png


By using the XML method it includes the assembly references and form + business logic hooks that we would need to make your plugin work for us.

You you do want to just provide a snippet of code, you can use the Code block BBCode to adorn the code to make it more readable.
Forums Code Block.png
Forums Code Block.png (14.22 KiB) Viewed 6902 times


For your latest problem - please attach the plugin XML so we can assist you further.
Mike Sheen
Chief Software Engineer
Jiwa Financials

If I do answer your question to your satisfaction, please mark it as the post solving the topic so others with the same issue can readily identify the solution
User avatar
Mike.Sheen
Overflow Error
Overflow Error
 
Posts: 2444
Joined: Tue Feb 12, 2008 11:12 am
Location: Perth, Republic of Western Australia
Topics Solved: 756

Next

Return to REST API

Who is online

Users browsing this forum: No registered users and 0 guests

cron