Prisma Schema not updating properly after adding new fields - reactjs

As the title states, I am using Prisma 2 in a Next JS app. I have a very simple schema:
model User {
id Int #id #default(autoincrement())
firstName String
middleName String?
firstLastname String
secondLastname String?
email String
role String
group Group? #relation(fields: [groupId], references: [id])
groupId Int?
activity Activity? #relation(fields: [activityId], references: [id])
activityId Int?
createdOn DateTime #default(now())
updatedOn DateTime #default(now())
}
model JobTitle {
id Int #id #default(autoincrement())
name String
createdOn DateTime #default(now())
updatedOn DateTime #default(now())
}
model Group {
id Int #id #default(autoincrement())
name String
users User[]
createdOn DateTime #default(now())
updatedOn DateTime #default(now())
}
model Activity {
id Int #id #default(autoincrement())
name String
users User[]
}
I added the email field on the User model and changed the groupId and activityId fields to be optional. I also changed the type for the role field to String. I run prisma migrate and prisma up to create a new migration and sync the database (using a remote heroku postgresql database as my datasource) and everything runs fine. No errors. However, when I try to create a new User, I get the following error:
An error ocurred: PrismaClientValidationError:
Invalid `prisma.user.create()` invocation:
{
data: {
firstName: 'John',
middleName: 'Edgar',
firstLastname: 'Doe',
secondLastname: 'Smith',
email: 'john#email.com',
~~~~~
role: 'ADMIN',
~~~~~~~
+ group: {
+ create?: GroupCreateWithoutUsersInput,
+ connect?: GroupWhereUniqueInput,
+ connectOrCreate?: GroupCreateOrConnectWithoutusersInput
+ },
+ activity: {
+ create?: ActivityCreateWithoutUsersInput,
+ connect?: ActivityWhereUniqueInput,
+ connectOrCreate?: ActivityCreateOrConnectWithoutusersInput
+ },
? createdOn?: DateTime,
? updatedOn?: DateTime
}
}
Unknown arg `email` in data.email for type UserCreateInput. Did you mean `role`?
Argument role: Got invalid value 'ADMIN' on prisma.createOneUser. Provided String, expected RoleCreateOneWithoutUserInput:
type RoleCreateOneWithoutUserInput {
create?: RoleCreateWithoutUserInput
connect?: RoleWhereUniqueInput
connectOrCreate?: RoleCreateOrConnectWithoutUserInput
}
Argument group for data.group is missing.
Argument activity for data.activity is missing.
Note: Lines with + are required, lines with ? are optional.
at Document.validate (C:\Users\user\Documents\projects\employee-evaluation-app\employee-evaluation-app\node_modules\#prisma\client\runtime\index.js:77411:19)
at NewPrismaClient._executeRequest (C:\Users\user\Documents\projects\employee-evaluation-app\employee-evaluation-app\node_modules\#prisma\client\runtime\index.js:79063:17)
at C:\Users\user\Documents\projects\employee-evaluation-app\employee-evaluation-app\node_modules\#prisma\client\runtime\index.js:79000:52
at AsyncResource.runInAsyncScope (node:async_hooks:197:9)
at NewPrismaClient._request (C:\Users\user\Documents\projects\employee-evaluation-app\employee-evaluation-app\node_modules\#prisma\client\runtime\index.js:79000:25)
at Object.then (C:\Users\user\Documents\projects\employee-evaluation-app\employee-evaluation-app\node_modules\#prisma\client\runtime\index.js:79117:39)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:93:5) {
clientVersion: '2.12.0'
}
It seems like the operation is using a previous version of the schema seeing as how it says that the email field does not exist and the role field is not a String type. Also, the groupId and activityId fields are still shown as required. I don't know if there some sort of cache. I already tried deleting all migrations and redeploying everything from scratch. I even deleted the database in heroku and started fresh but I am still getting the same error.

Running an npm install (no need to remove node_modules) and then re generating the Prisma types can fix this issue.
Since npm i removes the old Prisma generations, npx prisma generate will have to generate new ones from your schema.prisma.
Ryan's comment about adding a post install script for Prisma is a nice QOL improvement, too.
Edit:
Closing and opening your editor (in my case VsCode) will fix the red line errors. I think the extension struggles to update itself with the new changes. It's a pain but does work if the other solutions don't.

To fix this in VS Code after running npx prisma migrate dev or npx prisma db push, you can try one of these following methods:
Reloading VS Code (Just simply close and reopen VS Code)
Restart VS Code language server (Hit Ctrl + Shift + P, then search for Restart TS server)
Two method above will take a few minute to get VS Code working again, so I recommend this way:
Open file node_modules\.prisma\client\index.d.ts to get VS Code re-indexing this file (because it's too large, VS Code does not reload this file ), then it'll work in few seconds.

I had something closer to this problem. In my case, I updated my Schema.prisma with new models but anytime I run "prisma migrate dev", it wouldn't update. It turns out the error was because I didn't hit "Save" after making the changes before running the code. (In my defence, I thought auto-save took care of that but no).
Try saving the file again before you run "prisma migrate dev".

you can update it in migrations.sql file and run prisma migrate dev. that'll work.

Related

Cannot insert the value NULL into column 'id', table 'XXX'; column does not allow nulls

I have the below model:
class Loan(models.Model):
id = models.BigAutoField(primary_key=True)
date = models.DateField(default=timezone.now)
description = models.TextField(max_length=255)
When I try to save date and description I get the above error
below is my admin.py file:
#admin.register(Loan)
class LoanAdmin(admin.ModelAdmin):
pass
and below is my table created through migrations:
Django 3.2.6.
How can I solve this?
SQL Server version is Microsoft SQL Server 2019 (RTM-CU8-GDR)
I tried :
class Loan(models.Model):
date = models.DateField(default=timezone.now)
description = models.TextField(max_length=255)
The solution that worked to this problem was to delete all migrations and create new migrations.
you don't need to add id column specifically. Django creates id column itself.
class Loan(models.Model):
date = models.DateField(default=timezone.now)
description = models.TextField(max_length=255)
This should work.
Also, if you want to add custom id column check this

EF Core ExecuteSqlCommandAsync : Conversion failed when converting the nvarchar value '1,2' to data type int

I am running executing raw sql to delete some records that I added for the test. If I run the same query in management studio it works fine but when I run that query EF Core 2.0 it throws below error
System.Data.SqlClient.SqlException: 'Conversion failed when converting the nvarchar value '1,2' to data type int.'
Code
var idList = await Context.User.ToListAsync();
var ids = string.Join(",",idList.Select(x=>x.Id));
await _context.Database.ExecuteSqlCommandAsync($"Delete from User where Id in ({ids}) and RoleId = {contact.RoleId}");
Query executing
Delete from sale.WatchList where OfferId in (1,2) and UserId = 9
Could anybody please advise on what wrong with the above code.
Thanks
EF Core will transform interpolated strings into queries with parameters to create reusable queries and protect against SQL Injection vulnerabilities. See: Raw SQL Queries - EF Core - Passing Parameters
So
$"Delete from User where Id in ({ids}) and RoleId = {contact.RoleId}"
is transformed into
Delete from User where Id in (#ids) and RoleId = #RoleId
With SqlParameters bound.
If that's not what you want, just build the SQL Query on a previous line.
This will not work. You have to write dynamic query. Please try like below one
var idList = await _dataContext.User.ToListAsync();
var ids = string.Join(",", idList.Select(x => x.Id));
await _dataContext.Database.ExecuteSqlCommandAsync($"execute('Delete from User where Id in ({ids}) and RoleId = {contact.RoleId}')");
although accepted answer does work, it creates lot of warnings so for now I am using what #Abu Zafor suggested with small change/fix
await _dataContext.Database.ExecuteSqlCommandAsync($"execute('Delete from User where Id in ({ids}) and RoleId = {contact.RoleId}')",ids,contact.RoleId);

IdentityServer4 Sample with ASP Identity with real SQL Server

I have been struggling to get the final SAMPLE (ASP.Net, EF Core, SQL) to work against a real SQL Server. Every sample I can find does not use real SQL they always opt for in-memory data store
I changed the connection string
"Data Source=.;Initial Catalog=IS4;Integrated Security=True;"
and ran
dotnet ef database update -c ApplicationDbContext
This created me a SQL database with 25 tables.
I tweaked Startup.cs to change
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
and b.UseSqlite to b.UseSqlServer
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
// options.TokenCleanupInterval = 15;
});
I ran the server with "/seed" on the command line but the Seed functionality doesn't work
First it complains CLIENT can't have a NULL ID when it calls SaveChanges(). If I change the code to add the ID
if (!context.Clients.Any())
{
Console.WriteLine("Clients being populated");
int i = 1;
foreach (var client in Config.GetClients().ToList())
{
var x = client.ToEntity();
x.Id = i++;
context.Clients.Add(x);
}
context.SaveChanges();
}
else
{
Console.WriteLine("Clients already populated");
}
I then get
"Cannot insert the value NULL into column 'Id', table 'IS4.dbo.ClientGrantTypes".
When I watch the video's it says it can be migrated from SQLite to full SQL simply by changing the connection string which is obviously not true, given all the other changes I have done, so I must be doing (or missing) something else.
Any thoughts?
Could it be that all the tables with an "Id INT" column should all be IDENTITY columns and they are not!
I checked the migrations code and it has
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ApiResources",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Description = table.Column<string>(maxLength: 1000, nullable: true),
DisplayName = table.Column<string>(maxLength: 200, nullable: true),
I am guessing
.Annotation("Sqlite:Autoincrement", true),
doesn't work with full SQL and therefore all the tables need identity properties setting.
Interestingly if you run the other template to add the AdminUI
dotnet new is4admin
It seems to add a couple of SQL scripts
CREATE TABLE "Clients" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Clients" PRIMARY KEY AUTOINCREMENT,
"AbsoluteRefreshTokenLifetime" INTEGER NOT NULL,
"AccessTokenLifetime" INTEGER NOT NULL,
which does make them identity columns.
I was faced with this issue today and did a couple of searches online and stumbled upon this https://entityframeworkcore.com/knowledge-base/46587067/ef-core---do-sqlserver-migrations-apply-to-sqlite-
The link pointed out to switch the annotation portion in the migration class UP method after
Id = table.Column(nullable: false)
from
.Annotation("Sqlite:Autoincrement", true);
to
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
And you will need to import
using Microsoft.EntityFrameworkCore.Metadata;
Then you build, and the migration will be successful.
To resolve this particular issue I used SSMS.
right click on table
select script to drop and create
add IDENTITY after the NOT NULL
Execute
However you are correct, it is using sqlite annotations in the sql file and in the migrations.
To fully resolve this issue, you need to create an implementation of all 3 necessary database contexts: identity, persisted grant, and configuration.
That requires an implementation of design time factories for each of those contexts as well.
Then you can run add-migration in the package manager console for each of those contexts, and then run update database, or run the application with the migrate function when seeding.
So to recap:
Create implementations for the 3 db contexts
Create Design time factory implementations for those db contexts
Add the migrations
Update the database with those migrations

How to make the 'public' schema default in a Scala Play project that uses PostgreSQL?

I am not sure if my issue connecting to the Scala Play 2.5.x Framework or to PostgreSQL so I am going to describe my setup.
I am using the Play 2.5.6 with Scala and PostgreSQL 9.5.4-2 from the BigSQL Sandboxes. I use the Play Framework default evolution package to manage the DB versions.
I created a new database in BigSQL Sandbox's PGSQL and PGSQL created a default schema called public. I use this schema for development.
I would like to create a table with the following script (1.sql in DB evolution config):
# Initialize the database
# --- !Ups
CREATE TABLE user (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
creation_date TIMESTAMP NOT NULL
);
# --- !Downs
DROP TABLE user;
Besides that I would like to read the table with a code like this:
val resultSet = statement.executeQuery("SELECT id, name, email FROM public.user WHERE id=" + id.toString)
I got an error if I would like to execute any of the mentioned code or even if I use the CREATE TABLE... code in pgadmin. The issue is with the user table name. If I prefix it with public (i.e. public.user) everything works fine.
My questions are:
Is it normal to prefix the table name with the schema name every time? It seems to odd to me.
How can I make the public schema a default option so I do not have to qualify the table name? (e.g. CREATE TABLE user (...); will not throw an error)
I tried the following:
I set the search_path for my user: ALTER USER my_user SET search_path to public;
I set the search_path for my database: ALTER database "my_database" SET search_path TO my_schema;
search_path correctly shows this: "$user",public
I got the following errors:
In Play: p.a.d.e.DefaultEvolutionsApi - ERROR: syntax error at or near "user"
In pgadmin:
ERROR: syntax error at or near "user"
LINE 1: CREATE TABLE user (
********** Error **********
ERROR: syntax error at or near "user"
SQL state: 42601
Character: 14
This has nothing to do with the default schema. user is a reserved word.
You need to use double quotes to be able to create such a table:
CREATE TABLE "user" (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
creation_date TIMESTAMP NOT NULL
);
But I strongly recommend not doing that. Find a different name that does not require a quoted identifier.

SQL Server CE database and ADO.Net Entity Framework - data not saving

I have a SQL Server CE database file and I have ADO.NET Entity Framework object named History. I perform the following to get the latest ID:
var historyid = (from id in db.Histories // Get the current highest history Id
select (Int32?)(id.Id)).Max();
HistoryID = Convert.ToInt32(historyid);
if (HistoryID == 0) // No current record exists
{
HistoryID = 1; // Set the starter history Id
}
(Not the best way, but it is just to test).
This works well and returns the correct value (If I manually enter an ID of 1, it returns 1, same with 2 etc..)
The issue is with the following code:
History history = new History();
history.Id = 1;
history.SoftwareInstalled = "test";
db.AddToHistories(history);
db.SaveChanges();
The above works and runs through fine, but the changes are not saved to the database! Why is this?
Here is my db variable: dbDeSluggerEntities db = new dbDeSluggerEntities();
Thanks.
Edit: Here is an update: I noticed when I run the program and debug it, it shows that a history has been created and inserted and also gives an error of the primary key already existing, this happens each time I run the application (over and over). However, when I go to server explorer and right click the db and select 'Show Table Data' it shows no data.. When the program is run again, there is no primary key error or history's showing in the debug!
I was having exactly the same problem. By default the database is copied into your bin folder when you run the app and that is used.
My solution was to go into the properties of the db and set it to never copy and to put a full file path to the database in the connection string in the apps config file.

Resources