Room management system in Prisma - mysql

I tried to create a database for a room management sytem and I'm confused about the relations and couldn't find helpful resources on the internet can you tell me if there is anything wrong with this prisma script? as I want to control it in expressJs and make an application based on it
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model Guest {
guestId String #id #default(uuid())
name String
phone String #unique()
address String?
nationality String
Reservation Reservation[] #relation("GuestReservation")
}
model Reservation {
reservationId Int #id #default(autoincrement())
checkIn DateTime
checkOut DateTime
Guest Guest #relation("GuestReservation", fields: [guestId], references: [guestId], onDelete: Cascade)
guestId String
visitors Int
Room Room #relation("RoomReservation", fields: [roomId], references: [roomId], onDelete: Cascade)
type ReservationType
roomId Int
Bill Bill? #relation("BillReservation")
}
enum ReservationType {
Booking
Contract
Booked
Canceled
}
model Room {
roomId Int #id #default(autoincrement())
price Float
type Type
Reservation Reservation[] #relation("RoomReservation")
}
enum Type {
Single
Double
Triple
}
model Bill {
invoiceNo String #id #default(uuid())
Reservation Reservation #relation("BillReservation", fields: [reservationId], references: [reservationId], onDelete: Cascade)
reservationId Int #unique()
roomService Float #default(0)
paymentMode Payment
Service Service[]
}
enum Payment {
Cash
Visa
}
model Service {
serviceId String #id #default(uuid())
type ServiceType
name String
price Float
Bill Bill #relation(fields: [billInvoiceNo], references: [invoiceNo], onDelete: Cascade)
billInvoiceNo String
}
enum ServiceType {
Bar
Laundry
}
I tried to make a crud for each entity but I end up with relational erros such as foregin key and stuff like that which means there is something wrong with my relations.

Your schema is valid, though I would recommend keeping consistency while defining id for your tables. Some of the tables have id of string type while some are of numeric type.
Here's an example of queries to create entites for your models.
import {
PrismaClient,
Type,
ServiceType,
Payment,
ReservationType,
} from '#prisma/client';
const prisma = new PrismaClient({
log: ['query'],
});
async function main() {
// Creating a room
await prisma.room.create({
data: {
price: 100,
type: Type.Single,
roomId: 1,
},
});
// Creating a guest
await prisma.guest.create({
data: {
name: 'Test',
nationality: 'Indian',
phone: '1234567890',
address: 'Test Address',
guestId: '1',
},
});
// Creating a service with a bill and a reservation
await prisma.service.create({
data: {
name: 'test',
price: 100,
type: ServiceType.Bar,
serviceId: '1',
Bill: {
create: {
paymentMode: Payment.Cash,
invoiceNo: '1',
Reservation: {
create: {
checkIn: new Date(),
checkOut: new Date(),
type: ReservationType.Booked,
visitors: 1,
roomId: 1,
guestId: '1',
},
},
},
},
},
});
}
main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});
Here's the query response:
> ts-node index.ts
prisma:query BEGIN
prisma:query INSERT INTO `white_egret`.`Room` (`roomId`,`price`,`type`) VALUES (?,?,?)
prisma:query SELECT `white_egret`.`Room`.`roomId`, `white_egret`.`Room`.`price`, `white_egret`.`Room`.`type` FROM `white_egret`.`Room` WHERE `white_egret`.`Room`.`roomId` = ? LIMIT ? OFFSET ?
prisma:query COMMIT
prisma:query BEGIN
prisma:query INSERT INTO `white_egret`.`Guest` (`guestId`,`name`,`phone`,`address`,`nationality`) VALUES (?,?,?,?,?)
prisma:query SELECT `white_egret`.`Guest`.`guestId`, `white_egret`.`Guest`.`name`, `white_egret`.`Guest`.`phone`, `white_egret`.`Guest`.`address`, `white_egret`.`Guest`.`nationality` FROM `white_egret`.`Guest` WHERE `white_egret`.`Guest`.`guestId` = ? LIMIT ? OFFSET ?
prisma:query COMMIT
prisma:query BEGIN
prisma:query INSERT INTO `white_egret`.`Reservation` (`reservationId`,`checkIn`,`checkOut`,`guestId`,`visitors`,`type`,`roomId`) VALUES (?,?,?,?,?,?,?)
prisma:query INSERT INTO `white_egret`.`Bill` (`invoiceNo`,`reservationId`,`roomService`,`paymentMode`) VALUES (?,?,?,?)
prisma:query INSERT INTO `white_egret`.`Service` (`serviceId`,`type`,`name`,`price`,`billInvoiceNo`) VALUES (?,?,?,?,?)
prisma:query SELECT `white_egret`.`Service`.`serviceId`, `white_egret`.`Service`.`type`, `white_egret`.`Service`.`name`, `white_egret`.`Service`.`price`, `white_egret`.`Service`.`billInvoiceNo` FROM `white_egret`.`Service` WHERE `white_egret`.`Service`.`serviceId` = ? LIMIT ? OFFSET ?
prisma:query COMMIT

Related

Prisma One-to-One update Parent or update Parent and Child

I have a Parent Child (One-To-One) Relationship like this:
model Account {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
billingAddress Address?
name String
##map("Accounts")
}
model Address {
id Int #id #default(autoincrement())
city String?
country String?
postalCode Int?
state String?
street String?
accountId Int #unique
account Account #relation(fields: [accountId], references: [id])
}
I want to be able to Update the Parent Record without the need of updating also the Child Record. Furthermore, it would be great, if I can update the Parent Record and the Child Record at the same time. Right now I am getting an Error when only trying to send the Data for the Parent Record.
Here are my DTOs to Create and Edit the Entities:
Create / Edit Account:
export class CreateAccountDto {
#IsString()
#IsOptional()
name: string;
#IsOptional()
billingAddress?: CreateAddressDto;
}
Create / Edit Addresss:
export class EditAddressDto {
#IsString()
#IsOptional()
city?: string;
#IsString()
#IsOptional()
country?: string;
#IsNumber()
#IsOptional()
postalCode?: number;
#IsString()
#IsOptional()
state?: string;
#IsString()
#IsOptional()
street?: string;
#IsInt()
#IsOptional()
accountId: number;
}
I'm creating and editing the Account like this:
async editAccount(accountId: number, dto: EditAccountDto) {
let account;
console.log({dto})
account = await this.prisma.account.update({
where: {
id: accountId
},
data: {
...dto,
billingAddress: {
update: {
...dto.billingAddress
}
}
},
include: {
billingAddress: true
}
});
console.log(account)
return account;
}
When i try to Edit the Account with the following Data
{
"name": "Test Account Create2",
"billingAddress": {
"id": 2,
"city": "Dortmund",
"state": "NRW",
"postalCode": 44442,
"country": "Germany",
"street": "Benninghofer Heide 63",
"accountId": 10000001
}
}
i am getting the following Error:
Unknown arg `accountId` in data.billingAddress.update.accountId for type AddressUncheckedUpdateWithoutAccountInput. Did you mean `country`? Available args:
type AddressUncheckedUpdateWithoutAccountInput {
id?: Int | IntFieldUpdateOperationsInput
city?: String | NullableStringFieldUpdateOperationsInput | Null
country?: String | NullableStringFieldUpdateOperationsInput | Null
latitude?: Decimal | NullableDecimalFieldUpdateOperationsInput | Null
longitude?: Decimal | NullableDecimalFieldUpdateOperationsInput | Null
postalCode?: Int | NullableIntFieldUpdateOperationsInput | Null
state?: String | NullableStringFieldUpdateOperationsInput | Null
street?: String | NullableStringFieldUpdateOperationsInput | Null
}
at Document.validate (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:29297:20)
at serializationFn (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31876:19)
at runInChildSpan (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:25100:12)
at PrismaService._executeRequest (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31883:31)
at consumer (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31810:23)
at C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31815:51
at AsyncResource.runInAsyncScope (node:async_hooks:199:9)
at C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31815:29
at runInChildSpan (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:25100:12)
at PrismaService._request (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31812:22)
The error says, you are not allowed to specify accountId when you are updating the address in this way. You can just remove it from your DTO and everything should be fine.

Prisma 2 - Unkown arg 'where' in select.fruit.where for type UserFruit. Did you mean 'select'? Available args

Trying to query in prisma and filter results from a related object but get the error:
Unknown arg 'where' in select.fruit.where for type UserFruit. Did you
mean 'select'? Available args fruit{}
async findShops(req) {
const userId = parseInt(req.params.id);
const shop = await prisma.shop.findMany({
select: {
id: true,
name: true,
logo: true,
fruit:{
select:{
id:true,
userId:true,
fruitNumber:true,
created: true,
updated: true,
},
where: {
userId: userId
}
}
}
})
return shop;
};
example payload expected:
[
{ id: 1001, name: 'test1', logo: 'log.png', fruit: null },
{ id: 1002, name: 'test2', logo: 'log2.jpg', fruit: null },
{ id: 1003, name: 'test3', logo: 'log3.jpg', fruit: null },
{
id: 1005,
name: 'test4',
logo: 'log4.png',
fruit: {
id: '62450ee5-e75d-4a67-8d79-120d11ddf508',
userId: 111,
fruitNumber: '123456',
created: 2022-07-01T06:39:52.924Z,
updated: 2022-07-01T06:39:52.936Z
}
},
{
id: 1004,
name: 'test5',
logo: 'log5.jpg',
fruit: {
id: '20e9af37-2e6f-4070-8475-c5a914f311dc',
userId: 111,
fruitNumber: '123878',
created: 2022-07-01T07:21:27.898Z,
updated: 2022-07-01T07:21:27.901Z
}
}
]
I can easily achieve the expected output by not having the "where" but I need it because the fruit object can contain more than 1 object so I need to filter by userId e.g.
fruit: {
id: '62450ee5-e75d-4a67-8d79-120d11ddf508',
userId: 111,
fruitNumber: '123456',
created: 2022-07-01T06:39:52.924Z,
updated: 2022-07-01T06:39:52.936Z
},
{
id: '62450ee5-e75d-4a67-8d79-120d11ddf508',
userId: 999,
fruitNumber: '123456',
created: 2022-07-01T06:39:52.924Z,
updated: 2022-07-01T06:39:52.936Z
}
For the fruit object I need nulls and anything that matches the userId and based on design it should only ever be 1 record for each shop for the specific user.
At somepoint my code seemed to work but after I did a prisma generate it stopped working. Is there another way I can achieve the same result or is there someway to fix this?
Note:version info below.
model UserFruit {
id String #id #default(uuid())
fruitNumber String #map("fruit_number")
shopId Int #unique #map("shop_id")
userId Int #map("user_id")
created DateTime #default(now())
updated DateTime #updatedAt
fruit Fruit #relation(fields: [fruitId], references: [id])
##unique([userId, fruitId], name: "userFruit")
##map("user_Fruit")
}
model Shop {
id Int #id #default(autoincrement())
name String #unique
logo String
created DateTime #default(now())
updated DateTime #updatedAt
fruit UserFruit?
##map("Shop")
}
model User {
id Int #id #default(autoincrement())
created DateTime #default(now())
updated DateTime #updatedAt
uid String #unique
email String #unique
phone String #unique
firstName String #map("first_name")
lastName String #map("last_name")
dob DateTime?
gender String?
roleId Int #default(1) #map("role_id")
role Role #relation(fields: [roleId], references: [id])
##map("user")
}
Why not do a nested where at the top level to only search for shops whose fruit has the userId you need, rather than doing a nested select? It should make your query simpler and also solve your problem.
const userId = parseInt(req.params.id);
const shop = await prisma.shop.findMany({
select: {
id: true,
name: true,
logo: true,
fruit: {
select: {
id: true,
userId: true,
fruitNumber: true,
created: true,
updated: true,
},
// Removed the nested "where" from here
},
},
where: {
// One of the following conditions must be true
OR: [
// Return shops who have a connected fruit AND
// the fruit's "userId" attribute equals the variable "userID"
{
fruit: {
is: {
userId: userId,
// Can also simplify this to the below line if you want
// userId
},
},
},
// Return shops who do not have a connected fruit
// this will be true if "fruitId" is null
// could also write this as {fruit: {is: {}}}
{
fruitId: {
equals: null,
},
},
],
},
});
This query should output an array of shops where the connected fruit model's userId property equals your userId variable.

TypeORM inserts an additional empty row for no reason when saving an entity

I've been making an application for tracking user finances with NestJS, TypeORM and MySQL on the backend and all was going swell until I ran into a brick wall which was saving an entity called Financialchange which represents one unit of financial expense or gain. The problem is that in a table that represents a many to many relationship of user defined tags with the financial change, an empty row is inserted every time I save this entity along with the row that is correctly inserted.
The saving is done like this:
const financialChange = await this.financialChangeRepository.save({
amount: payload.amount,
description: payload.description,
expense: payload.expense,
paymentSourceId: payload.paymentSourceId,
appUserId: payload.appUserId,
createdAt: format(new Date(), "yyyy-MM-dd hh:mm:ss")
});
payload.tagIds.forEach(async (tagId) => {
await this.financialChangeTagRepository.save({
financialChangeId: financialChange.id,
tagId
});
});
An example of sent data:
mutation {
addFinancialChange(
financialChange: {
appUserId: 1
amount: 200
description: "Description"
expense: true
paymentSourceId: 1
tagIds: [1]
}
)
}
And when selecting data from the many to many table I get this:
The entity data is as follows, first the MySQL table creation:
CREATE TABLE financialchange (
id INT AUTO_INCREMENT PRIMARY KEY,
amount DOUBLE,
createdAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
description VARCHAR(255),
expense BOOLEAN,
paymentSourceId INT,
appUserId INT,
FOREIGN KEY (appUserId) REFERENCES appuser(id),
FOREIGN KEY (paymentSourceId) REFERENCES paymentsource(id)
);
And then the TypeORM entity in Nest:
#Index("appUserId", ["appUserId"], {})
#Index("paymentSourceId", ["paymentSourceId"], {})
#Entity("financialchange", { schema: "finapp" })
export class Financialchange {
#PrimaryGeneratedColumn({ type: "int", name: "id" })
public id?: number;
#Column("double", { name: "amount", nullable: true, precision: 22 })
public amount?: number | null;
#Column("datetime", { name: "createdAt", default: () => "CURRENT_TIMESTAMP" })
public createdAt?: Date;
#Column("varchar", { name: "description", nullable: true, length: 255 })
public description?: string | null;
#Column("tinyint", { name: "expense", nullable: true, width: 1 })
public expense?: boolean | null;
#Column("int", { name: "paymentSourceId", nullable: true })
public paymentSourceId?: number | null;
#Column("int", { name: "appUserId", nullable: true })
public appUserId?: number | null;
#ManyToOne(() => Appuser, (appuser) => appuser.financialchanges, {
onDelete: "NO ACTION",
onUpdate: "NO ACTION"
})
#JoinColumn([{ name: "appUserId", referencedColumnName: "id" }])
public appUser?: Appuser;
#ManyToOne(
() => Paymentsource,
(paymentsource) => paymentsource.financialchanges,
{ onDelete: "NO ACTION", onUpdate: "NO ACTION" }
)
#JoinColumn([{ name: "paymentSourceId", referencedColumnName: "id" }])
public paymentSource?: Paymentsource;
#OneToMany(
() => Financialchangetag,
(financialchangetag) => financialchangetag.financialChange
)
public financialchangetags?: Financialchangetag[];
}
It is in concept defined as having N amounts of tags binded to it, which is why I have created a table that represents a many to many relation called financialchangetags:
CREATE TABLE financialchangetag (
id INT AUTO_INCREMENT PRIMARY KEY,
financialChangeId INT,
tagId INT,
FOREIGN KEY (financialChangeId) REFERENCES financialchange(id),
FOREIGN KEY (tagId) REFERENCES tag(id)
);
#Index("financialChangeId", ["financialChangeId"], {})
#Index("tagId", ["tagId"], {})
#Entity("financialchangetag", { schema: "finapp" })
export class Financialchangetag {
#PrimaryGeneratedColumn({ type: "int", name: "id" })
public id?: number;
#Column("int", { name: "financialChangeId", nullable: true })
public financialChangeId?: number | null;
#Column("int", { name: "tagId", nullable: true })
public tagId?: number | null;
#ManyToOne(
() => Financialchange,
(financialchange) => financialchange.financialchangetags,
{ onDelete: "NO ACTION", onUpdate: "NO ACTION" }
)
#JoinColumn([{ name: "financialChangeId", referencedColumnName: "id" }])
public financialChange?: Financialchange;
#ManyToOne(() => Tag, (tag) => tag.financialchangetags, {
onDelete: "NO ACTION",
onUpdate: "NO ACTION"
})
#JoinColumn([{ name: "tagId", referencedColumnName: "id" }])
public tag?: Tag;
}
And the tag table is defined in this manner:
CREATE TABLE tag (
id INT AUTO_INCREMENT PRIMARY KEY,
description VARCHAR(255)
);
#Entity("tag", { schema: "finapp" })
export class Tag {
#PrimaryGeneratedColumn({ type: "int", name: "id" })
public id?: number;
#Column("varchar", { name: "description", nullable: true, length: 255 })
public description?: string | null;
#OneToMany(
() => Financialchangetag,
(financialchangetag) => financialchangetag.tag
)
public financialchangetags?: Financialchangetag[];
}
I have no clue why this is, I have tried inserting a record into financialchange with a transaction manager and through other methods of saving data that TypeORM offers, but I still get an empty row in my M:N table.

Sequelize Upsert is Creating instead of Updating

According to the documentation found here it states as follows
upsert(values, [options]) -> Promise.<created>
Insert or update a single row. An update will be executed if a row which matches the supplied values on either the primary key or a unique key is found. Note that the unique index must be defined in your sequelize model and not just in the table. Otherwise you may experience a unique constraint violation, because sequelize fails to identify the row that should be updated.
So my expectation is that upserting using a unique key should replace the existing value. However when my code runs instead of updating the existing database record, it adds a new one. What am I doing wrong?
here is a sample of my model
'use strict'
module.exports = (db, dataTypes) => {
const titanJob = db.define('titanJob', {
titanId: {
type: dataTypes.STRING,
allowNull: false,
unique: true
},
name: {
type: dataTypes.STRING,
allowNull: false
}
}, {
timestamps: true
})
return titanJob
}
and here is an example of my upsert
await asyncForEach(res.data.hits.hits, async es => {
const src = es._source
try {
await titanJob.upsert({
name: src.name,
titanId: src.id,
}, { titanId: src.id })
logger.debug(`[${file}] upsert successful`)
} catch (err) {
logger.warn(`[${file}] failed to save to database`)
logger.warn(`[${file}] ${err}`)
}
})
First you should add a unique index (constraint) to your table. The data you upserting should contain the field set of the unique index (constraint).
It should work. Here is an example using "sequelize": "^5.21.3":
index.ts:
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../../db';
import assert from 'assert';
class TitanJob extends Model {}
TitanJob.init(
{
titanId: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
},
{ sequelize, modelName: 'titanJob', timestamps: true },
);
(async function test() {
try {
await sequelize.sync({ force: true });
const datas = [
{ titanId: '1', name: 'programmer' },
{ titanId: '2', name: 'teacher' },
];
const jobs = await TitanJob.bulkCreate(datas);
assert.deepEqual(
jobs.map((job) => ({ titanId: job.id, name: job.name })),
datas,
'Should bulk create programmer and teacher datas',
);
const rval = await TitanJob.upsert({ titanId: '1', name: 'driver' }, { returning: true });
assert.equal(rval[0].titanId, '1', 'Should update the row which titanId is "1"');
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
Execution results:
{ POSTGRES_HOST: '127.0.0.1',
POSTGRES_PORT: '5430',
POSTGRES_PASSWORD: 'testpass',
POSTGRES_USER: 'testuser',
POSTGRES_DB: 'node-sequelize-examples' }
Executing (default): DROP TABLE IF EXISTS "titanJob" CASCADE;
Executing (default): DROP TABLE IF EXISTS "titanJob" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "titanJob" ("id" SERIAL , "titanId" VARCHAR(255) NOT NULL UNIQUE, "name" VARCHAR(255) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'titanJob' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "titanJob" ("id","titanId","name","createdAt","updatedAt") VALUES (DEFAULT,'1','programmer','2020-02-14 08:09:45.506 +00:00','2020-02-14 08:09:45.506 +00:00'),(DEFAULT,'2','teacher','2020-02-14 08:09:45.506 +00:00','2020-02-14 08:09:45.506 +00:00') RETURNING *;
Executing (default): CREATE OR REPLACE FUNCTION pg_temp.sequelize_upsert(OUT created boolean, OUT primary_key text) AS $func$ BEGIN INSERT INTO "titanJob" ("titanId","name","createdAt","updatedAt") VALUES ('1','driver','2020-02-14 08:09:45.524 +00:00','2020-02-14 08:09:45.524 +00:00') RETURNING "id" INTO primary_key; created := true; EXCEPTION WHEN unique_violation THEN UPDATE "titanJob" SET "titanId"='1',"name"='driver',"updatedAt"='2020-02-14 08:09:45.524 +00:00' WHERE ("id" IS NULL OR "titanId" = '1') RETURNING "id" INTO primary_key; created := false; END; $func$ LANGUAGE plpgsql; SELECT * FROM pg_temp.sequelize_upsert();
Executing (default): SELECT "id", "titanId", "name", "createdAt", "updatedAt" FROM "titanJob" AS "titanJob" WHERE "titanJob"."id" = '1';
No assertion fails. It works as expected. Check the data rows in the database:
node-sequelize-examples=# select * from "titanJob";
id | titanId | name | createdAt | updatedAt
----+---------+---------+----------------------------+----------------------------
2 | 2 | teacher | 2020-02-14 08:09:45.506+00 | 2020-02-14 08:09:45.506+00
1 | 1 | driver | 2020-02-14 08:09:45.506+00 | 2020-02-14 08:09:45.524+00
(2 rows)
source code: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/59686743

how to serialize using entityframework ICollection 'my way'

i have
table of users. - key IdUser , and other colsumns...
table of perms key IdPerm, and column PermName
and table of UserPerms key IdUserPermand columns IdPerm IdUser and Value
so when i select this user using Entity Framework and return it as json from api i get
{ IdUser : 1, login: "xx", name: "xxx",
UserPerms : [
{IdUserPerm : 1, IdUser : 1, idPerm: 1, value: 1, idPermNavigation: {idperm: 1, PermName:"Feature1"}}
{IdUserPerm : 2, IdUser : 1, idPerm: 2, value: 2, idPermNavigation: {idperm: 2, PermName:"Feature2"}}
{IdUserPerm : 3, IdUser : 1, idPerm: 3, value: 5, idPermNavigation: {idperm: 3, PermName:"Feature3"}}
]
}
is there any way i can configure this json serializer or .net core EF so i get result
UserPerms :{permname:value, next..}
so in this example to get
{IdUser:1, login:"xx", name:"yy",..., UserPerms:{Feature1:1, Feature2:2, Feature3:5}}
or any way to redesign DB so EF got this as 'default' ?
thanks and regards !
You can workaround by create DTO like
class UserPermResult {
int IdUser;
string Login;
...
ICollection<Perm> UserPerms;
}
class Perm {
string Name;
int Value;
}
and use Select linQ
values.Select(f=> new UserPermResult {
IdUser = f.IdUser,
...
UserPerms = f.UserPerms.Select(p=> new Perm{
Name = p.IdPermNavigation?.PermName,
Value = p.Value
})
});