Related
I am using .net5.0 EF
I have a class AppUser and extend it to IdentityUser
public class AppUser : IdentityUser
{
}
I am using command to generate EF migrations
dotnet ef migrations add "myMessage" -p Persistence -s API
I have deleted all previous migration files, so this is a new migration.
I also deleted the DB as well.
I am ablle to successfullly generate new db in sqlLite.
But when I am trying to do the same in production / testing server SQL, it gives me below issue.
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
Failed executing DbCommand (38ms) [Parameters=[], CommandType='Text', CommandTimeout='60']
CREATE TABLE [AspNetRoles] (
[Id] TEXT NOT NULL,
[Name] TEXT NULL,
[NormalizedName] TEXT NULL,
[ConcurrencyStamp] TEXT NULL,
CONSTRAINT [PK_AspNetRoles] PRIMARY KEY ([Id])
);
fail: API.Program[0]
An error occured during migration
Microsoft.Data.SqlClient.SqlException (0x80131904): Column 'Id' in table 'AspNetRoles' is of a type that is invalid for use as a key column in an index.
Could not create constraint or index. See previous errors.
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at Microsoft.Data.SqlClient.SqlCommand.InternalEndExecuteNonQuery(IAsyncResult asyncResult, Boolean isInternal, String endMethod)
at Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(IAsyncResult asyncResult)
at Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryAsync(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
The error relates to something in AspNetRoles table
But I am not even touching anything in this AspNetRoles table.
Can anyone help me, please?
Thanks
Autogenerated migration code below
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
Name = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
This error is due to the fact that the migration code EF generates for SQLite is different from the migration code generated for SQL Server. Check your builder configuration logic (Program.cs or Startup.cs) and make sure that you are specifying the correct database options when invoking AddDbContext. When using a SQL Server database you'll need to specify that as follows:
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connection));
For comparison to your SQLite migration code, this is what the SQL Server migration code looks like for the default AspNetRoles table:
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
I think for sql server's text type index is maximum length required. using FluentApi you can set maxLength for Id.
public class AppDbContext
{
....
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Role>().Property(x => x.Id).HasMaxLength(250);
base.OnModelCreating(builder);
}
}
and re-migration created required.
The migrations created for SQLite is not useable for Sql Server, so you have to create new migrations like this:
step 1: Change "UseSqlite" to "UseSqlServer"
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
To
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
step 2: Remove all migrations (by deleting the "Migrations" folder)
step 3: add a new migration, then update the database
dotnet ef migrations add "CreateIdentitySchema"
dotnet ef database update
I'm following the EF Core with MVC tutorial on learn.microsoft.com.
I have the following migration:
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace ContosoUniversity.Migrations
{
public partial class ComplexDataModel : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "EnrollmentDate",
table: "Student",
type: "timestamp with time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone"
);
migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Course",
type: "character varying(50)",
maxLength: 50,
nullable: false,
oldClrType: typeof(string),
oldType: "text"
);
// migrationBuilder.AddColumn<int>(
// name: "DepartmentID",
// table: "Course",
// type: "integer",
// nullable: false,
// defaultValue: 0
// );
migrationBuilder.CreateTable(
name: "Instructor",
columns: table =>
new
{
ID = table
.Column<int>(type: "integer", nullable: false)
.Annotation(
"Npgsql:ValueGenerationStrategy",
NpgsqlValueGenerationStrategy.IdentityByDefaultColumn
),
LastName = table.Column<string>(
type: "character varying(50)",
maxLength: 50,
nullable: false
),
FirstName = table.Column<string>(
type: "character varying(50)",
maxLength: 50,
nullable: false
),
HireDate = table.Column<DateTime>(
type: "timestamp with time zone",
nullable: true
)
},
constraints: table => table.PrimaryKey("PK_Instructor", x => x.ID)
);
migrationBuilder.CreateTable(
name: "CourseAssignment",
columns: table =>
new
{
InstructorID = table.Column<int>(type: "integer", nullable: false),
CourseID = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey(
"PK_CourseAssignment",
x => new { x.CourseID, x.InstructorID }
);
table.ForeignKey(
name: "FK_CourseAssignment_Course_CourseID",
column: x => x.CourseID,
principalTable: "Course",
principalColumn: "CourseID",
onDelete: ReferentialAction.Cascade
);
table.ForeignKey(
name: "FK_CourseAssignment_Instructor_InstructorID",
column: x => x.InstructorID,
principalTable: "Instructor",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade
);
}
);
migrationBuilder.CreateTable(
name: "Department",
columns: table =>
new
{
DepartmentID = table
.Column<int>(type: "integer", nullable: false)
.Annotation(
"Npgsql:ValueGenerationStrategy",
NpgsqlValueGenerationStrategy.IdentityByDefaultColumn
),
Name = table.Column<string>(
type: "character varying(50)",
maxLength: 50,
nullable: false
),
Budget = table.Column<decimal>(type: "money", nullable: false),
StartDate = table.Column<DateTime>(
type: "timestamp with time zone",
nullable: false
),
InstructorID = table.Column<int>(type: "integer", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Department", x => x.DepartmentID);
table.ForeignKey(
name: "FK_Department_Instructor_InstructorID",
column: x => x.InstructorID,
principalTable: "Instructor",
principalColumn: "ID"
);
}
);
migrationBuilder.Sql(
"INSERT INTO Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())"
);
// Default value for FK points to department created above, with
// defaultValue changed to 1 in following AddColumn statement.
migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
nullable: false,
defaultValue: 1
);
migrationBuilder.CreateTable(
name: "OfficeAssignment",
columns: table =>
new
{
InstructorID = table.Column<int>(type: "integer", nullable: false),
Location = table.Column<string>(
type: "character varying(50)",
maxLength: 50,
nullable: false
)
},
constraints: table =>
{
table.PrimaryKey("PK_OfficeAssignment", x => x.InstructorID);
table.ForeignKey(
name: "FK_OfficeAssignment_Instructor_InstructorID",
column: x => x.InstructorID,
principalTable: "Instructor",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade
);
}
);
migrationBuilder.CreateIndex(
name: "IX_Course_DepartmentID",
table: "Course",
column: "DepartmentID"
);
migrationBuilder.CreateIndex(
name: "IX_CourseAssignment_InstructorID",
table: "CourseAssignment",
column: "InstructorID"
);
migrationBuilder.CreateIndex(
name: "IX_Department_InstructorID",
table: "Department",
column: "InstructorID"
);
migrationBuilder.AddForeignKey(
name: "FK_Course_Department_DepartmentID",
table: "Course",
column: "DepartmentID",
principalTable: "Department",
principalColumn: "DepartmentID",
onDelete: ReferentialAction.Cascade
);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Course_Department_DepartmentID",
table: "Course"
);
migrationBuilder.DropTable(name: "CourseAssignment");
migrationBuilder.DropTable(name: "Department");
migrationBuilder.DropTable(name: "OfficeAssignment");
migrationBuilder.DropTable(name: "Instructor");
migrationBuilder.DropIndex(name: "IX_Course_DepartmentID", table: "Course");
migrationBuilder.DropColumn(name: "DepartmentID", table: "Course");
migrationBuilder.AlterColumn<DateTime>(
name: "EnrollmentDate",
table: "Student",
type: "timestamp with time zone",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone",
oldNullable: true
);
migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Course",
type: "text",
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(50)",
oldMaxLength: 50
);
}
}
}
And upon trying to execute it (database deleted beforehand so it is re-created) i get the following PostgreSQL error/.NET stacktrace:
dotnet ef database update
Build started...
Build succeeded.
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 6.0.2 initialized 'SchoolContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL:6.0.2+854d2438884c0bf3a4ba8ccde2c47f7ba1ea3a4c' with options: None
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (26,524ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE DATABASE contoso_university;
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (188ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (39ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace WHERE c.relname='__EFMigrationsHistory');
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT "MigrationId", "ProductVersion"
FROM "__EFMigrationsHistory"
ORDER BY "MigrationId";
info: Microsoft.EntityFrameworkCore.Migrations[20402]
Applying migration '20220525123835_InitialCreate'.
Applying migration '20220525123835_InitialCreate'.
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (348ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "Course" (
"CourseID" integer NOT NULL,
"Title" text NOT NULL,
"Credits" integer NOT NULL,
CONSTRAINT "PK_Course" PRIMARY KEY ("CourseID")
);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (281ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "Student" (
"ID" integer GENERATED BY DEFAULT AS IDENTITY,
"LastName" text NOT NULL,
"FirstMidName" text NOT NULL,
"EnrollmentDate" timestamp with time zone NOT NULL,
CONSTRAINT "PK_Student" PRIMARY KEY ("ID")
);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (95ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "Enrollment" (
"EnrollmentID" integer GENERATED BY DEFAULT AS IDENTITY,
"CourseID" integer NOT NULL,
"StudentID" integer NOT NULL,
"Grade" integer NULL,
CONSTRAINT "PK_Enrollment" PRIMARY KEY ("EnrollmentID"),
CONSTRAINT "FK_Enrollment_Course_CourseID" FOREIGN KEY ("CourseID") REFERENCES "Course" ("CourseID") ON DELETE CASCADE,
CONSTRAINT "FK_Enrollment_Student_StudentID" FOREIGN KEY ("StudentID") REFERENCES "Student" ("ID") ON DELETE CASCADE
);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (104ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE INDEX "IX_Enrollment_CourseID" ON "Enrollment" ("CourseID");
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (187ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE INDEX "IX_Enrollment_StudentID" ON "Enrollment" ("StudentID");
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20220525123835_InitialCreate', '6.0.2');
info: Microsoft.EntityFrameworkCore.Migrations[20402]
Applying migration '20220525130657_MaxLengthOnNames'.
Applying migration '20220525130657_MaxLengthOnNames'.
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (525ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE "Student" ALTER COLUMN "LastName" TYPE character varying(50);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (175ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE "Student" ALTER COLUMN "FirstMidName" TYPE character varying(50);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20220525130657_MaxLengthOnNames', '6.0.2');
Applying migration '20220525140736_ColumnFirstName'.
info: Microsoft.EntityFrameworkCore.Migrations[20402]
Applying migration '20220525140736_ColumnFirstName'.
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE "Student" RENAME COLUMN "FirstMidName" TO "FirstName";
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20220525140736_ColumnFirstName', '6.0.2');
Applying migration '20220526192225_ComplexDataModel'.info: Microsoft.EntityFrameworkCore.Migrations[20402]
Applying migration '20220526192225_ComplexDataModel'.
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE "Student" ALTER COLUMN "EnrollmentDate" DROP NOT NULL;
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (145ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE "Course" ALTER COLUMN "Title" TYPE character varying(50);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (83ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "Instructor" (
"ID" integer GENERATED BY DEFAULT AS IDENTITY,
"LastName" character varying(50) NOT NULL,
"FirstName" character varying(50) NOT NULL,
"HireDate" timestamp with time zone NULL,
CONSTRAINT "PK_Instructor" PRIMARY KEY ("ID")
);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (70ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "CourseAssignment" (
"InstructorID" integer NOT NULL,
"CourseID" integer NOT NULL,
CONSTRAINT "PK_CourseAssignment" PRIMARY KEY ("CourseID", "InstructorID"),
CONSTRAINT "FK_CourseAssignment_Course_CourseID" FOREIGN KEY ("CourseID") REFERENCES "Course" ("CourseID") ON DELETE CASCADE,
CONSTRAINT "FK_CourseAssignment_Instructor_InstructorID" FOREIGN KEY ("InstructorID") REFERENCES "Instructor" ("ID") ON DELETE CASCADE
);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (93ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "Department" (
"DepartmentID" integer GENERATED BY DEFAULT AS IDENTITY,
"Name" character varying(50) NOT NULL,
"Budget" money NOT NULL,
"StartDate" timestamp with time zone NOT NULL,
"InstructorID" integer NULL,
CONSTRAINT "PK_Department" PRIMARY KEY ("DepartmentID"),
CONSTRAINT "FK_Department_Instructor_InstructorID" FOREIGN KEY ("InstructorID") REFERENCES "Instructor" ("ID")
);
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
Failed executing DbCommand (6ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
INSERT INTO Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())
Failed executing DbCommand (6ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
INSERT INTO Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())
Npgsql.PostgresException (0x80004005): 42P01: relation "department" does not exist
POSITION: 13
at Npgsql.Internal.NpgsqlConnector.<ReadMessage>g__ReadMessageLong|213_0(NpgsqlConnector connector, Boolean async, DataRowLoadingMode dataRowLoadingMode, Boolean readingNotifications, Boolean isReadingPrependedMessage)
at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
at Npgsql.NpgsqlDataReader.NextResult()
at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteNonQuery(Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteNonQuery()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Exception data:
Severity: ERROR
SqlState: 42P01
MessageText: relation "department" does not exist
Position: 13
File: parse_relation.c
Line: 1381
Routine: parserOpenTable
42P01: relation "department" does not exist
POSITION: 13
I don't know where that relation should exist and why it does not exist, could you help me please?
EDIT: As correctly noted in Belayer's answer, the cause of the error was that EF Core generates its commands inside them it uses double-quotes to surround the names of columns and tables. When writing plain-SQL statements, one has to use and surround the names with double-quotes too.
I've just pasted that line from the MS tutorial, and that tutorial was made wth SQL Server in mind and not PostgreSQL. That said, cases like this one are exactly why plain-old SQL is almost always not a good thing to do.
You created table "Department" but then used table Department. Those are not the same. Postgres folds all non-doubled quoted ("...") identifiers to lower case (as opposed to the SQL Standard of folding them to uppercase) but keeps the exact case when identifiers are double quoted. However when created with double quotes you must always double quote when referencing.
I've been frustrating myself for too long trying to get the syntax for an Insert correct and am hoping someone can point out my error. I'm using EF Core 5.0.1.
I am trying to insert on the following table using raw SQL:
CREATE TABLE [dbo].[MyTable](
[MyTableId] [smallint] IDENTITY(1,1) NOT NULL,
[Description] [nvarchar](50) NOT NULL,
[UpdateDt] [datetime] NOT NULL,
[UpdateBy] [nvarchar](30) NOT NULL,
[CreateDt] [datetime] NOT NULL,
[CreateBy] [nvarchar](30) NOT NULL,
CONSTRAINT [PK_C_MyTable] PRIMARY KEY CLUSTERED
(
[MyTableId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
I've tried this:
dbContext.Database.ExecuteSqlRaw($"INSERT INTO MyTable(Description, UpdateDt, UpdateBy, CreateDt, CreateBy) VALUES(#Description, #UpdateDt, #UpdateBy, #CreateDt, #CreateBy)", new[] { "status description", "2021-01-17 10:47:45.760", "updater", "2021-01-17 10:47:45.760", "creator" });
I also tried this:
db.Database.ExecuteSqlRaw($"INSERT INTO MyTable (Description, UpdateDt, UpdateBy, CreateDt, CreateBy) VALUES(#Description, #UpdateDt, #UpdateBy, #CreateDt, #CreateBy)", "status description", "2021-01-17 10:47:45.760", "updater", "2021-01-17 10:47:45.760", "creator");
Running either of these gives me the following exception:
System.TypeInitializationException : The type initializer for 'MyClass' threw an exception.
---- Microsoft.Data.SqlClient.SqlException : Must declare the scalar variable "#Description".
I have a hunch I'm overlooking something that's going to make me want to slap my forehead later, but am hoping someone can see what I'm doing wrong.
dbContext.Database.ExecuteSqlRaw(
$"INSERT INTO MyTable(Description, UpdateDt, UpdateBy, CreateDt, CreateBy) VALUES({0}, {1}, {2}, {3}, {4})",
new[]
{
"status description", "2021-01-17 10:47:45.760", "updater", "2021-01-17 10:47:45.760", "creator"
});
This should work. The problem with your solution is that #description, #updatedDt doesn't work as a placeholder. Please follow this documentation here .
I have 2 entities that have a OneToOne relation (User and CodUser) and where User has the JoinColumn. When TypeOrm syncs this pattern to the database it create the CodUser columns within the user, so it embeds the CodUser AND creates a separate table for the CodUser entity.
What I want is that the 2 entities are separate and the columns in the CodUser only appear in the CodUser table in my (Postgres) database.
I believe this is the exact pattern used by TypeOrm to demonstrate OneToOne relations but there seems to be something off.
user.entity.ts
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column({ unique: true })
email: string;
#Column({ nullable: true })
avatar: string;
#Column()
password: string;
#Column({
type: "text",
array: true,
nullable: false,
default: `{${Role.Player}}`
})
roles: Role[];
#OneToOne((type) => CodUser, {
cascade: true
})
#JoinColumn()
codUser: CodUser;
#Column({ default: 0 })
invalidLoginAttempts: number;
#Column({ nullable: true })
activationCode: string;
#Column({ nullable: false, default: false })
active: boolean;
#Column({ nullable: true })
lockedUntil: Date;
#Column({ nullable: true })
lastLoginAttemptAt: Date;
#OneToMany((type) => ChallangeUser, (challangeUser) => challangeUser.user)
challanges: ChallangeUser[];
#CreateDateColumn({ type: "timestamp" })
createdAt: Date;
#UpdateDateColumn({ type: "timestamp" })
updatedAt: Date;
constructor(email: string, username: string, platform: Platform, password: string) {
this.email = email;
this.codUser = new CodUser(username, platform);
this.password = password;
}
}
cod-user.entity.ts
#Entity()
export class CodUser {
#PrimaryGeneratedColumn()
id: string;
#Column({ unique: true })
username: string;
#Column({ nullable: false })
platform: Platform;
#Column({ type: "jsonb", nullable: true })
recentWarzoneMatches: object[];
#Column({ nullable: true })
recentWarzoneMatchesSyncedAt: Date;
constructor(username: string, platform: Platform) {
this.username = username;
this.platform = platform;
}
}
Result:
Transaction while syncing:
query: START TRANSACTION
query: SELECT * FROM current_schema()
query: SELECT * FROM "information_schema"."tables" WHERE ("table_schema" = 'public' AND "table_name" = 'challange') OR ("table_schema" = 'public' AND "table_name" = 'challange_user') OR ("table_schema" = 'public' AND "table_name" = 'cod_user') OR ("table_schema" = 'public' AND "table_name" = 'user') OR ("table_schema" = 'public' AND "table_name" = 'user') OR ("table_schema" = 'public' AND "table_name" = 'challange') OR ("table_schema" = 'public' AND "table_name" = 'challange_user')
query: SELECT *, ('"' || "udt_schema" || '"."' || "udt_name" || '"')::"regtype" AS "regtype" FROM "information_schema"."columns" WHERE ("table_schema" = 'public' AND "table_name" = 'challange') OR ("table_schema" = 'public' AND "table_name" = 'challange_user') OR ("table_schema" = 'public' AND "table_name" =
'cod_user') OR ("table_schema" = 'public' AND "table_name" = 'user') OR ("table_schema" = 'public' AND "table_name" = 'user') OR ("table_schema" = 'public' AND "table_name" = 'challange') OR ("table_schema" = 'public' AND "table_name" = 'challange_user')
query: SELECT "ns"."nspname" AS "table_schema", "t"."relname" AS "table_name", "cnst"."conname" AS "constraint_name", pg_get_constraintdef("cnst"."oid") AS "expression", CASE "cnst"."contype" WHEN 'p' THEN 'PRIMARY' WHEN 'u' THEN 'UNIQUE' WHEN 'c' THEN 'CHECK' WHEN 'x' THEN 'EXCLUDE' END AS "constraint_type", "a"."attname" AS "column_name" FROM "pg_constraint" "cnst" INNER JOIN "pg_class" "t" ON "t"."oid" = "cnst"."conrelid" INNER JOIN "pg_namespace" "ns" ON "ns"."oid" = "cnst"."connamespace" LEFT JOIN "pg_attribute" "a" ON "a"."attrelid" = "cnst"."conrelid" AND "a"."attnum" = ANY ("cnst"."conkey") WHERE "t"."relkind" = 'r' AND (("ns"."nspname" = 'public' AND "t"."relname" = 'challange') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'challange_user') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'cod_user') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'user') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'user') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'challange') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'challange_user'))
query: SELECT "ns"."nspname" AS "table_schema", "t"."relname" AS "table_name", "i"."relname" AS "constraint_name", "a"."attname" AS "column_name", CASE "ix"."indisunique" WHEN 't' THEN 'TRUE' ELSE'FALSE' END AS "is_unique", pg_get_expr("ix"."indpred", "ix"."indrelid") AS "condition", "types"."typname" AS "type_name" FROM "pg_class" "t" INNER JOIN "pg_index" "ix" ON "ix"."indrelid" = "t"."oid" INNER JOIN "pg_attribute" "a" ON "a"."attrelid" = "t"."oid" AND "a"."attnum" = ANY ("ix"."indkey") INNER JOIN "pg_namespace" "ns" ON "ns"."oid" = "t"."relnamespace" INNER JOIN "pg_class" "i" ON "i"."oid" = "ix"."indexrelid" INNER JOIN "pg_type" "types" ON "types"."oid" = "a"."atttypid" LEFT JOIN "pg_constraint" "cnst" ON "cnst"."conname" = "i"."relname" WHERE "t"."relkind" = 'r' AND "cnst"."contype" IS NULL AND (("ns"."nspname" = 'public' AND "t"."relname" = 'challange') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'challange_user') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'cod_user') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'user') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'user') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'challange') OR ("ns"."nspname" = 'public' AND "t"."relname" = 'challange_user'))
query: SELECT "con"."conname" AS "constraint_name", "con"."nspname" AS "table_schema", "con"."relname" AS "table_name", "att2"."attname" AS "column_name", "ns"."nspname" AS "referenced_table_schema", "cl"."relname" AS "referenced_table_name", "att"."attname" AS "referenced_column_name", "con"."confdeltype" AS "on_delete", "con"."confupdtype" AS "on_update", "con"."condeferrable" AS "deferrable", "con"."condeferred" AS "deferred" FROM ( SELECT UNNEST ("con1"."conkey") AS "parent", UNNEST ("con1"."confkey") AS "child", "con1"."confrelid", "con1"."conrelid", "con1"."conname", "con1"."contype", "ns"."nspname", "cl"."relname", "con1"."condeferrable", CASE WHEN "con1"."condeferred" THEN 'INITIALLY DEFERRED' ELSE 'INITIALLY IMMEDIATE' END as condeferred, CASE "con1"."confdeltype" WHEN 'a' THEN 'NO ACTION' WHEN 'r' THEN 'RESTRICT' WHEN 'c' THEN 'CASCADE' WHEN 'n' THEN 'SET NULL' WHEN 'd' THEN 'SET DEFAULT' END as "confdeltype", CASE "con1"."confupdtype" WHEN 'a' THEN 'NO ACTION' WHEN 'r' THEN 'RESTRICT' WHEN 'c' THEN 'CASCADE' WHEN 'n' THEN 'SET NULL' WHEN 'd' THEN 'SET DEFAULT' END as "confupdtype" FROM "pg_class" "cl" INNER JOIN "pg_namespace" "ns" ON "cl"."relnamespace" = "ns"."oid" INNER JOIN "pg_constraint" "con1" ON "con1"."conrelid" = "cl"."oid" WHERE "con1"."contype" = 'f' AND (("ns"."nspname" = 'public' AND "cl"."relname" = 'challange') OR ("ns"."nspname" = 'public' AND "cl"."relname" = 'challange_user') OR ("ns"."nspname" = 'public' AND "cl"."relname" = 'cod_user') OR ("ns"."nspname" = 'public' AND "cl"."relname" = 'user') OR ("ns"."nspname" = 'public' AND "cl"."relname" = 'user') OR ("ns"."nspname" = 'public' AND "cl"."relname" = 'challange') OR ("ns"."nspname" = 'public' AND "cl"."relname" = 'challange_user')) ) "con" INNER JOIN "pg_attribute" "att" ON "att"."attrelid" = "con"."confrelid" AND "att"."attnum" = "con"."child" INNER JOIN "pg_class" "cl" ON "cl"."oid" = "con"."confrelid" INNER JOIN "pg_namespace" "ns" ON "cl"."relnamespace" = "ns"."oid" INNER JOIN "pg_attribute" "att2" ON "att2"."attrelid" = "con"."conrelid" AND "att2"."attnum" = "con"."parent"
query: SELECT * FROM "information_schema"."tables" WHERE "table_schema" = current_schema() AND "table_name" = 'typeorm_metadata'
query: ALTER TABLE "user" DROP CONSTRAINT "FK_c8521799e9a87cab5983c57ba1c"
query: ALTER TABLE "challange_user" DROP CONSTRAINT "FK_0c9f41f81c2f9cadd1154c90499"
query: ALTER TABLE "challange" DROP COLUMN "userLimit"
query: ALTER TABLE "user" DROP CONSTRAINT "UQ_c8521799e9a87cab5983c57ba1c"
query: ALTER TABLE "user" DROP COLUMN "custom_cod_user"
query: ALTER TABLE "user" DROP CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb"
query: ALTER TABLE "user" DROP COLUMN "username"
query: ALTER TABLE "user" DROP COLUMN "platform"
query: ALTER TABLE "user" DROP COLUMN "recentWarzoneMatches"
query: ALTER TABLE "user" DROP COLUMN "recentWarzoneMatchesSyncedAt"
query: ALTER TABLE "user" DROP COLUMN "roles"
query: ALTER TABLE "challange" DROP COLUMN "slots"
query: ALTER TABLE "challange_user" DROP COLUMN "isConfirmed"
query: ALTER TABLE "challange_user" DROP COLUMN "challangeId"
query: ALTER TABLE "challange" ADD "slots" integer NOT NULL DEFAULT -1
query: ALTER TABLE "challange_user" ADD "isConfirmed" boolean NOT NULL DEFAULT false
query: ALTER TABLE "challange_user" ADD "challangeId" uuid
query: ALTER TABLE "user" ADD "roles" text array NOT NULL DEFAULT '{player}'::text[]
query: ALTER TABLE "user" ADD "codUserId" integer
query: ALTER TABLE "user" ADD CONSTRAINT "UQ_4ee803ddc575ea07a96a0aa5f40" UNIQUE ("codUserId")
query: ALTER TABLE "user" ADD "username" character varying NOT NULL
query: ALTER TABLE "user" ADD CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username")
query: ALTER TABLE "user" ADD "platform" character varying NOT NULL
query: ALTER TABLE "user" ADD "recentWarzoneMatches" jsonb
query: ALTER TABLE "user" ADD "recentWarzoneMatchesSyncedAt" TIMESTAMP
query: ALTER TABLE "challange" ADD "userLimit" integer NOT NULL DEFAULT -1
query: ALTER TABLE "challange_user" ADD CONSTRAINT "FK_0c9f41f81c2f9cadd1154c90499" FOREIGN KEY ("challangeId") REFERENCES "challange"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
query: ALTER TABLE "user" ADD CONSTRAINT "FK_4ee803ddc575ea07a96a0aa5f40" FOREIGN KEY ("codUserId") REFERENCES "cod_user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
query: COMMIT
Removing the /dist folder in my NestJS project resolved the issue, seems like it was a NestJS issue after all.
I'm trying to use the timer service provided by Glassfish. Thus, I have to create a table named EJB__TIMER__TBL and configure jdbc resource in Glassfish.
I want to store this table on postgreSQL on a schema named glassfish. So my ddl is this one (I replace the BLOB type to BYTEA) :
CREATE SCHEMA glassfish;
CREATE TABLE glassfish.EJB__TIMER__TBL (
CREATIONTIMERAW BIGINT NOT NULL,
BLOB BYTEA,
TIMERID VARCHAR(255) NOT NULL,
CONTAINERID BIGINT NOT NULL,
OWNERID VARCHAR(255) NULL,
STATE INTEGER NOT NULL,
PKHASHCODE INTEGER NOT NULL,
INTERVALDURATION BIGINT NOT NULL,
INITIALEXPIRATIONRAW BIGINT NOT NULL,
LASTEXPIRATIONRAW BIGINT NOT NULL,
SCHEDULE VARCHAR(255) NULL,
APPLICATIONID BIGINT NOT NULL,
CONSTRAINT PK_EJB__TIMER__TBL PRIMARY KEY (TIMERID)
);
DROP ROLE IF EXISTS glassfish;
CREATE ROLE glassfish WITH NOINHERIT LOGIN PASSWORD '...';
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA glassfish FROM glassfish;
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA glassfish FROM glassfish;
GRANT USAGE ON SCHEMA glassfish TO glassfish;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA glassfish TO glassfish;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA glassfish TO glassfish;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA glassfish TO glassfish;
ALTER USER glassfish SET search_path to 'glassfish';
I configured a jdbc pool and resource for Glassfish :
asadmin create-jdbc-connection-pool
--datasourceclassname org.postgresql.ds.PGConnectionPoolDataSource
--restype javax.sql.ConnectionPoolDataSource
--property User=glassfish:Password=...:PortNumber=5432:DatabaseName=...:ServerName=localhost jdbc/simPool/glassfish
asadmin create-jdbc-resource --connectionpoolid jdbc/simPool/glassfish jdbc/sim/glassfish
And I properly enter jdbc/sim/glassfish in the jdbc resource to use for timer service in Glassish GUI.
Each time I deploy my app, I receive Exception :
[#|2013-02-18T11:42:42.562+0100|WARNING|glassfish3.1.2|org.eclipse.persistence.session.file
:/E:/softs/serveurs/glassfish3_1122/glassfish/domains/domain1/applications/ejb-timer-service-app/WEB-INF/classes/___EJB__Timer__App|_ThreadID=58;_ThreadName=Thread-2;|Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERREUR: la relation « EJB__TIMER__TBL » n'existe pas
Position : 193
Error Code: 0
Call: SELECT "TIMERID", "APPLICATIONID", "BLOB", "CONTAINERID", "CREATIONTIMERAW", "INITIALEXPIRATIONRAW", "INTERVALDURATION", "LASTEXPIRATIONRAW", "OWNERID", "PKHASHCODE", "SCHEDULE", "STATE" FROM "EJB__TIMER__TBL" WHERE (("OWNERID" = ?) AND ("STATE" = ?))
bind => [2 parameters bound]
Query: ReadAllQuery(name="findTimersByOwnerAndState" referenceClass=TimerState sql="SELECT "TIMERID", "APPLICATIONID", "BLOB", "CONTAINERID", "CREATIONTIMERAW", "INITIALEXPIRATIONRAW", "INTERVALDURATION", "LASTEXPIRATIONRAW", "OWNERID", "PKHASHCODE", "SCHEDULE", "STATE" FROM "EJB__TIMER__TBL" WHERE (("OWNERID" = ?) AND ("STATE" = ?))")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:644)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1717)
So my table EJB__TIMER__TBL doesn't seem to be accessible by Glassfish.
When I create another project, configure a persistence.xml file with the same credentials as my pooled connexion above and create a simple query SELECT COUNT(*) FROM EJB__TIMER__TBL, I receive 0 so my connexion is well established and the default schema accessed is glassfish as espected.
In ${glassfish_root}\glassfish\lib\install\databases there is some ddls but neither for postgresql...so where am I doing wrong ?
NB: when I test to configure service timer with MySQL jdbc resource, it's work...
Thanks for help
Ok I found the solution of my problem.
I didn't know that SQL can be case sensitive. Glassfish calls SELECT ... FROM "EJB__TIMER__TBL" with double quotes so I have to create a table named "EJB__TIMER__TBL" not "ejb__timer__tbl" or anything else.
The workaround is just to recreate my table with double quotes :
CREATE TABLE glassfish."EJB__TIMER__TBL" (
"CREATIONTIMERAW" BIGINT NOT NULL,
"BLOB" BYTEA,
"TIMERID" VARCHAR(255) NOT NULL,
"CONTAINERID" BIGINT NOT NULL,
"OWNERID" VARCHAR(255) NULL,
"STATE" INTEGER NOT NULL,
"PKHASHCODE" INTEGER NOT NULL,
"INTERVALDURATION" BIGINT NOT NULL,
"INITIALEXPIRATIONRAW" BIGINT NOT NULL,
"LASTEXPIRATIONRAW" BIGINT NOT NULL,
"SCHEDULE" VARCHAR(255) NULL,
"APPLICATIONID" BIGINT NOT NULL,
CONSTRAINT "PK_EJB__TIMER__TBL" PRIMARY KEY ("TIMERID")
);