Postgres NestJS Prisma migration - Database error code: 23502 column of relation contains null values - postgresql

I updated my Prisma ORM database model by adding two more fields 'ahash' and 'sAddress' to the 'invitation' table.
The table already contains 6 rows of data.
When I try to migrate the new changes to the Postgresql database, I get the error Database error code: 23502. ERROR: column "aHash" of relation "Invitation" contains null values.
How do I cater for the null values and migrate the model updates smoothly onto the database?
Give me a Step by step account please. I'm new to Prisma migration.
Thanks in advance!
The Prisma invitation model looks like below.
model Invitation {
id String #id #db.Uuid
workId String #db.Uuid
work Work #relation(fields: [workId], references: [id])
status RequestStatus
coId String #db.Uuid
oSignature String
note String
aHash String
sAddress String
createdAt DateTime
respondedAt DateTime
}

The problem here is that ahash and sAddress are both mandatory fields. However, they do not exist for the 6 existing rows/records in your database.
If you want to add new columns to an existing database without causing data loss you need to make sure the new columns/field are optional. This can be done in Prisma by marking the type of the field with a ?.
If you need the field to be mandatory, you could do it in three steps:
Create the new ahash and sAddress fields as optional first in your prisma schema and run a migration.
Run a script to update all existing records, so that they have a value for the ahash and sAddress fields.
Mark both fields as mandatory in your Prisma schema and run a migration.
In step 3, you will no longer get the error because none of the records contain a null value for the ahash and sAddress fields.

Related

What should I use as validation tool using NestJS and MongoDB?

Let's say, I am creating application using NestJS. I use MongoDB as a database and mongoose as ODM. So, NestJS has it's own way to validate data - ValidationPipe's. On the other side, there is mongoose built-in ways to validate data that being pushed into DB.
The question is - can I use only NestJS validation or do I need also second-check my data using mongoose validation tools?
Personally, I can't see why should I use additional layer of validation if I already have NestJS validation. But maybe there is best-practice or something?
Each database validates input data and emits an error if found. However, you must take into account your schema file. For instance, if you are using Prisma(It doesn't actually matter) and you have a User model like below
model User {
id String #id #default(auto()) #map("_id") #db.ObjectId
email String #unique
password String
name String
image String?
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##map("user")
}
As you can see there is only one optional property "image". Whether you pass a value for image property or not, the database will insert the data as a row. On the other hand, the properties without "?" mark at the end of the type, will not be stored if you don't pass them and emit an error.
Therefore, if you modeled schema according to your business logic, you don't need to validate twice but only add an exception handling like the one below.
const user = await this.usersService.findOne('id...')
.catch((e) => new NotFoundException({ message: 'No user found.' }))

Does Prisma support composite keys with one of the attribute being NULL for PostgreSQL?

In PostgreSQL you can make a table with 2 columns as the composite key of that table, with one of them being NULL-able. I was just wondering how I can achieve this with Prisma.
In the current version of Prisma that I have (3.14.0), Prisma does allow composite key using ##id([column1,column2]), but only if those two columns are mandatory.
No, Prisma doesn't support composite keys with optional columns. ID Definitions are required.
Example:
This would work
model Post {
title String
content String
##id([title, content])
}
But this wouldn't as column content is defined as optional
model Post {
title String
content String?
##id([title, content])
}
You can create a Feature Request here to support allowing nullable columns in composite id.

Entity Framework writing NULL to the DB

I am using EF v 6.2.0. My issue is similar to the SOF question - Entity Framework not claiming datetime.now is null. However, the proposed solution does not work for me.
buildDetail.BuildTime = epoch.AddMilliseconds(Double.Parse(buildTime)).ToLocalTime();
:
:
: // Other properties.
ps.dbEntities.BuildDetails.Add(buildDetailT);
ps.dbEntities.SaveChanges();
On the SaveChanges() line, I get an exception
Inner Exception 2:
SqlException: Cannot insert the value NULL into column 'BuildTime', table 'BuildDetailsDB.dbo.BuildDetails'; column does not allow nulls. INSERT fails.
The statement has been terminated.
The buildDetail.BuildTime property, when I hover over in debug, shows the value as {3/29/2018 9:17:22 AM} i.e. current date time. The datatype in Sql Server is datetime and the model I have generated from the database shows that this field has a return value of System.DateTime. So, I am frustrated as to why EF is trying to insert a null. In fact, if I allow nulls for this columns in the DB, that is exactly what it writes in that column - NULL.
The field in question is neither marked as Identity (both in model and db) nor Calculated. I have also updated the model from the Database and they are in sync.
Note: I have tried the DateTime.ParseExact and even an DateTime object converted from a string in the exact same format as expected in SQL Server i.e. "yyyy-MM-DD HH:MM:SS.FFF" with no luck and the same exception. eg.
buildDetailT.BuildTime = DateTime.Parse("2018-11-25 08:25:26.0000");

JPA Relation or Secondary Table

I am reengineering one of my project with JPA which was initially on iBatis.
public class Entity{
//ids and other stuff
String locale;
String text;
}
I was storing locale and text into separate table, which can be achieved via secondary table in JPA.
I am not able to create secondary table with its own ids besides Join
id?
how can I achieve it? If possible then it raises the following
question:
how would I retrieve it back if I create an entity object with locale set to user settings
See,
http://en.wikibooks.org/wiki/Java_Persistence/Tables#Multiple_tables
Otherwise include your exact schema and model and issue.

How to manage GetDate() with Entity Framework

I have a column like this in 1 of my database tables
DateCreated, datetime, default(GetDate()), not null
I am trying to use the Entity Framework to do an insert on this table like this...
PlaygroundEntities context = new PlaygroundEntities();
Person p = new Person
{
Status = PersonStatus.Alive,
BirthDate = new DateTime(1982,3,18),
Name = "Joe Smith"
};
context.AddToPeople(p);
context.SaveChanges();
When i run this code i get the following error
The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated.
So i tried setting the StoreGeneratedPattern to computed... same thing, then identity... same thing. Any ideas?
You have to manually edit the edmx xml and set your SSDL StoreGeneratedPattern attributes to identity or computed. But whenever you update your edmx via the designer your changes will get overwritten.
This is a known issue. Please see the following links for more details:
Microsoft Connect Ticket
Using a GUID as an EntityKey in Entity Framework 4
I had the same problem! For me it works like this:
Database MS SQL Server express:
[RowTime] [datetime2](7) NOT NULL
ALTER TABLE [dbo].[Table_1] ADD CONSTRAINT [DF_Table_1_RowTime] DEFAULT (getdate()) FOR [RowTime]
GO
Then I import the table from database to my Entities model.
Entities will not realise the default value!
So, you have to set the StoreGeneratedPattern of the column to Computed.
Then Entities will not put there any default value any more.
Combination of:
datetime2,
NOT NULL,
StoreGeneratedPattern=Computed
Works for me!
Changing type of DateCreated to datetime2 might solve the problem.
datetime 2007-05-08 12:35:29.123
datetime2 2007-05-08 12:35:29. 12345
Ref: http://technet.microsoft.com/en-us/library/bb677335.aspx67
Here is a working workaround:
1) Change the column to datetime2 as mentioned elsewhere. This fixes the conversion error.
2) Add a trigger that sets DateCreated to getdate();
CREATE TRIGGER [TR_AS_ChangeTime] ON [AS_ApplicationSession]
AFTER INSERT,UPDATE AS
BEGIN
SET NOCOUNT ON;
UPDATE AS_ApplicationSession
SET AS_ChangeTime = getdate()
WHERE AS_Id IN(SELECT AS_ID FROM INSERTED)
END
3) If neccessary, set
p.DateCreated = DateTime.MinValue;
just to initialize it.
4) If you need the DateCreated from the database, add
context.Refresh(System.Data.Objects.RefreshMode.StoreWins, p);
just after
context.SaveChanges();
Focusing on the fact that I do not want change the database, since it is an application problem and I expect them to solve this problem one day, my solution (that is totally possible in my case) is to create a partial class of the model to correct the problem on constructor:
public partial class Log
{
public Log()
{
this.Date = DateTime.Now;
}
}
This works for me because:
I create the model on the moment I send it to database.
I use CLOUD for these services, the datetime must be the same in both Application and Database servers!
Don't forget that the namespace needs to match the Model namespace or partial should not list properties (and should no be partial as well ;])!