Hello (i'm french sorry for my bad english!!)
i want to create database for a project with prisma schema, with a table of users, an other for the comments that users written, and a finally for the likes (each user can like each comment).
so my schema is :
model User {
idUser Int #id #default(autoincrement())
pseudo String #unique #db.VarChar(100)
password String #db.VarChar(255)
role Role #default(USER)
nom String #db.VarChar(100)
prenom String #db.VarChar(100)
email String #unique #db.VarChar(100)
info_email String #default("null") #db.VarChar(200)
writtenComments Comment[]
likes Like []
##unique([idUser, pseudo])
}
model Comment {
idComment Int #id #default(autoincrement())
title String #db.VarChar(100)
comment String #db.VarChar(200)
author User #relation(fields: [authorId, authorPseudo], references: [idUser, pseudo], onDelete: Cascade)
authorId Int
authorPseudo String
likes Like []
##unique([idComment, title, authorPseudo, authorId])
}
model Like {
idLikes Int #id #default(autoincrement())
Liker User #relation( fields: [LikerId, LikerPseudo], references: [idUser, pseudo], onDelete: Cascade)
LikerId Int
LikerPseudo String
Commented Comment #relation(fields: [commentId, commentTitle, commentAuthor, commentAuthorId ], references: [idComment, title, authorPseudo,authorId], onDelete: Cascade)
commentId Int
commentTitle String
commentAuthor String
commentAuthorId Int
##unique([commentId, LikerId])
}
enum Role {
USER
ADMIN
}
the problem :
on like is the combination of one comment and one user, but the unique constraint failed. And in my database i can have two id like for a comment liked by the same user !! So one user can like any times he want a same comment. And when i add the unique constraint in the Like table, a message of failed appeared. :/
Error: P2002
Unique constraint failed on the constraint: `Like_commentId_LikerId_key
thank for your help i hope your suggestion can help me =)
have a good day !
sorry
the problem was that my table wasn't purged before I pushed my schema. The constraint is ok =)
Related
I am using GORM in my Go Gin API and want to create an association between my User and the Role table. So far, I have simply followed the documentation, but I am running into a problem.
Here are my used models:
type User struct {
gorm.Model
FirstName string
LastName string
Email string `gorm:"unique"`
Password []byte
Roles []Role `gorm:"many2many:user_roles"`
}
type Role struct {
gorm.Model
Name string
}
While I'm still developing, I want to write data directly to the database when I start the API. For this I create the following:
Db.Create(&User{
FirstName:"Jon",
LastName:"Doe",
Email: "jon#doe.local",
Password: encoded,
Roles: []Role{
{Name: "admin"},
{Name: "service"},
},
})
Db.Create(&User{
FirstName:"Jon",
LastName:"Doe",
Email: "jon2#doe.local",
Password: encoded,
Roles: []Role{
{Name: "admin"},
{Name: "service"},
},})
This way I want each name to appear only once in the role table. The corresponding ID should be used in the automatically created user_roles table each time such an entry is created.
What happens, however, is this:
Roles Table:
id
name
1
admin
2
service
3
admin
4
service
User_Role Table:
user_id
role_id
1
1
1
2
2
3
2
4
I have read through https://gorm.io/docs/associations.html and tried Omit but nothing worked yet.
I hope someone has an idea or already solved the same problem. Thanks a lot!
Edit:
When trying "try sending just the role IDs instead of role names" i do it like this:
Db.Create(&User{
FirstName:"Jon",
LastName:"Doe",
Email: "jon2#doe.local",
Password: encoded,
Roles: []Role{
{ID: 1},
{ID: 2},
},})
This gives me the error
cannot use promoted field Model.ID in struct literal of type Role
2. Edit
The ID needs to be listed seperated in the Role model, it does not work just with the gorm.Model
type Role struct {
gorm.Model
ID uint `gorm:"primarykey"`
Name string
}
I have situation like this: in LearningStatuses table I have a composite primary key, made up of CourseCode and UserID.
CourseCode and UserID are also the PK of Course and ApplicationUser tables respectively.
The LearningStatuses table is basically working as a enroll table.
So if a user enroll in a course, his user ID and Course Code will be stored in this table.
Now I want to fetch all the enrolled courses of a particular user in his dashboard.
Firstly I'm looking for the courseCode that is there in the learningSatatuses table with his user ID, and storing it in a list of int.
Now I want the list of courses from the database, of those IDs as an IEnumerable to iterate over them in the view.
public ActionResult Dashboard()
{
string currentUserID = User.Identity.GetUserId();
List<int> CoursesEnrolled = db.LearningStatuses
.Where(l => l.UserID == currentUserID)
.Select(l => l.CourseCode)
.ToList();
List<Course> CoursesEnrolledCourse = new List<Course>();
foreach (int item in CoursesEnrolled)
{
Course c = (Course)db.Courses.Where(c => c.CourseCode == item);
CoursesEnrolledCourse.Add(c);
}
return View();
}
During the 2nd step, I find myself unable to cast this IQueryable to a list anymore.
I've tried few other approaches too. but at the end of it I'm not able to get the desired IEnumerable of course objects for a particular user.
N.B: I have an Identity Framework user table. So my UserID is an alias of ApplicationUserID, that's a string.
What is the right approach to get the expected result.
I want to suppress the CosmosDB information in the following resultset, how can that be done?
{
"id": null,
"_rid": null,
"_self": null,
"_ts": 0,
"_etag": null,
"topLevelCategory": "Shorts,Skirt"
},
This is an extract of course but I dont want to show the ID etc as they serve no purpose in this result but I cannot figure out how to suppress that info.
I expect the following
{
"topLevelCategory": "Shorts,Skirt"
},
Query looks as follows
$"SELECT DISTINCT locales.categories[0] AS topLevelCategory " +
$"FROM c JOIN locales in c.locales " +
$"WHERE locales.country = '{apiInputObject.Locale}' " +
$"AND locales.language = '{apiInputObject.Language}'";
Interesting thing is if I cast the result as a JOBJECT I dont get the system data, I only get it if I createDOcumentQuery as DOcument, so a workaround would be as follows
IQueryable<JObject> queryResultSet = client.CreateDocumentQuery<JObject>(UriFactory.CreateDocumentCollectionUri(databaseName, databaseCollection), parsedQueryObject.SqlStatement, queryOptions);
but that has other async issues but the above does not show the system generate IDs but the below one does
var query = client.CreateDocumentQuery<Document>(UriFactory.CreateDocumentCollectionUri(databaseName, databaseCollection), parsedQueryObject.SqlStatement, queryOptions).AsDocumentQuery();
var result = await query.ExecuteNextAsync<Document>();
These are system-generated properties of items in Cosmos DB.
Surely,you could filter them in the sql: select c.topLevelCategory from c, don't mention them or use select * from c. Filtering in sql is the best method, better than secondary processing of result set.
Update Answer:
Your situation is executing the exact same query the JOBJECT does not show the system data but the Document does.
My explanation as below:
Document Class is a self-contained base class of Document DB .NET package.It has these generate properties:
SDK will try to map the result data one by one to the entity class which you defined in the CreateDocumentQuery<T>.
So actually,you already find the solution.You could define your custom pojo to receive the result data. Just contain the properties you want in that pojo inside like:
class Pojo : Document
{
public string id { get; set; }
public string name { get; set; }
}
That would have both business implications and no more redundant fields.Hope i'm clear on this.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Suppose I have the following models in the ASP.NET MVC code first approach :
public class City
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Restaurant
{
public int Id { get; set; }
public int CityId { get; set; }
public virtual City City { get; set; }
}
That means I have a table called City Which has :
Id ( Primary key and it's an identity field)
Name ( varchar )
And another table called Restaurant Which has :
Id ( Primary key and it's an identity field)
CityId( Foreign key refrencing Id in City table and no cascade on delete )
Now because my city data is fixed and not changing much i use the seed method to populate it like:
context.Cities.AddOrUpdate(x => x.Name,
new City() { Name = "Springfield" },
new City() { Name = "Franklin" },
new City() { Name = "Greenville" }
);
Please notice I'm not assigning any ID because City Id is an identity field and auto-increments.
One Scenario:
A scenario which i fear is this:
Assume there are some restaurants in the Restaurant table referencing these cities. Now as time goes by, for some unknown reasons Franklin which had the Id of 2 gets deleted from the City table. So when you notice what happened, you insert Franklin as a city again but this time it's Id has changed. So what happens to those restaurants which were already referencing "Franklin" as their city?
Should I make City Id not an identity primary key but just an integer primary key and assign City Ids myself?
If I enable cascade delete on the foreign key, then i will lose the records referencing the deleted city and I don't want that. I want to keep them until I figure out what happened to the deleted city and fix the issue.
Question
So with this information, in my case, is it a good practice to make a foreign key from an identity field? What's the best way to handle this situation?
Primary and Foreign keys ensure something called "referential integrity." Just like it sounds, they ensure the integrity of the references contained in the data. If you have restaurants in a city you should not be allowed to delete that city because it would destroy the integrity of the references (i.e. you now have orphaned restaurants). The alternative would be to allow the database to delete the restaurants if you delete the city. Either of those scenarios (blocking the deletion or cascading the deletion) can be accomplished with a foreign key.
Whenever the data in one table is dependent on the data in another table for its existence you should create a foreign key to ensure you don't end up with data corruption. The fact that it is an identity column is irrelevant.
Your database is the last line of defense against corrupt data. You want to ensure that those "unknown reasons" that cause the row to be deleted are simply not allowed. It's easier to prevent the problem in the first place than to try to fix the data after it's corrupt.
You woun't be able to delete any city from the table as long as there are restaurants referencing it.
That will be enforced by the foreign key. (You can customize this when creating the foreign key: ON DELETE CASCADE, ON DELETE SET NULL...)
So the answer is yes: it is a good practice.
First of all, let's define a few tables:
Users table will store information about a user:
Users
- UserID (int, PK)
- ...
UserTasks is a table that stores a task associated with a user:
UserTasks
- userID (int, FK to Users table)
- taskName (varchar)
When I generate the UserTasks table using the ADO Entity Framework, I'll get a class that looks like this:
UserTasks
- taskName (string)
- Users (collection of Users objects)
Note: There's no userID that is generated in the UserTasks table. So let's assume now that I need to insert a new user task... how do I do it? I don't have access to the userID FK field, so my only option is to do a lookup and populate a Users object, then pass that to my task object, like this:
//get the user we are interested in
var user = (from u in context.Users
where u.userID == 2
select u).FirstOrDefault();
//create the new task
UserTasks newTask = new UserTasks();
newTask.taskName = "New Task";
newTask.User = user;
The problem with the above is that I'm doing an extra and needless database call to populate my user object. Is there anyway to somehow create a new mapping to my userID field and still keep the User object?
Thanks
--Ryan
Not now, but maybe in the next version.