explicit many to many self-relations produces weird results in the generated client, pairing up wrong values - prisma

I've got users and contact requests with a table in between to explicitly define a self relation for cascade purposes.
user schema:
contactRequestsReceivedFrom ContactRequestRelations[] #relation("contactRequestReceivedFrom")
contactRequestsMadeTo ContactRequestRelations[] #relation("contactRequestMadeTo")
relations schema:
model ContactRequestRelations {
contactRequestReceivedFrom User #relation("contactRequestReceivedFrom", fields: [requestReceivedFromId], references: [id], onDelete: Cascade)
contactRequestMadeTo User #relation("contactRequestMadeTo", fields: [requestMadeToId], references: [id], onDelete: Cascade)
requestReceivedFromId String
requestMadeToId String
##id([requestReceivedFromId, requestMadeToId])
}
• I have to give the relations a name, prisma will complain it's too ambiguous otherwise
• if I give the same relation reference on all 4 of them, prisma will complain of "wrongly named relation detected"
I wanted to make a 'send contact request' operation.
Where I find either the user that the request is made for and then add the relation to the 'contactRequestsReceivedFromarray ---- or ---- find the user that is sending the request and create a relation on thecontactRequestsMadeTo`.
The issue is, even though the relation contactRequestsReceivedFrom ContactRequestRelations[] #relation("contactRequestReceivedFrom") on the user is clearly paired with the contactRequestReceivedFrom User #relation("contactRequestReceivedFrom", fields: [requestReceivedFromId], references: [id], onDelete: Cascade) relation on the relation table, when I attempt to create this with the client, prisma only lets me define the opposite of that relation which is rather redundant and confusing:
as it would serve no purpose to define in that context, as I would be defining who made the request.
Is this the correct pattern/syntax, or should I be looking at a more complex model with a couple more tables in between? Not a big fan of that option.

Related

Implementing 3 way relationship in Prisma

I also asked this question on Prisma forum.
** EDIT **: The forum has since been locked as read-only just 1 day after my question. It's sure getting scary because there is no official announcement of whether they'll stop developing Prisma 1 after implementing promised features or not. Surely they could have said something. And TBH, the unstable Prisma site does add to my shaking confidence in Prisma despite the number of stars in their repo.
I'm new to Prisma. So I have a 3-way relationship between User, Event and Role I would like to define. For each association of a User and an Event, there exists a Role for that association. If I were to design a database table for another ORM, I would have created a event_user table with user_id, event_id and role_id as columns to relate them.
Practically, a row of these 3 columns must be unique. Obviously, it would be good if Prisma can do the safeguarding of these constraints, but the obvious solution I see might not even come to Prisma 1.
My current design consists of the following:
type User {
// ...
eventUsers: [EventUser!]!
}
type Event {
// ...
eventUsers: [EventUser!]!
}
type EventUser {
role: Role!
event: Event!
user: User!
}
This design will make render all xxWhereUniquexx unusable, which is definitely a hassle to maintain relationships. upserts will certainly be unusable for maintaining the relationships.
How would one create a relationship like this in Prisma?
For some context, each user would have a list of global roles as well, so there would already be an association between User and Role. The question concerns the "local roles" for each event.
If each user already have a value for their respective roles, there would be no need for a third table (unless there is more information you'd like to be stored in your modal layer in which case the role type should be in the Role table).
Relationships are set with the #relation directive. You can apply it to either one of two tables in a relation but for clarity I'm apply them to the Event table. The example assumes users can be part of several events.
Tables:
enum ROLE_TYPE {
TYPE_ONE
TYPE_TWO
}
User {
user_id: ID! #id
events: [Event!]!
}
Event {
event_id: ID! #id
users: [User!]! #relation(link: INLINE)
}
Role {
role_id: ID! #id
type: ROLE_TYPE
event: Event! #relation(link: INLINE)
user: User! #relation(link: INLINE)
}
You can read more about relations on the Prisma site

How should I handle two different types of users in database?

I am building a ecommerce application with two different types of users, users who shop and vendors/brands.
Should I make two tables for each user like?
User| id, email, password, username, address, stripeCustomerId
Brands| id, email, password, username/brandName, shippingRate, address, stripeAccessToken etc.
Or should I make it like so:
Users| id, email, password, username, address, stripeCustomerId
Brands| userid, etc...
This is an example of trying to model the object-oriented notion of inheritance in a relational database. If you search for that term, you'll find several answers on Stack Overflow.
In your case, I think you have 3 logical entities:
User: email, password, username, address...
Customer (is a type of user): StripeID
Vendor (is a type of user): shipping rate, stripe token
How you model those logical entities to physical objects in your database is mostly a question of trade-offs - the other answers explain those.
I assume there will be significant differences in both the behaviour and attributes between "customer" and "vendor".
I also assume your data model will evolve over time - for instance, you probably need to store more than one address for each user (shipping, billing), you probably have different lifecycles for "customers" (new, registered, registration confirmed, payment confirmed) and "vendors" (new, approved, rejected).
If those things are true, I'd just bite the bullet and have 2 tables, customer and vendor. This means you can evolve their behaviour more easily - you don't have to worry about needing a slightly different address logic between two "customer" and "vendor", you just build what you need. Your schema is a little more self-explanatory - your foreign keys go to tables that say what they do (products -> vendors, not products -> users).
It shouldn't be two tables, but three :D
1. users (id, name, password, )
2. customers (user_id, customer_specific_fields)
3. vendors (user_id, vendor_specific_fields)

What's the relationship between res.partner and res.user?

I am new to odoo v8 and i am not able to understand the relationship between res_partner and res_users tables and also with hr_employee table are they all related?
The relationship between res.partner and res.user is that res.user inherits from res.partner using an inheritance type called "Delegation Inheritance" (see documentation).
Because of "Delegation Inheritance" every res.user record has a mandatory internal connection to a corresponding res.partner record using a field partner_id. What is this connection all about is to directly use all the fields of res.partner to store data shared by res.user and res.partner (i.e. name, phone, etc... if for example you refer to phone property of a record of res.user you'll get the value stored in the corresponding res.partner record) so res.user has to define fewer number of fields on it's own, like password, login, etc..
Note also that because of this relation res.user can NOT exist in the system without corresponding res.partner, it's why every res.user has one, but nonetheless res.partner can exist without res.user.
hr.employee have m21 with res.users (user_id)
res.users have m21 with res.partner(partner_id)
Actually only res.users has a "real" relationship to res.partner, because with every user odoo will create a partner (per default no customer and no supplier). this partner will be used e.g. for emails and the followers system in odoo.
But you can have partners without users, too. That will be a normal partner, for defining customers and suppliers.
And finally there is the employee. You can set a user on it. If i recall right, the user will be used for attendances and timesheets.

ADO.NET Entities not picking up an FK relationship

I've got a table "Persons" (PersonId, Name, Address) which contains information about people. I then subclass this information with tables "Clients" (PersonId, DateJoined) and Victims (PersonId, DateAssassinated).
In SSMS I have established an FK relationship FK_Clients_Persons and FK_Victims_Persons where the Primary Key is Persons.PersonId and the foreign key is the eponymous field in the Clients and Victims tables respectively. In SSMS I cannot see any obvious functional difference between these relationships.
However, in ADO.NET Entities when I create the model from the database, the tool does not identify FK_Victims_Persons but it does recognise FK_Clients_Persons. It just treats Victims.PersonId as a simple field and doesn't generate relationship members for it. The missing FK relationship does not appear in the Constraints tree of the Model Browser, but the other one does.
I have no idea why this is, has anyone faced this problem before?
No matter how many times I start over, I can't get it to work.

In Entity Framework, how do I specify a condition on an association?

I have a relational model with an associative table. But in addition to the related keys, this table also has a flag. I would like to define two associations: one where the flag is true and another where it is false. The EF designer can add a condition to an entity, but not to an association.
The associative table looks like this:
UserPrivilege
-------------
UserId int (FK1)
PrivilegeId int (FK2)
IsGranted bit
I would like to create two associations between the User entity and the Privilege entity: PrivilegesGranted and PrivilegesDenied.
You can't do this directly through the designer.
But this is possible in the XML using DefiningQuery and Create and Delete sprocs. See this old post on my blog for more: Associations with Payloads.
The only thing that is a bit interesting is I assume the PK is just UserId and PrivilegeId, which means a user can't be granted and denied for a particular privilege at the same time.
So if you write code like this:
Privilege p = user.Granted.First();
user.Granted.Remove(p);
user.Denied.Add(p);
ctx.SaveChanges();
Update ordering is important. because you are using a DefiningQuery for both associations, the EF doesn't know they are related, and that it needs to do the delete before it can do the update.
So you might end up with PK violations.
A way to address this issue is in the Insert and Delete sprocs for each association, you can essentially make them change the current row for the User and Privilege pair, if it exists update it with the correct IsGranted value, if not create it, i.e. make it an upsert.
Let me know how you go here
Alex