I want to model a tournament in Prisma. I have this:
model Tournament {
id Int #id #default(autoincrement())
meets Meet[]
}
model Meet {
id Int #id #default(autoincrement())
name String
matches Match[]
}
model Match {
id Int #id #default(autoincrement())
player1Id Int
player2Id Int
meet Meet #relation(fields: [meetId], references: [id])
meetId Int
}
model Player {
id Int #id #default(autoincrement())
name String
}
model Result {
id Int #id #default(autoincrement())
matchId Int
playerId Int
}
I feel the Match model might need to link player1 and player2 (with a relation) to the Player model. I'm also not sure how the result should be modelled.
Any advice will be appreciated.
You can do it as follow:
datasource mysql {
provider = "mysql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
generator erd {
provider = "prisma-erd-generator"
output = "./entity-relationship-diagram.svg"
}
model Tournament {
id Int #id #default(autoincrement())
name String
meets Meet[] #relation()
}
model Meet {
id Int #id #default(autoincrement())
name String
tournament Tournament #relation(fields: [tournamentId], references: [id])
tournamentId Int
matches Match[] #relation()
}
model Match {
id Int #id #default(autoincrement())
name String
meeet Meet #relation(fields: [meetId], references: [id])
meetId Int
players Player[] #relation("matchPlayers", fields: [playerId], references: [id])
playerId Int
winner Player? #relation("matchWinner", fields: [winnerId], references: [id])
winnerId Int?
score Score[] #relation()
}
model Player {
id Int #id #default(autoincrement())
name String
matchesPlayers Match[] #relation("matchPlayers")
matchesWinner Match[] #relation("matchWinner")
score Score[] #relation()
}
model Score {
id Int #id #default(autoincrement())
score Int
match Match #relation(fields: [matchId], references: [id])
matchId Int
player Player #relation(fields: [playerId], references: [id])
playerId Int
}
And it will generate the following database
Related
I want to add a self relation on my user table but it seems there is an issue with the way am doing it.
model User {
id BigInt #id(map: "user_pkey") #unique(map: "user_id_key") #default(autoincrement())
firstname String? #db.VarChar
lastname String? #db.VarChar
username String? #unique #db.VarChar
email String? #db.VarChar
password String? #db.VarChar
organization String? #db.VarChar
createdAt DateTime? #db.Timestamptz(6)
updatedAt DateTime? #db.Timestamptz(6)
parent_id BigInt?
deletedAt DateTime? #db.Timestamptz(6)
deleted_by BigInt?
##map("users")
parent User? #relation(fields: [parent_id], references: [id]) // this line gives me error
}
I see the following error :
```Error validating field parent in model User: The relation field parent on model User is missing an opposite relation field on the model User. Either run prisma format or add it manually.
What am i doing wrong here?
Can you try this schema?
model User {
id BigInt #id(map: "user_pkey") #unique(map: "user_id_key") #default(autoincrement())
firstname String? #db.VarChar
lastname String? #db.VarChar
username String? #unique #db.VarChar
email String? #db.VarChar
password String? #db.VarChar
organization String? #db.VarChar
createdAt DateTime? #db.Timestamptz(6)
updatedAt DateTime? #db.Timestamptz(6)
parent_id BigInt?
deletedAt DateTime? #db.Timestamptz(6)
deleted_by BigInt?
parent User? #relation("UserParent", fields: [parent_id], references: [id]) // this line gives me error
usersAsParents User[] #relation("UserParent")
##map("users")
}
For reference, here is a guide on Self-Relations.
I have a model Post that looks like this:
model Post {
id String #id #default(auto()) #map("_id") #db.ObjectId
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
...
...
...
LikedPosts LikedPost[]
}
and model LikedPost that looks like this:
model LikedPost {
id String #id #default(auto()) #map("_id") #db.ObjectId
createdAt DateTime #default(now())
post Post #relation(fields: [postId], references: [id])
postId String
user User #relation(fields: [userId], references: [id])
userId String
##unique([userId, postId])
}
I'm trying to return all posts that user liked inside db.post.findMany with this prisma filter:
where: {
LikedPosts: {
some: {
userId: {
equals: session.userId as string,
},
},
},
},
But it always returns empty array as a result.
Even if I put raw value instead of session.userId like "62d6b8d220ba0fa6d5cea60f" of the user that has liked posts, it still returns nothing.
It doesn't even work inside Prisma Studio.
Am I doing something wrong here?
The answer was to add #db.ObjectId to the userId field in prisma Schema like this:
model LikedPost {
id String #id #default(auto()) #map("_id") #db.ObjectId
createdAt DateTime #default(now())
post Post #relation(fields: [postId], references: [id])
postId String #db.ObjectId
user User #relation(fields: [userId], references: [id])
userId String #db.ObjectId
##unique([userId, postId])
}
I'm new to ORM tools and I want to do relationships between tables only with naming convention. For example if I have classes like below;
public class City
{
public int Id;
public string Name;
}
public class District
{
public int Id;
public string Name;
public City City;
}
I want to map these classes in my database like this.
City
Id int,
Name nvarchar(100)
District
Id int,
Name nvarchar(100),
CityId int
I don't want to use foreign keys and when I put any class as a property in another class I want to migrate these property as "ClassNameId". Any solution for this ?
Your design for relationship is not correct to use EF.
the correct relationship is
public class City
{
public int Id;
public string Name;
public virtual ICollection<District> Districts;
}
public class District
{
public int Id;
public string Name;
public int CityId;
public virtual City City;
}
and in entity configuration you need to make in city definition on your EntityTypeConfiguration :
public DistrictConfiguration()
{
HasKey(a => a.Id);
HasRequired(a => a.City)
.WithMany(a => a.Districts)
.HasForeignKey(a => a.CityId);
ToTable("District");
}
Is it possible to map the following scenario?
Data Tables
Students
+ ID: int PK
+ Name: varchar(200)
Classes
+ ID: int PK
+ StudentID: FK
+ CourseID: FK
+ EnrollmentDate: DateTime
Courses
+ ID: int PK
+ Name: varchar(200)
I would like to map the tables to entities below.
public class Student
{
[Key]
public int ID {get;set;}
public string Name {get;set;}
public virtual ICollection<Class> Classes {get;set;}
}
public class Class
{
[Key]
public int ID {get;set;}
public Student Student {get;set;}
public DateTime EnrollmentDate {get;set;}
public string Name {get;set;} // this comes from the Courses data table
}
This should be how to establish the FK relationships you require:
public class Student
{
[Key]
public int StudentId {get;set;}
public string Name {get;set;}
}
public class Class
{
[Key]
public int ClassId {get;set;}
public DateTime EnrollmentDate {get;set;}
//foreign keys
public int CourseId {get;set;}
public string StudentId {get;set;}
//virtual constraint to link to referenced tables
public virtual Course Course {get;set;}
public virtual Student Student {get;set;}
}
public class Course
{
[Key]
public int CourseId {get;set;}
public string CourseName {get;set;}
}
I'm just starting out with Entity Framework and I seem to be misunderstanding something. Basically I've got a database already setup. Let's say the following are my tables.
**Employees**
EmployeeId
CubeId (FK to Cubes table)
NameId (FK to Name table)
**Cubes**
CubeId
CubeName
**Person**
NameId
FirstName
LastName
I want to be able to write something like this: SELECT EmployeeId, CubeId, CubeName, FirstName, LastName FROM Employees LEFT OUTER JOIN Cubes LEFT OUTER JOIN Person. So it would return all of the Employees. Basically, in EF Code First do you have to create a class for EVERY table? If not, how do you create a LEFT OUTER Join equivalent? All of the examples I've found use navigational properties to go from table to table (i.e. class to class).
Models:
public class Employee
{
[Key]
public int EmployeeId {get;set;}
public int CubeId {get;set;}
[ForeignKey("Cube")]
public int NameId {get;set;}
[ForeignKey("Name")]
public virtual Cube Cube {get;set;}
public virtual Name Name {get;set;}
}
public class Cube
{
[Key]
public int CubeId {get;set;}
public string CubeName {get;set;}
}
public class Name
{
[Key]
public int NameId {get;set}
public string FirstName {get;set;}
public string LastName {get;set;}
}
Your context:
public class YourContext:DbContext
{
public DbSet<Name> Names {get;set;}
public DbSet<Cube> Cubes {get;set;}
public DbSet<Employee> Employees {get;set;}
}
Your query:
YourContext db = new YourContext();
var query = db.Employees.Where(x => x.EmployeeId == id).Select(x => new
{
EmployeeId = x.EmployeeId,
CubeId = x.Cube.CubeId,
CubeName = x.Cube.CubeName,
FirstName = x.Name.FirstName,
LastName = x.Name.LastName
}).FirstOrDefault();
This will locate first employee that has some id (or return null if there's none), and then create a type that has all the properties you mentioned. If you need last name, you access it with:
string lastName = query.LastName;