Getting Record ID after saving with SubSonic 2.2 - subsonic

How do I get the Record ID (Primary Key) immediately after saving a record? I have the ID column as auto generated. I need to pass the ID to another object as a "Foreign Key" before saving that object.
Currently I do
Product.Save()
Can't I do
int id = Product.Save()

You can simply do
Product.Save();
int id = Product.ID; //or whatever your ID column is

Related

How to insert new rows to a junction table Postgres

I have a many to many relationship set up with with services and service_categories. Each has a table, and there is a third table to handle to relationship (junction table) called service_service_categories. I have created them like this:
CREATE TABLE services(
service_id SERIAL,
name VARCHAR(255),
summary VARCHAR(255),
profileImage VARCHAR(255),
userAgeGroup VARCHAR(255),
userType TEXT,
additionalNeeds TEXT[],
experience TEXT,
location POINT,
price NUMERIC,
PRIMARY KEY (id),
UNIQUE (name)
);
CREATE TABLE service_categories(
service_category_id SERIAL,
name TEXT,
description VARCHAR(255),
PRIMARY KEY (id),
UNIQUE (name)
);
CREATE TABLE service_service_categories(
service_id INT NOT NULL,
service_category_id INT NOT NULL,
PRIMARY KEY (service_id, service_category_id),
FOREIGN KEY (service_id) REFERENCES services(service_id) ON UPDATE CASCADE,
FOREIGN KEY (service_category_id) REFERENCES service_categories(service_category_id) ON UPDATE CASCADE
);
Now, in my application I would like to add a service_category to a service from a select list for example, at the same time as I create or update a service. In my node js I have this post route set up:
// Create a service
router.post('/', async( req, res) => {
try {
console.log(req.body);
const { name, summary } = req.body;
const newService = await pool.query(
'INSERT INTO services(name,summary) VALUES($1,$2) RETURNING *',
[name, summary]
);
res.json(newService);
} catch (err) {
console.log(err.message);
}
})
How should I change this code to also add a row to the service_service_categories table, when the new service ahas not been created yet, so has no serial number created?
If any one could talk me through the approach for this I would be grateful.
Thanks.
You can do this in the database by adding a trigger to the services table to insert a row into the service_service_categories that fires on row insert. The "NEW" keyword in the trigger function represents the row that was just inserted, so you can access the serial ID value.
https://www.postgresqltutorial.com/postgresql-triggers/
Something like this:
CREATE TRIGGER insert_new_service_trigger
AFTER INSERT
ON services
FOR EACH ROW
EXECUTE PROCEDURE insert_new_service();
Then your trigger function looks something like this (noting that the trigger function needs to be created before the trigger itself):
CREATE OR REPLACE FUNCTION insert_new_service()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS
$$
BEGIN
-- check to see if service_id has been created
IF NEW.service_id NOT IN (SELECT service_id FROM service_service_categories) THEN
INSERT INTO service_service_categories(service_id)
VALUES(NEW.service_id);
END IF;
RETURN NEW;
END;
$$;
However in your example data structure, it doesn't seem like there's a good way to link the service_categories.service_category_id serial value to this new row - you may need to change it a bit to accommodate
I managed to get it working to a point with multiple inserts and changing the schema a bit on services table. In the service table I added a column: category_id INT:
ALTER TABLE services
ADD COLUMN category_id INT;
Then in my node query I did this and it worked:
const newService = await pool.query(
`
with ins1 AS
(
INSERT INTO services (name,summary,category_id)
VALUES ($1,$2,$3) RETURNING service_id, category_id
),
ins2 AS
(
INSERT INTO service_service_categories (service_id,service_category_id) SELECT service_id, category_id FROM ins1
)
select * from ins1
`,
[name, summary, category_id]
);
Ideally I want to have multiple categories so the category_id column on service table, would become category_ids INT[]. and it would be an array of ids.
How would I put the second insert into a foreach (interger in the array), so it creates a new service_service_categories row for each id in the array?

Proper Sequelize flow to avoid duplicate rows?

I am using Sequelize in my node js server. I am ending up with validation errors because my code tries to write the record twice instead of creating it once and then updating it since it's already in DB (Postgresql).
This is the flow I use when the request runs:
const latitude = req.body.latitude;
var metrics = await models.user_car_metrics.findOne({ where: { user_id: userId, car_id: carId } })
if (metrics) {
metrics.latitude = latitude;
.....
} else {
metrics = models.user_car_metrics.build({
user_id: userId,
car_id: carId,
latitude: latitude
....
});
}
var savedMetrics = await metrics();
return res.status(201).json(savedMetrics);
At times, if the client calls the endpoint very fast twice or more the endpoint above tries to save two new rows in user_car_metrics, with the same user_id and car_id, both FK on tables user and car.
I have a constraint:
ALTER TABLE user_car_metrics DROP CONSTRAINT IF EXISTS user_id_car_id_unique, ADD CONSTRAINT user_id_car_id_unique UNIQUE (car_id, user_id);
Point is, there can only be one entry for a given user_id and car_id pair.
Because of that, I started seeing validation issues and after looking into it and adding logs I realize the code above adds duplicates in the table (without the constraint). If the constraint is there, I get validation errors when the code above tries to insert the duplicate record.
Question is, how do I avoid this problem? How do I structure the code so that it won't try to create duplicate records. Is there a way to serialize this?
If you have a unique constraint then you can use upsert to either insert or update the record depending on whether you have a record with the same primary key value or column values that are in the unique constraint.
await models.user_car_metrics.upsert({
user_id: userId,
car_id: carId,
latitude: latitude
....
})
See upsert
PostgreSQL - Implemented with ON CONFLICT DO UPDATE. If update data contains PK field, then PK is selected as the default conflict key. Otherwise, first unique constraint/index will be selected, which can satisfy conflict key requirements.

Azure CosmosDB/Nodejs - Entity with the specified id does not exist in the system

I am trying to delete and update records in cosmosDB using my graphql/nodejs code and getting error - "Entity with the specified id does not exist in the system". Here is my code
deleteRecord: async (root, id) => {
const { resource: result } = await container.item(id.id, key).delete();
console.log(`Deleted item with id: ${id}`);
},
Somehow below code is not able to find record, even "container.item(id.id, key).read()" doesn't work.
await container.item(id.id, key)
But if I try to find record using query spec it works
await container.items.query('SELECT * from c where c.id = "'+id+'"' ).fetchNext()
FYI- I am able to fetch all records and create new item, so Connection to DB and reading/writing is not an issue.
What else can it be? Any pointer related to this will be helpful.
Thanks in advance.
It seems you pass the wrong key to item(id,key). According to the Note of this documentation:
In both the "update" and "delete" methods, the item has to be selected
from the database by calling container.item(). The two parameters
passed in are the id of the item and the item's partition key. In this
case, the parition key is the value of the "category" field.
So you need to pass the value of your partition key, not your partition key path.
For example, if you have document like below, and your partition key is '/category', you need to use this code await container.item("xxxxxx", "movie").
{
"id":"xxxxxx",
"category":"movie"
}

AutoMapper - Retrieve a different field from a linked source table than the one that links it

I have the following table structure that mixes legacy fields with an updated schema:
Coaster
Id (Int)
ParkId (Int)
Park
Id (int)
UniqueId (Guid)
So, the Coaster and Park tables are linked using the Park.Id field. The UniqueId field is not currently used in the old schema. We are migrating to a clean DB using AutoMapper, and this new schema looks like this:
Coaster
Id (Int)
ParkId (Guid)
Park
Id (Guid)
The problem I am having is doing this using AutoMapper. I've been experimenting with this code:
private ModelMapper()
{
Mapper.Initialize(x =>
{
x.AddProfile<ConvertersMappingProfile>();
});
}
// This is the part that I'm trying to work out
public ConvertersMappingProfile()
{
CreateMap<Park, NewSchema.Park>()
.ForMember(dst => dst.Id, map => map.MapFrom(src => src.ParkId));
}
In the new schema, the Park table's Id matches the old schema's UniqueId.
My question is: Because in the old schema there is no direct link to the UniqueId value of the Park table, how to do I get that value to map to the new schema using the Coaster.ParkId field to Park.Id field mapping?
I used a custom resolve to fix the problem. So I created my resolver, which pulls up a list of the items in the database (which is typically pretty small) to get all the values from the table I need, and retrieves the value. (Pre-refactored code):
public class ParkResolver : IValueResolver<Original.Park, New.Park, string> {
public string Resolve(Original.Park source, New.Park dest, string destMember, ResolutionContext context) {
List<Original.Park> list = new List<Original.Park>();
using (IDbConnection con = new SQLiteConnection(#"Data Source=C:\Users\Me\Documents\Parks.sql;")) {
con.Open();
list = con.Query<Original.Park>($"SELECT * FROM Parks WHERE Id = {source.ParkId}").ToList();
con.Close();
}
return list.FirstOrDefault().UniqueId;
}
}
And I call my custom resolver for the tables I am mapping:
CreateMap<Original.Park, New.Park>()
.ForMember(dst => dst.ParkId, map => map.MapFrom(new ParkResolver()));
Hopefully that will help someone else.

NetSuite Suite script - all columns for object

Is there a function in Suitescript using which we would get all the fields or columns belonging to the object (i.e. location, account, transaction etc.)
You can use the function getAllFields() of the record to retrieve all the fields for that record.
var fields = nlapiGetNewRecord().getAllFields()
// loop through the returned fields
fields.forEach(function(fieldName){
var field = record.getField(fieldName);
var fieldlabel = field.getLabel();
if(fieldlabel=='something'){
//do something here
return;
}
}
you can also get the list of available fields for a record here

Resources