What 's the best practice of change encrypted column's property - entity-framework

My [User] table which is having column [Email] encrypted using Always-Encrypt.
I need to limit [Email]'s length from max to MaxLength(250), I do this by add MaxLength(250) on the email property.
public class User
{
[Key, Required]
public Guid Id { get; set; }
[Required, **MaxLength(250)**]
public string Email { get; set; }
...
}
but when I run migration scripts, I got following exception:
Operand type clash: nvarchar(max) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK1', column_encryption_key_database_name = 'Identity') is incompatible with nvarchar
and the migration scripts is:
DECLARE #var0 nvarchar(128)
SELECT #var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'dbo.User')
AND col_name(parent_object_id, parent_column_id) = 'Email';
IF #var0 IS NOT NULL
EXECUTE('ALTER TABLE [dbo].[User] DROP CONSTRAINT [' + #var0 + ']')
ALTER TABLE [dbo].[User] ALTER COLUMN [Email] [nvarchar](250) NOT NULL
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201804250659054_12345678', N'Concordya.PWC.Verify.DataAccess.Migrations.Configuration', 0x1F8... , N'6.2.0-61023')
I manually run the scripts in DB, same error.
Does that mean once the column is encrypted, the only way to change property is decrypt, modify, then encrypt?
Thanks,
Cheng

I came across a similar error when trying to increase the size of an Always Encrypted NVARCHAR column. The problem was that the ALTER COLUMN statement still needs to include the encryption parameters. So for example you could alter this -
ALTER TABLE [dbo].[User] ALTER COLUMN [Email] [nvarchar](250) NOT NULL
To this (or whatever you originally set the Always Encrypted parameters to) -
ALTER TABLE [dbo].[User] ALTER COLUMN [Email] [nvarchar](250) NOT NULL
ENCRYPTED WITH (
ENCRYPTION_TYPE = DETERMINISTIC
, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
, COLUMN_ENCRYPTION_KEY = [**YOUR KEY**]
) NULL

Related

org.postgresql.util.PSQLException: ERROR: column "dsa" does not exist

I am trying to develop a java web app. It is connected to a postgresql database. In this database, I have a table called emp99.In it there is a column called company. when I try to add values to the table I get an error which is:
org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [insert into emp99(name,salary,designation,age,surname,department,company,address,working) values('s',1.0,'d',4,'ff',gg,'dd',true )]; nested exception is org.postgresql.util.PSQLException: ERROR: column "gg" does not exist
But I have this column
CREATE TABLE emp99 (
id int PRIMARY KEY,
name VARCHAR ( 50 ) ,
salary float ,
designation varchar(50),
age int,
surname varchar(50),
department varchar(50),
company varchar(50),
address varchar(50),
working Boolean
);
and this is my adding code:
public int save(Emp p){
String sql="insert into emp99(name,salary,designation,age,surname,department,company,address,working) values('"+p.getName()+"',"+p.getSalary()+",'"+p.getDesignation()+"',"+p.getAge()+",'"+p.getSurname()+"',"+p.getCompany()+",'"+p.getAddress()+"',"+p.getWorking()+" )";
return template.update(sql);
}
#stiky bit you were right i was missing Quotes. The correct one:
public int save(Employee p){
String sql="insert into emp89(name,salary,surname,departmentname,company,address,working,age,saat) values('"+p.getName()+"','"+p.getSalary()+"','"+p.getSurname()+"','"+p.getDepartmentname()+"','"+p.getCompany()+"','"+p.getAddress()+"','"+p.getWorking()+"','"+p.getAge()+"','"+saat+"')";
return template.update(sql);

Include columns from related table in JPA using ListAll()

I have 2 related tables and i am wondering if it is possible to include other columns (like firstname and surname) from table no1 when i am calling the function ListAll() in table no2? I am using JPA with Session Beans (AbstractFacade) and JSF Pages. Thanks in advance :-)
Table No1
CREATE TABLE cases (
caseid INT AUTO_INCREMENT PRIMARY KEY,
category VARCHAR(32),
descript VARCHAR(512),
isDone TINYINT,
userid INT,
INDEX user_ind(userid),
FOREIGN KEY (userid) REFERENCES USERS(userid)
);
Table 2
CREATE TABLE users (
userid INT NOT NULL AUTO_INCREMENT,
firstname VARCHAR(64) NOT NULL,
surname VARCHAR(64) NOT NULL,
telephone VARCHAR(12),
email VARCHAR(64),
PRIMARY KEY (userid)
);
Entity Controller
#Named(value = "caseController")
#SessionScoped
public class CaseController implements Serializable {
#EJB
CasesFacade casesFacade;
#Inject
CasesBean casesBean;
public List<Cases> getAll() {
return casesFacade.findAll();
}
If i correct understand maybe the good idea will be unpack chosen columns/fields to custom DTO on level repository or in code.

EF model not being updated correctly from database

I have noted that one of my tables in my existing Entity Framework model has not been updated for long.
One table has news columns in the database which they are not present in the EF model.
Now I need to update de EF model to include these new columns in the table.
So from edmx designer I select the option "Update model from database..."
After doing that, new columns are added correctly to the table in EF model except one in which I am interested in. This column is a foreign key that points to another table.
So Why are some new columns added correctly to the EF model and the one I am interested in isn't?
UPDATE:
I am using database first. So I post here some details.
Tables in SQL Server are below:
Table [eq].[CalibracionVerificacion]
CREATE TABLE [eq].[CalibracionVerificacion](
[calibracionVerificacionId] [int] IDENTITY(1,1) NOT NULL,
[equipoId] [int] NOT NULL,
[empresaCVId] [int] NULL,
[usuarioCVMId] [int] NULL,
[tipo] [smallint] NOT NULL,
[fechaPrevista] [datetime] NULL,
[magnitudId] [nvarchar](10) NULL,
[frecuencia] [smallint] NULL,
[fechaInforme] [datetime] NULL,
[usuarioAprobadorId] [int] NULL,
[fechaAprobacion] [datetime] NULL,
[procedenciaInforme] [int] NULL,
[numeroCertificado] [varchar](25) NULL,
[temperatura] [int] NULL,
[humedadRelativa] [int] NULL,
[presionAtmosferica] [int] NULL,
[incertidumbreMaxima] [decimal](7, 2) NULL,
[correccionMedidas] [int] NULL,
[controlRealizado] [int] NULL,
[observacion] [varchar](500) NULL,
[equipoComprobacionId] [int] NULL,
[resultado] [smallint] NOT NULL,
[estado] [smallint] NOT NULL,
[fechaCalibracion] [datetime] NULL,
[unidadFrecuencia] [nvarchar](2) NULL,
CONSTRAINT [PK__Calibrac__596425FE797F8D7F] PRIMARY KEY CLUSTERED
(
[calibracionVerificacionId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [eq].[CalibracionVerificacion] WITH CHECK ADD CONSTRAINT [FK_CalibracionVerificacion_Equipo] FOREIGN KEY([equipoId])
REFERENCES [eq].[Equipo] ([equipoId])
ON DELETE CASCADE
GO
ALTER TABLE [eq].[CalibracionVerificacion] CHECK CONSTRAINT [FK_CalibracionVerificacion_Equipo]
GO
ALTER TABLE [eq].[CalibracionVerificacion] WITH CHECK ADD CONSTRAINT [FK_CalibracionVerificacion_Equipo1] FOREIGN KEY([equipoComprobacionId])
REFERENCES [eq].[Equipo] ([equipoId])
GO
ALTER TABLE [eq].[CalibracionVerificacion] CHECK CONSTRAINT [FK_CalibracionVerificacion_Equipo1]
GO
Table [eq].[Equipo]
CREATE TABLE [eq].[Equipo](
[equipoId] [int] IDENTITY(1,1) NOT NULL,
[empresaPropietariaId] [int] NULL,
[sociedadId] [varchar](4) NOT NULL,
[unidadOrganizativaId] [varchar](10) NOT NULL,
[delegacionPropiedadId] [varchar](4) NULL,
[magnitudId] [nvarchar](10) NULL,
[subMagnitudId] [nvarchar](10) NULL,
[familiaId] [nvarchar](10) NULL,
[axaptaId] [varchar](10) NULL,
[denominacion] [varchar](75) NULL,
[equipoPropio] [smallint] NOT NULL,
[equipoPatron] [smallint] NOT NULL,
[usuarioSegundoResponsable] [varchar](75) NULL,
[mailSegundoResponsable] [varchar](75) NULL,
[modelo] [varchar](50) NULL,
[numeroSerie] [varchar](25) NULL,
[capacidad] [varchar](25) NULL,
[fechaAdquisicion] [datetime] NULL,
[fechaFin] [datetime] NULL,
[precioSinIva] [decimal](10, 2) NULL,
[observacion] [varchar](500) NULL,
[motivoBaja] [varchar](500) NULL,
[estado] [smallint] NOT NULL,
[equipoIdOldSocotec] [int] NULL,
[marcaId] [smallint] NULL,
[limitacion] [varchar](500) NULL,
[proveedor] [varchar](500) NULL,
[tipoId] [int] NULL,
[usuarioResponsableId] [int] NULL,
[activoFieldeas] [bit] NULL,
CONSTRAINT [PK_Equipo] PRIMARY KEY CLUSTERED
(
[equipoId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Below is the generated DDL dbModel.edmx.sql. I have udpated the model from database using option "Update model from database" from model designer, but as you can see equipoId and equipoComprobacionId fields which are foreign keys are not created in the model in table [CalibracionVerificacion]. Why?
-- --------------------------------------------------
-- Dropping existing FOREIGN KEY constraints
-- --------------------------------------------------
IF OBJECT_ID(N'[eq].[FK_CalibracionVerificacion_Equipo]', 'F') IS NOT NULL
ALTER TABLE [eq].[CalibracionVerificacion] DROP CONSTRAINT [FK_CalibracionVerificacion_Equipo];
GO
IF OBJECT_ID(N'[eq].[FK_CalibracionVerificacion_Equipo1]', 'F') IS NOT NULL
ALTER TABLE [eq].[CalibracionVerificacion] DROP CONSTRAINT [FK_CalibracionVerificacion_Equipo1];
GO
IF OBJECT_ID(N'[st].[FK_EquipoUtilizado_Equipo]', 'F') IS NOT NULL
ALTER TABLE [st].[EquipoUtilizado] DROP CONSTRAINT [FK_EquipoUtilizado_Equipo];
GO
-- --------------------------------------------------
-- Dropping existing tables
-- --------------------------------------------------
IF OBJECT_ID(N'[eq].[CalibracionVerificacion]', 'U') IS NOT NULL
DROP TABLE [eq].[CalibracionVerificacion];
GO
IF OBJECT_ID(N'[eq].[Equipo]', 'U') IS NOT NULL
DROP TABLE [eq].[Equipo];
GO
IF OBJECT_ID(N'[st].[EquipoUtilizado]', 'U') IS NOT NULL
DROP TABLE [st].[EquipoUtilizado];
GO
-- --------------------------------------------------
-- Creating all tables
-- --------------------------------------------------
-- Creating table 'Equipo'
CREATE TABLE [dbo].[Equipo] (
[equipoId] int IDENTITY(1,1) NOT NULL,
[empresaPropietariaId] int NULL,
[sociedadId] varchar(4) NOT NULL,
[unidadOrganizativaId] varchar(10) NOT NULL,
[magnitudId] nvarchar(10) NULL,
[subMagnitudId] nvarchar(10) NULL,
[familiaId] nvarchar(10) NULL,
[axaptaId] varchar(10) NULL,
[denominacion] varchar(75) NULL,
[equipoPropio] smallint NOT NULL,
[equipoPatron] smallint NOT NULL,
[usuarioSegundoResponsable] varchar(75) NULL,
[mailSegundoResponsable] varchar(75) NULL,
[modelo] varchar(50) NULL,
[numeroSerie] varchar(25) NULL,
[capacidad] varchar(25) NULL,
[fechaAdquisicion] datetime NULL,
[fechaFin] datetime NULL,
[precioSinIva] decimal(10,2) NULL,
[observacion] varchar(500) NULL,
[motivoBaja] varchar(500) NULL,
[estado] smallint NOT NULL,
[equipoIdOldSocotec] int NULL,
[marcaId] smallint NULL,
[limitacion] varchar(500) NULL,
[proveedor] varchar(500) NULL,
[delegacionPropiedadId] varchar(4) NULL,
[tipoId] int NULL,
[usuarioResponsableId] int NULL,
[activoFieldeas] bit NULL
);
GO
-- Creating table 'EquipoUtilizado'
CREATE TABLE [dbo].[EquipoUtilizado] (
[equipoUtilizadoId] int IDENTITY(1,1) NOT NULL,
[seguimientoTrabajoId] int NOT NULL,
[mantenimiento] bit NULL,
[orden] tinyint NULL,
[Equipo_equipoId] int NOT NULL
);
GO
-- Creating table 'CalibracionVerificacion'
CREATE TABLE [dbo].[CalibracionVerificacion] (
[calibracionVerificacionId] int IDENTITY(1,1) NOT NULL,
[empresaCVId] int NULL,
[usuarioCVMId] int NULL,
[tipo] smallint NOT NULL,
[fechaPrevista] datetime NULL,
[magnitudId] nvarchar(10) NULL,
[frecuencia] smallint NULL,
[fechaInforme] datetime NULL,
[usuarioAprobadorId] int NULL,
[fechaAprobacion] datetime NULL,
[procedenciaInforme] int NULL,
[numeroCertificado] varchar(25) NULL,
[temperatura] int NULL,
[humedadRelativa] int NULL,
[presionAtmosferica] int NULL,
[incertidumbreMaxima] decimal(7,2) NULL,
[correccionMedidas] int NULL,
[controlRealizado] int NULL,
[observacion] varchar(500) NULL,
[resultado] smallint NOT NULL,
[estado] smallint NOT NULL,
[fechaCalibracion] datetime NULL,
[unidadFrecuencia] nvarchar(2) NULL,
[Equipo_equipoId] int NOT NULL,
[Equipo1_equipoId] int NULL
);
GO
-- --------------------------------------------------
-- Creating all PRIMARY KEY constraints
-- --------------------------------------------------
-- Creating primary key on [equipoId] in table 'Equipo'
ALTER TABLE [dbo].[Equipo]
ADD CONSTRAINT [PK_Equipo]
PRIMARY KEY CLUSTERED ([equipoId] ASC);
GO
-- Creating primary key on [equipoUtilizadoId] in table 'EquipoUtilizado'
ALTER TABLE [dbo].[EquipoUtilizado]
ADD CONSTRAINT [PK_EquipoUtilizado]
PRIMARY KEY CLUSTERED ([equipoUtilizadoId] ASC);
GO
-- Creating primary key on [calibracionVerificacionId] in table 'CalibracionVerificacion'
ALTER TABLE [dbo].[CalibracionVerificacion]
ADD CONSTRAINT [PK_CalibracionVerificacion]
PRIMARY KEY CLUSTERED ([calibracionVerificacionId] ASC);
GO
-- --------------------------------------------------
-- Creating all FOREIGN KEY constraints
-- --------------------------------------------------
-- Creating foreign key on [Equipo_equipoId] in table 'EquipoUtilizado'
ALTER TABLE [dbo].[EquipoUtilizado]
ADD CONSTRAINT [FK_EquipoUtilizado_Equipo]
FOREIGN KEY ([Equipo_equipoId])
REFERENCES [dbo].[Equipo]
([equipoId])
ON DELETE NO ACTION ON UPDATE NO ACTION;
GO
-- Creating non-clustered index for FOREIGN KEY 'FK_EquipoUtilizado_Equipo'
CREATE INDEX [IX_FK_EquipoUtilizado_Equipo]
ON [dbo].[EquipoUtilizado]
([Equipo_equipoId]);
GO
-- Creating foreign key on [Equipo_equipoId] in table 'CalibracionVerificacion'
ALTER TABLE [dbo].[CalibracionVerificacion]
ADD CONSTRAINT [FK_CalibracionVerificacion_Equipo]
FOREIGN KEY ([Equipo_equipoId])
REFERENCES [dbo].[Equipo]
([equipoId])
ON DELETE CASCADE ON UPDATE NO ACTION;
GO
-- Creating non-clustered index for FOREIGN KEY 'FK_CalibracionVerificacion_Equipo'
CREATE INDEX [IX_FK_CalibracionVerificacion_Equipo]
ON [dbo].[CalibracionVerificacion]
([Equipo_equipoId]);
GO
-- Creating foreign key on [Equipo1_equipoId] in table 'CalibracionVerificacion'
ALTER TABLE [dbo].[CalibracionVerificacion]
ADD CONSTRAINT [FK_CalibracionVerificacion_Equipo1]
FOREIGN KEY ([Equipo1_equipoId])
REFERENCES [dbo].[Equipo]
([equipoId])
ON DELETE NO ACTION ON UPDATE NO ACTION;
GO
-- Creating non-clustered index for FOREIGN KEY 'FK_CalibracionVerificacion_Equipo1'
CREATE INDEX [IX_FK_CalibracionVerificacion_Equipo1]
ON [dbo].[CalibracionVerificacion]
([Equipo1_equipoId]);
GO
So as above explained, since equipoId and equipoComprobacionId fields which are foreign keys are not created in the model in table [CalibracionVerificacion], then below Linq query are not working, that is, fechaPrevista is getting Nothing because c3.equipoId and c.equipoId are always 0 because equipoId field is always 0 and not present in table CalibracionVerificacion. So the problem is that equipoId field in CalibracionVerificacion table is never being loaded in the model. Why?
Dim eq = db.Equipo
For Each equipo As Equipo In eq
Dim fechaPrevista As DateTime? = If(Not (equipo.CalibracionVerificacion.Any()) OrElse
Not (equipo.CalibracionVerificacion.Any(Function(x) Not (String.IsNullOrWhiteSpace(x.magnitudId)))),
CType(Nothing, DateTime?),
(From c In equipo.CalibracionVerificacion
Join c2 In
(From c3 In equipo.CalibracionVerificacion
Where c3.equipoId = equipo.equipoId AndAlso Not (String.IsNullOrWhiteSpace(c3.magnitudId))
Group c3 By c3.magnitudId Into cgroup = Group
Select New With
{
Key .MagnitudID = magnitudId,
Key .MaxDate = cgroup.Max(Function(x) x.fechaPrevista)
}
) On New With {.JoinProperty1 = c.magnitudId, .JoinProperty2 = c.fechaPrevista} Equals
New With {.JoinProperty1 = c2.MagnitudID, .JoinProperty2 = c2.MaxDate}
Where c.equipoId = equipo.equipoId
Select c).Min(Function(d) d.fechaPrevista))
Next
LAST ATTEMPT:
From model designer I have deleted all the tables. Then I have gone through option "Update model from database..." and I have selected "Add" tab. Finally I select the tables above indicated which I am interested in and all three tables are inserted correctly into the model edmx, also equipoId and equipoComprobacionId fields are added correctly into table [CalibracionVerificacion]. Relations between tables are created correctly as well. Finally I successfully build the solution and execute it. I put a breakpoint in the above LINQ expression to debug it, after pressing F10 to proceed with its execution an exception is thrown saying this:
{"Schema specified is not valid. Errors: The relationship
'MyModel.FK_CalibracionVerificacion_Equipo' was not loaded because the
type 'MyModel.CalibracionVerificacion' is not available. The following
information may be useful in resolving the previous error: The
required property 'equipoComprobacionId' does not exist on the type
'MyService.CalibracionVerificacion'.
The relationship 'MyModel.FK_CalibracionVerificacion_Equipo1' was not
loaded because the type 'MyModel.CalibracionVerificacion' is not
available. The following information may be useful in resolving the
previous error: The required property 'equipoComprobacionId' does not
exist on the type 'MyService.CalibracionVerificacion'.
"}
Below are the entities generated by EF:
Partial Public Class Equipo
Public Property equipoId As Integer
Public Property empresaPropietariaId As Nullable(Of Integer)
Public Property sociedadId As String
Public Property unidadOrganizativaId As String
Public Property delegacionPropiedadId As String
Public Property magnitudId As String
Public Property subMagnitudId As String
Public Property familiaId As String
Public Property axaptaId As String
Public Property denominacion As String
Public Property equipoPropio As Short
Public Property equipoPatron As Short
Public Property usuarioSegundoResponsable As String
Public Property mailSegundoResponsable As String
Public Property modelo As String
Public Property numeroSerie As String
Public Property capacidad As String
Public Property fechaAdquisicion As Nullable(Of Date)
Public Property fechaFin As Nullable(Of Date)
Public Property precioSinIva As Nullable(Of Decimal)
Public Property observacion As String
Public Property motivoBaja As String
Public Property estado As Short
Public Property equipoIdOldSocotec As Nullable(Of Integer)
Public Property marcaId As Nullable(Of Short)
Public Property limitacion As String
Public Property proveedor As String
Public Property tipoId As Nullable(Of Integer)
Public Property usuarioResponsableId As Nullable(Of Integer)
Public Property activoFieldeas As Nullable(Of Boolean)
Public Overridable Property CalibracionVerificacion As ICollection(Of CalibracionVerificacion) = New HashSet(Of CalibracionVerificacion)
Public Overridable Property CalibracionVerificacion1 As ICollection(Of CalibracionVerificacion) = New HashSet(Of CalibracionVerificacion)
Public Overridable Property EquipoUtilizado As ICollection(Of EquipoUtilizado) = New HashSet(Of EquipoUtilizado)
End Class
Partial Public Class CalibracionVerificacion
Public Property calibracionVerificacionId As Integer
Public Property equipoId As Integer
Public Property empresaCVId As Nullable(Of Integer)
Public Property usuarioCVMId As Nullable(Of Integer)
Public Property tipo As Short
Public Property fechaPrevista As Nullable(Of Date)
Public Property magnitudId As String
Public Property frecuencia As Nullable(Of Short)
Public Property fechaInforme As Nullable(Of Date)
Public Property usuarioAprobadorId As Nullable(Of Integer)
Public Property fechaAprobacion As Nullable(Of Date)
Public Property procedenciaInforme As Nullable(Of Integer)
Public Property numeroCertificado As String
Public Property temperatura As Nullable(Of Integer)
Public Property humedadRelativa As Nullable(Of Integer)
Public Property presionAtmosferica As Nullable(Of Integer)
Public Property incertidumbreMaxima As Nullable(Of Decimal)
Public Property correccionMedidas As Nullable(Of Integer)
Public Property controlRealizado As Nullable(Of Integer)
Public Property observacion As String
Public Property equipoComprobacionId As Nullable(Of Integer)
Public Property resultado As Short
Public Property estado As Short
Public Property fechaCalibracion As Nullable(Of Date)
Public Property unidadFrecuencia As String
Public Overridable Property Equipo As Equipo
Public Overridable Property Equipo1 As Equipo
End Class
What's happening?

Entity Framework Insert - Cannot add or update a child row: a foreign key constraint fails

I'm getting the following error and despite following-up on many 'similar' posts I cannot find find the answer when making insert to 2 tables with a FK using Entity Framework. I think the issue, when looking at the Trace/Log (below) the FK (id) value is 0 (zero). If I can get that figured out it might solve the problem.
ERROR: (Obvious what it is saying, but can't figure out how to fix)
Cannot add or update a child row: a foreign key constraint fails ("xdata"."table_b", CONSTRAINT "f111" FOREIGN KEY ("table_a_id") REFERENCES "table_a" ("id") ON DELETE CASCADE ON UPDATE CASCADE)
MODELS:
public class table_a
{
public int id { get; set; }
public string name { get; set; }
}
public class table_b
{
public int id { get; set; }
public string desc { get; set; }
public int table_a_id { get; set; }
}
CODE TO INSTANTIATE MODELS AND INSERT:
table_a a = new table_a()
{
name = "table a name",
};
table_b b = new table_b()
{
desc = "table b desc",
table_a_id = a.id
};
DataContext.Database.Log = message => Trace.Write(message);
DataContext.TableA.Add(a);
DataContext.TableB.Add(b);
var result = DataContext.SaveChanges();
TRACE:
SET SESSION sql_mode='ANSI';
INSERT INTO table_a(
name) VALUES (
#gp1);
SELECT
id
FROM table_a
WHERE row_count() > 0 AND id=last_insert_id()
-- #gp1: 'table a name' (Type = String, IsNullable = false, Size = 12)
-- Executing at 12/8/2017 7:50:53 PM -07:00
-- Completed in 55 ms with result: EFMySqlDataReader
SET SESSION sql_mode='ANSI';
INSERT INTO table_b(
desc,
table_a_id) VALUES (
#gp1,
0);
SELECT
id
FROM table_b
WHERE row_count() > 0 AND id=last_insert_id()
-- #gp1: 'table b desc' (Type = String, IsNullable = false, Size = 12)
-- Executing at 12/8/2017 7:50:53 PM -07:00
-- Failed in 56 ms with error: Cannot add or update a child row: a foreign key constraint fails ("xdata"."table_b", CONSTRAINT "f111" FOREIGN KEY ("table_a_id") REFERENCES "table_a" ("id") ON DELETE CASCADE ON UPDATE CASCADE)
DB SCHEMA:
Edited to remove db schema image (12/8/2017)
CREATE TABLE `table_a`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `table_b`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`desc` varchar(45) DEFAULT NULL,
`table_a_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `f111_idx` (`table_a_id`),
CONSTRAINT `f111` FOREIGN KEY (`table_a_id`) REFERENCES `table_a` (`id`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

Grails doesn't create foreign key column in PostgreSQL

I am having trouble generating my tables in PostgreSQL from Grails. I have simple Email and EmailAttachment domain classes with a hasMany and belongsTo relationship. This setup worked well on our production server (AS400 DB2), but when I try to run my program on PostgreSQL (the new dev environment), the Email class does not have the attachment_id column.
Email.groovy:
class Email {
static hasMany = [attachments:EmailAttachment]
Integer id
Integer version = 0
String subject
String recipients
String sender
Date sentDate
String plainTextMessage
Set attachments
static mapping = {
datasources(['DEFAULT'])
table name:'error_email', schema: Appointment.schema
sort sentDate:'desc'
}
static constraints = {
subject nullable:true
version nullable:true
recipients nullable:true
sender nullable:true
sentDate nullable:true
plainTextMessage nullable:true
attachments nullable:true
}
def String toString(){
return subject
}
}
EmailAttachment.groovy:
class EmailAttachment {
static belongsTo = [email:ErrorEmail]
ErrorEmail email
String filename
byte[] content
static mapping = {
datasources(['DEFAULT'])
table name:'error_email_attachment', schema: Appointment.schema
}
static constraints = {
filename nullable:true
content nullable:true
}
}
Also, here are the relevant lines from schema-export:
alter table program.email_attachment drop constraint FK2E592AFD1D80E229;
drop table program.email cascade;
drop table program.email_attachment cascade;
drop sequence hibernate_sequence;
create table program.email (id int4 not null, version int4, plain_text_message varchar(255), recipients varchar(255), sender varchar(255), sent_date timestamp, subject varchar(255), primary key (id));
create table program.email_attachment (id int8 not null, version int8 not null, content bytea, email_id int4 not null, filename varchar(255), primary key (id));
alter table program.email_attachment add constraint FK2E592AFD1D80E229 foreign key (email_id) references program.error_email;
create sequence hibernate_sequence;
I've tried specifying joinTable: attachments joinTable:[name: 'email_table', column: 'attachment_id', key: 'id'] to no avail, as well as leaving it out, and trying other collection types for attachment. Thanks in advance for your time and brain cells.
The email doesn't have an attachment_id column because it's the one side of the one-to-many. The many side, attachment in this case, has a reference to its owning email in the email_id int4 not null column. Given an email with id 42 you (and Grails/GORM/Hibernate) can find all of the attachments by querying for all rows in that table with email_id=42.