I can't figure out why this works
var blah = this.Database.SqlQuery<MyObjectWithTwoStringPropsNamedKeyAndValue>("exec mySproc").ToList();
and this doesn't
var blah = this.Database.SqlQuery<KeyValuePair<string,string>>("exec mySproc").ToList();
"mySproc" returns three records with two varchar columns aliased "Key" and "Value".
In the second line of code, I get a list of three KeyValuePairs, but both properties (Key and Value) are null for each item in the list.
That's because the KeyValuePair properties, Key and Value are readonly properties.
The values for Key and Value can only be set in the constructor, and not changed later.
SqlQuery tries to map the columns returned by the stored procedure, but cannot find properties in which to write them. The documentation doesn't state that the properties must be writeable, but it's clear that it won't use the parameterized constructor, but the properties.
The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type.
Related
I am using jsonb type in a column in postgresql11. And I'd like to update one field in the json data and I see there is a function jsonb_set which can be used. (https://www.postgresql.org/docs/current/functions-json.html).
However, based on the document,
jsonb_set ( target jsonb, path text[], new_value jsonb [, create_if_missing boolean ] ) → jsonb
Returns target with the item designated by path replaced by new_value, or with new_value added
if create_if_missing is true (which is the default) and the item designated by path does not
exist. All earlier steps in the path must exist, or the target is returned unchanged. As with
the path oriented operators, negative integers that appear in the path count from the end of
JSON arrays. If the last path step is an array index that is out of range, and create_if_missing
is true, the new value is added at the beginning of the array if the index is negative, or at
the end of the array if it is positive.
The first argument is target. What does target mean here? Do I need to do a query to get existing value and put it as target?
I have tried below update statement:
my current data is:
# select "taxes" from "Sites" where "id" = '6daa9b5d-d5b2-4b0d-a8ee-5ad2cb141594';
taxes
--------------------------------------------------------------------------------------------------------------
{"feePercent": 0, "percent": 0}
And I tried below update:
# update "Sites" set "feePercent" = jsonb_set('{"feePercent": 0, "percent": 0}', '{feePercent}', 1) where "siteUuid"='6daa9b5d-d5b2-4b0d-a8ee-5ad2cb141594';
but I got below error:
ERROR: function jsonb_set(unknown, unknown, integer) does not exist
LINE 1: update "Sites" set "feePercent" = jsonb_set('{"feePerce...
jsonb_set() modifies a specific JSON object. So, your target is the JSON object (or JSON column) which you want to modify.
jsonb_set(my_jsonb_to_be_modified, ...)
So, if you had this JSON object;
{"my":"old", "json":"object"}
With the function you can turn it into:
{"my":"new", "json":"object"}
The code is:
demo:db<>fiddle
SELECT jsonb_set('{"my":"old", "json":"object"}', '{my}', '"new"')
The target is the original JSON object, the path points to the element you want to modify, and new_value is the new value for the element you specified in the path.
In that case my had the value old, which turns into new now.
From PostgreSQL v14 on, you can use subscripts to make this UPDATE statement look natural:
UPDATE "Sites"
SET taxes['feePercent'] = to_jsonb(1)
WHERE id = '6daa9b5d-d5b2-4b0d-a8ee-5ad2cb141594';
For earlier versions, you will have to use jsonb_set like this:
UPDATE "Sites"
SET taxes = jsonb_set(taxes, ARRAY['feePercent'], to_jsonb(1))
WHERE id = '6daa9b5d-d5b2-4b0d-a8ee-5ad2cb141594';
The effect is the same: the whole JSON is read, a new JSON is created and stored in a new version of the row.
All this becomes much simpler if you don't use JSON, but regular table columns.
I am currently getting a list of related field like so
List ( join_table::id_b;)'
and what i would like to do is filter that list by a second field in the same related table pseudo code as follows
List ( join_table::id_b;jointable:other="foo")
not really sure how to filter it down
The List() function will return a list of (non-empty) values from all related records.
To get a list filtered by a second field, you could do any one of the following:
Define a calculation field in the join table = If ( other = "foo" ; id_b ) and use this field in your List() function call instead of the id_b field;
Construct a relationship filtered by the other field;
Use the ExecuteSQL() function instead of List();
Write your own recursive custom function (requires the Advanced version to install).
my table contains int columns that correspons to enum types.
E.g. the values of int column Command corresponds to this type:
public enum Commands
{
Start = 1,
End = 2
}
If I query the table and order it by Command, I get the rows with Command=Start followed by Commen=End.
Is there a way I can sort the query by the string value of the Command column, e.g. End first and Start last.
results.OrderBy(s => (Command as Commands).ToString())
But it gives me error "Only initializers, entity members, and entity navigation properties are supported".
Of course I could put the Command's string value as a column and sort by it, but we prefer using int columns for different reasons.
Thanks
What is the best way to access table data from a SAP system?
I tried it with it RFC_READ_TABLE, but this RFC returns the data in concatenated form within a single column and has a size restriction for row data.
Is there a better way to access SAP data in generic form without creating custom RFCs into the system?
I am searching for a standard RFC solution, not a custom script.
If I understand your question right, you want to read a table, but at time of programming, you don't know which table.
With Select * from (tablename)you can read with a dynamic table name.
The target field can be defined dynamic with create data.
An example (untested, currently I have no access to an SAP-system):
DATA: lv_tablename TYPE string,
ev_filelength TYPE i.
lv_tablename = 'mara'. "e.g. a parameter
DATA dref TYPE REF TO data.
CREATE DATA dref TYPE TABLE OF (lv_tablename).
FIELD-SYMBOLS: <wa> TYPE ANY TABLE.
ASSIGN dref->* to <wa>.
SELECT * FROM (lv_tablename) INTO TABLE <wa>. "Attention for test, may be large result
"<wa> is like a variable with type table mara
TYPES: BEGIN OF t_bseg,
*include structure bseg.
bukrs LIKE bseg-bukrs,
belnr LIKE bseg-belnr,
gjahr LIKE bseg-gjahr,
buzei LIKE bseg-buzei,
mwskz LIKE bseg-mwskz, "Tax code
umsks LIKE bseg-umsks, "Special G/L transaction type
prctr LIKE bseg-prctr, "Profit Centre
hkont LIKE bseg-hkont, "G/L account
xauto LIKE bseg-xauto,
koart LIKE bseg-koart,
dmbtr LIKE bseg-dmbtr,
mwart LIKE bseg-mwart,
hwbas LIKE bseg-hwbas,
aufnr LIKE bseg-aufnr,
projk LIKE bseg-projk,
shkzg LIKE bseg-shkzg,
kokrs LIKE bseg-kokrs,
END OF t_bseg.
DATA: it_bseg TYPE STANDARD TABLE OF t_bseg INITIAL SIZE 0,
wa_bseg TYPE t_bseg.
DATA: it_ekko TYPE STANDARD TABLE OF ekko.
*Select all fields of a SAP database table into in itab
SELECT *
FROM ekko
INTO TABLE it_ekko.
Try this snippet of RFC_READ_TABLE to get data in structured form:
DATA: oref TYPE REF TO cx_root,
text TYPE string,
obj_data TYPE REF TO data.
lt_options TYPE TABLE OF rfc_db_opt,
ls_option TYPE rfc_db_opt,
lt_fields TYPE TABLE OF rfc_db_fld,
ls_field TYPE rfc_db_fld,
lt_entries TYPE STANDARD TABLE OF tab512.
FIELD-SYMBOLS: <fs_tab> TYPE STANDARD TABLE.
TRY.
ls_option-text = `some query`.
APPEND ls_option TO lt_options.
ls_field-fieldname = 'PARTNER'.
APPEND ls_field TO lt_fields.
ls_field-fieldname = 'TYPE'.
APPEND ls_field TO lt_fields.
ls_field-fieldname = 'BU_GROUP'.
APPEND ls_field TO lt_fields.
ls_field-fieldname = 'BU_SORT1'.
APPEND ls_field TO lt_fields.
ls_field-fieldname = 'TITLE'.
APPEND ls_field TO lt_fields.
CALL FUNCTION 'RFC_READ_TABLE' DESTINATION dest
EXPORTING
query_table = 'BUT000'
TABLES
options = lt_options
fields = lt_fields
data = lt_entries.
CATCH cx_root INTO oref.
text = oref->get_text( ).
MESSAGE text TYPE 'E'.
ENDTRY.
IF lt_entries IS NOT INITIAL.
CREATE DATA obj_data TYPE TABLE OF but000.
ASSIGN obj_data->* TO <fs_tab>.
CREATE DATA obj_data TYPE but000.
ASSIGN obj_data->* TO FIELD-SYMBOL(<fs_line>).
LOOP AT lt_entries ASSIGNING FIELD-SYMBOL(<wa_data>).
LOOP AT lt_fields ASSIGNING FIELD-SYMBOL(<fs_fld>).
ASSIGN COMPONENT <fs_fld>-fieldname OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<lv_field>).
IF <lv_field> IS ASSIGNED AND sy-subrc IS INITIAL.
<lv_field> = <wa_data>-wa+<fs_fld>-offset(<fs_fld>-length).
ENDIF.
APPEND <fs_line> TO <fs_tab>.
ENDLOOP.
ENDLOOP.
ENDIF.
IF <fs_tab> IS NOT INITIAL.
"Bingo!
ENDIF.
How to set an object to null.
Ex:
my object samp contains three fileds
samp.field1,samp.field2.sampfield3
If i set samp:= null;
im getting errors is there a way to set the object value to null.
An sql database does not know about objects, it deals with rows in table.
To remove a row use DELETE :
e.g. :
DELETE FROM samp WHERE id = 12345;
DELETE FROM samp WHERE field1 = 'Delete Me';
The first example is typical to remove individual rows uing their primary key (id in this case)
The second example will remove a group of rows which have a speciic value for a field.