How do I map Entity Framework many To many table with extra key part? - entity-framework

Is there a way to map this so that the parent tables Airport and Flight map to only the relevant part of the foreign composite key?
Using EF4.3 with Code First and Fluid API.
Each flight lands at one or more airports in a specific order. Without the additonal key property of FlightOrder, this mapping works.
Airport
- string Code
- List<AirportFlight> AirportFlights
Flight
- string Number
- List<AirportFlight> AirportFlights
AirportFlight
- string AirportCode
- string FlightNumber
- int FlightOrder
public AirportConfiguration() {
HasKey(x => x.Code);
HasMany(x => x.AirportFlights).WithRequired().HasForeignKey(x => x.AirportCode);
}
public AirportFlightConfiguration() {
HasKey(x => new { x.AirportCode, x.FlightNumber, x.FlightOrder });
}
public FlightConfiguration()
{
HasKey(x => x.Number);
HasMany(x => x.AirportFlights).WithRequired().HasForeignKey(x => x.FlightNumber);
}
This is Entity Framework generated schema:
CREATE TABLE Airports(
Code nvarchar(128) NOT NULL,
AirportFlight_AirportCode nvarchar(128) NULL, -- *** DO NOT WANT THIS ***
AirportFlight_FlightNumber nvarchar(128) NULL, -- *** DO NOT WANT THIS ***
AirportFlight_FlightOrder int NULL, -- *** DO NOT WANT THIS ***
CREATE TABLE Flights(
Number nvarchar(128) NOT NULL,
AirportFlight_AirportCode nvarchar(128) NULL, -- *** DO NOT WANT THIS ***
AirportFlight_FlightNumber nvarchar(128) NULL, -- *** DO NOT WANT THIS ***
AirportFlight_FlightOrder int NULL, -- *** DO NOT WANT THIS ***
CREATE TABLE AirportFlights(
AirportCode nvarchar(128) NOT NULL,
FlightNumber nvarchar(128) NOT NULL,
FlightOrder int NOT NULL,
CreatedDate datetime NOT NULL,
RowVersion varbinary(max) NULL,
CONSTRAINT PK_AirportFlights PRIMARY KEY CLUSTERED
(
AirportCode ASC,
FlightNumber ASC,
FlightOrder ASC
)
ALTER TABLE AirportFlights WITH CHECK ADD CONSTRAINT FK_AirportFlights_Airports_AirportCode FOREIGN KEY(AirportCode)
REFERENCES Airports (Code)
ALTER TABLE AirportFlights WITH CHECK ADD CONSTRAINT FK_AirportFlights_Flights_FlightNumber FOREIGN KEY(FlightNumber)
REFERENCES Flights (Number)
-- *** DO NOT WANT THIS ***
ALTER TABLE Airports WITH CHECK ADD CONSTRAINT FK_Airports_AirportFlights_AirportFlight_AirportCode_AirportFlight_FlightNumber_AirportFlight_FlightOrder FOREIGN KEY(AirportFlight_AirportCode, AirportFlight_FlightNumber, AirportFlight_FlightOrder)
REFERENCES AirportFlights (AirportCode, FlightNumber, FlightOrder)
-- *** DO NOT WANT THIS ***
ALTER TABLE Flights WITH CHECK ADD CONSTRAINT FK_Flights_AirportFlights_AirportFlight_AirportCode_AirportFlight_FlightNumber_AirportFlight_FlightOrder FOREIGN KEY(AirportFlight_AirportCode, AirportFlight_FlightNumber, AirportFlight_FlightOrder)
REFERENCES AirportFlights (AirportCode, FlightNumber, FlightOrder)
Thanks.
Fixed:
These properties were in the AirportFlights entity
- List<Airport> Airports
- List<Flight> Flights

Since you have mapped the join table as an entity, it does not have collection navigational properties to Airport and Flight. You have to model this as two one-to-many relationships. Remove List<Airport> Airports and List<Flight> Flights.
AirportFlight
- string AirportCode
- string FlightNumber
- int FlightOrder
However you can place navigationa proprties Airport and Flight on AirportFlight entity if you want.

Related

MIGRATION FAILED ENUM TYPE ALREADY EXISTS ERROR

I'm building a microservices app using Spring Boot + Postgres + Flyway,
within flight-archive microservice, I created a script sql that contains the following code:
CREATE TYPE Payment_method AS ENUM ('CASH', 'PAYPAL', 'CREDIT CARD');
CREATE TABLE IF NOT EXISTS flight_booking_archive (
booking_Id INT NOT NULL PRIMARY KEY,
flight_Id INT NOT NULL,
passenger_Id INT NOT NULL,
adults INT NOT NULL,
babies INT NOT NULL,
amount_paid MONEY,
payment_method Payment_method,
booked DATE DEFAULT CURRENT_DATE,
CONSTRAINT fk_flight_id FOREIGN KEY (flight_Id) references flight(flight_ID),
CONSTRAINT fk_passenger_id FOREIGN KEY (passenger_Id) references passenger(passenger_ID)
)
then, when I run flight-archive microservice using maven, I got the following error
SQL State : 42710
Error Code : 0
Message : ERROR: type "payment_method" already exists
Location : db/migration/V1__flight_archive_table.sql (C:\Users\OMAYMA\flight-app-
demo\server\flight-booking-
archive\target\classes\db\migration\V1__flight_archive_table.sql)
Line : 1
Statement : CREATE TYPE Payment_method AS ENUM ('CASH', 'PAYPAL', 'CREDIT CARD')
In Postgres if you want to use uppercase you have to use quotation marks, otherwise, the words will always be in lowercase.
Try making this change:
CREATE TYPE "Payment_method" AS ENUM ('CASH', 'PAYPAL', 'CREDIT CARD');
CREATE TABLE IF NOT EXISTS flight_booking_archive (
booking_Id INT NOT NULL PRIMARY KEY,
flight_Id INT NOT NULL,
passenger_Id INT NOT NULL,
adults INT NOT NULL,
babies INT NOT NULL,
amount_paid MONEY,
payment_method "Payment_method",
booked DATE DEFAULT CURRENT_DATE,
CONSTRAINT fk_flight_id FOREIGN KEY (flight_Id) references flight(flight_ID),
CONSTRAINT fk_passenger_id FOREIGN KEY (passenger_Id) references passenger(passenger_ID)

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.

PostgreSQL foreign key create error

I'm new to PostgreSQL and trying to create table with foreign keys.But I got error below.
create table User_Role
(
RoleId serial primary key not null,
RoleCode varchar(21),
Rolename varchar(30),
isActive bool
)
CREATE TABLE User_Account(
UserId serial primary key not null,
RoleId_ref int REFERENCES User_Role (RoleId) NULL,
Username text NULL,
Password text NULL,
IsActive bool NULL
)
CREATE TABLE User_Profile(
ProfileId serial primary key not null,
UserId_ref int REFERENCES User_Account (UserId) NULL,
RoleId_ref int REFERENCES User_Role (RoleId) NULL,
FirstName Text NULL,
LastName Text NULL,
Address Text NULL,
City varchar(100) NULL
)
first two table created successfully. But last table occur create error.
ERROR: column "roleid" referenced in foreign key constraint does not exist
SQL state: 42703
but I can't understand why.

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;

Using Automapper with F# Entity Type Provider

I am looking at Automapper for the first time using F# and the Entity Type Provider. I want to map between the EF Type Provider types and the F# record types that I have created.
The EF Type Provider is based on the following database schema:
CREATE TABLE [dbo].[Address](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[State] [varchar](50) NOT NULL,
[County] [varchar](50) NOT NULL,
[City] [varchar](50) NOT NULL,
CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Child](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[FirstName] [varchar](50) NOT NULL,
[Gender] [varchar](50) NOT NULL,
[Grade] [int] NOT NULL,
CONSTRAINT [PK_Child] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Family](
[Id] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](50) NOT NULL,
[IsRegistered] [bit] NOT NULL,
CONSTRAINT [PK_Family] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Parent](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[FirstName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Pet](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ChildId] [int] NOT NULL,
[GivenName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Pet] PRIMARY KEY CLUSTERED ([Id] ASC)
ALTER TABLE [dbo].[Address] WITH CHECK ADD CONSTRAINT [FK_Address_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Address] CHECK CONSTRAINT [FK_Address_Family]
ALTER TABLE [dbo].[Child] WITH CHECK ADD CONSTRAINT [FK_Child_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Child] CHECK CONSTRAINT [FK_Child_Family]
ALTER TABLE [dbo].[Parent] WITH CHECK ADD CONSTRAINT [FK_Parent_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Parent] CHECK CONSTRAINT [FK_Parent_Family]
ALTER TABLE [dbo].[Pet] WITH CHECK ADD CONSTRAINT [FK_Pet_Child] FOREIGN KEY([ChildId])
REFERENCES [dbo].[Child] ([Id])
ALTER TABLE [dbo].[Pet] CHECK CONSTRAINT [FK_Pet_Child]
I then created a comparable set of types in F#:
type Pet = {Id:int; GivenName:string}
type Child = {Id:int; FirstName:string; Gender:string; Grade:int; Pets: Pet list}
type Address = {Id:int; State:string; County:string; City:string}
type Parent = {Id:int; FirstName:string}
type Family = {Id:int; Parents:Parent list; Children: Child list; Address:Address}
The only real difference is that the foreign key is not explicit in the record types.
When I use Automapper on the Address type, it works as expected:
Mapper.CreateMap<EntityConnection.ServiceTypes.Address, Address>()
let context = EntityConnection.GetDataContext()
let addressQuery = query {for address in context.Addresses do select address}
let address = Seq.head addressQuery
let address' = Mapper.Map<Address>(address)
val address' : Address = {Id = 1;
State = "WA";
County = "King";
City = "Seattle";}
But when I try and do the same with the entire graph,
Mapper.CreateMap<EntityConnection.ServiceTypes.Pet, Pet>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Child, Child>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Address, Address>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Parent, Parent>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Family, Family>()
let context = EntityConnection.GetDataContext()
let familyQuery = query {for family in context.Families do select family}
let family = Seq.head familyQuery
let family' = Mapper.Map<Family>(family)
I get this exception:
System.ArgumentException: Type needs to have a constructor with 0 args or only optional args
Parameter name: type
I am wondering if it is b/c EF is lazy loading so the remaining types are not being evaluated? has anyone seen this before?
The error is pretty straight forward. None of your classes have a constructor that takes 0 arguments.
F# creates default constructors for you so the default constructor on your class has multiple arguments in it. For example:
type Pet = {Id:int; GivenName:string}
as a c# class would have this as it's definition.
public class Pet
{
public int Id { get; private set; }
public string GivenName { get; private set; }
public Pet(int id, string givenName)
{
Id = id;
GivenName = givenName;
}
}
Note the lack of a parameterless constructor. That's where your error is coming from.
You can fix it by flagging your type as CLIMutable
[<CLIMutable>]
type Pet = {Id:int; GivenName:string}