diff --git a/API/FamilyTreeAPI/Data/DataWork.cs b/API/FamilyTreeAPI/Data/DataWork.cs
index c6e4e72..8168a05 100644
--- a/API/FamilyTreeAPI/Data/DataWork.cs
+++ b/API/FamilyTreeAPI/Data/DataWork.cs
@@ -2,7 +2,12 @@
using Microsoft.EntityFrameworkCore;
using System.Data.Common;
using FamilyTreeAPI.Entities;
-using FamilyTreeAPI.Interface;
+
+/*
+ dotnet ef migrations add PersonPhoto run at project .csproj folder
+
+dotnet ef database update
+ */
namespace FamilyTreeAPI.Models
{
diff --git a/API/FamilyTreeAPI/Migrations/20251013112634_PersonPhoto.Designer.cs b/API/FamilyTreeAPI/Migrations/20251013112634_PersonPhoto.Designer.cs
new file mode 100644
index 0000000..ffd781c
--- /dev/null
+++ b/API/FamilyTreeAPI/Migrations/20251013112634_PersonPhoto.Designer.cs
@@ -0,0 +1,229 @@
+//
+using System;
+using FamilyTreeAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace FamilyTreeAPI.Migrations
+{
+ [DbContext(typeof(FamilyTreeDBContext))]
+ [Migration("20251013112634_PersonPhoto")]
+ partial class PersonPhoto
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.4")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.Lookup", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Code")
+ .HasMaxLength(10)
+ .HasColumnType("character varying(10)")
+ .HasColumnName("code");
+
+ b.Property("Description")
+ .HasMaxLength(80)
+ .HasColumnType("character varying(80)")
+ .HasColumnName("description");
+
+ b.Property("Lactive")
+ .HasColumnType("boolean")
+ .HasColumnName("lactive");
+
+ b.Property("Type")
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)")
+ .HasColumnName("ltype");
+
+ b.HasKey("Id");
+
+ b.ToTable("lookup", (string)null);
+ });
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.Person", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Address")
+ .HasMaxLength(120)
+ .HasColumnType("character varying(120)")
+ .HasColumnName("address");
+
+ b.Property("Alive")
+ .HasColumnType("boolean")
+ .HasColumnName("alive");
+
+ b.Property("Email")
+ .HasMaxLength(80)
+ .HasColumnType("character varying(80)")
+ .HasColumnName("email");
+
+ b.Property("FatherId")
+ .HasColumnType("integer")
+ .HasColumnName("fatherid");
+
+ b.Property("FirstName")
+ .HasMaxLength(70)
+ .HasColumnType("character varying(70)")
+ .HasColumnName("firstname");
+
+ b.Property("Image")
+ .HasMaxLength(300)
+ .HasColumnType("character varying(300)")
+ .HasColumnName("image");
+
+ b.Property("LastName")
+ .HasMaxLength(70)
+ .HasColumnType("character varying(70)")
+ .HasColumnName("lastname");
+
+ b.Property("MotherId")
+ .HasColumnType("integer")
+ .HasColumnName("motherid");
+
+ b.Property("Phone")
+ .HasMaxLength(30)
+ .HasColumnType("character varying(30)")
+ .HasColumnName("phone");
+
+ b.Property("Sex")
+ .HasMaxLength(10)
+ .HasColumnType("character varying(10)")
+ .HasColumnName("sex");
+
+ b.Property("dob")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("dob");
+
+ b.HasKey("Id");
+
+ b.ToTable("person", (string)null);
+ });
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.PersonPhoto", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ImagePhoto")
+ .IsRequired()
+ .HasColumnType("bytea")
+ .HasColumnName("imagephot");
+
+ b.Property("PersonId")
+ .HasColumnType("integer")
+ .HasColumnName("personid");
+
+ b.Property("Photo")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("photo");
+
+ b.HasKey("Id");
+
+ b.ToTable("personphoto", (string)null);
+ });
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.RelationShip", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("PersonId")
+ .HasColumnType("integer")
+ .HasColumnName("personid");
+
+ b.Property("RelatePersonId")
+ .HasColumnType("integer")
+ .HasColumnName("relatepersonid");
+
+ b.HasKey("Id");
+
+ b.ToTable("relationship", (string)null);
+ });
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.staff", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Email")
+ .HasMaxLength(80)
+ .HasColumnType("character varying(80)")
+ .HasColumnName("email");
+
+ b.Property("Firstname")
+ .HasMaxLength(70)
+ .HasColumnType("character varying(70)")
+ .HasColumnName("firstname");
+
+ b.Property("Lastname")
+ .HasMaxLength(70)
+ .HasColumnType("character varying(70)")
+ .HasColumnName("lastname");
+
+ b.Property("Phone")
+ .HasMaxLength(30)
+ .HasColumnType("character varying(30)")
+ .HasColumnName("phone");
+
+ b.Property("Sactive")
+ .HasColumnType("boolean")
+ .HasColumnName("sactive");
+
+ b.Property("Spassword")
+ .HasMaxLength(200)
+ .HasColumnType("character varying(200)")
+ .HasColumnName("spassword");
+
+ b.Property("Srole")
+ .HasColumnType("integer")
+ .HasColumnName("srole");
+
+ b.Property("Stype")
+ .HasColumnType("integer")
+ .HasColumnName("stype");
+
+ b.HasKey("Id");
+
+ b.ToTable("staff", (string)null);
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/API/FamilyTreeAPI/Migrations/20251013112634_PersonPhoto.cs b/API/FamilyTreeAPI/Migrations/20251013112634_PersonPhoto.cs
new file mode 100644
index 0000000..3dcb80b
--- /dev/null
+++ b/API/FamilyTreeAPI/Migrations/20251013112634_PersonPhoto.cs
@@ -0,0 +1,128 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace FamilyTreeAPI.Migrations
+{
+ ///
+ public partial class PersonPhoto : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ /*
+ migrationBuilder.CreateTable(
+ name: "lookup",
+ columns: table => new
+ {
+ id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ code = table.Column(type: "character varying(10)", maxLength: 10, nullable: true),
+ description = table.Column(type: "character varying(80)", maxLength: 80, nullable: true),
+ ltype = table.Column(type: "character varying(20)", maxLength: 20, nullable: true),
+ lactive = table.Column(type: "boolean", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_lookup", x => x.id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "person",
+ columns: table => new
+ {
+ id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ firstname = table.Column(type: "character varying(70)", maxLength: 70, nullable: true),
+ lastname = table.Column(type: "character varying(70)", maxLength: 70, nullable: true),
+ email = table.Column(type: "character varying(80)", maxLength: 80, nullable: true),
+ phone = table.Column(type: "character varying(30)", maxLength: 30, nullable: true),
+ address = table.Column(type: "character varying(120)", maxLength: 120, nullable: true),
+ sex = table.Column(type: "character varying(10)", maxLength: 10, nullable: true),
+ image = table.Column(type: "character varying(300)", maxLength: 300, nullable: true),
+ alive = table.Column(type: "boolean", nullable: true),
+ motherid = table.Column(type: "integer", nullable: true),
+ fatherid = table.Column(type: "integer", nullable: true),
+ dob = table.Column(type: "timestamp without time zone", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_person", x => x.id);
+ });
+ */
+ migrationBuilder.CreateTable(
+ name: "personphoto",
+ columns: table => new
+ {
+ id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ personid = table.Column(type: "integer", nullable: false),
+ photo = table.Column(type: "text", nullable: false),
+ imagephot = table.Column(type: "bytea", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_personphoto", x => x.id);
+ });
+ /*
+ migrationBuilder.CreateTable(
+ name: "relationship",
+ columns: table => new
+ {
+ id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ relatepersonid = table.Column(type: "integer", nullable: false),
+ personid = table.Column(type: "integer", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_relationship", x => x.id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "staff",
+ columns: table => new
+ {
+ id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ firstname = table.Column(type: "character varying(70)", maxLength: 70, nullable: true),
+ lastname = table.Column(type: "character varying(70)", maxLength: 70, nullable: true),
+ email = table.Column(type: "character varying(80)", maxLength: 80, nullable: true),
+ phone = table.Column(type: "character varying(30)", maxLength: 30, nullable: true),
+ stype = table.Column(type: "integer", nullable: true),
+ srole = table.Column(type: "integer", nullable: true),
+ spassword = table.Column(type: "character varying(200)", maxLength: 200, nullable: true),
+ sactive = table.Column(type: "boolean", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_staff", x => x.id);
+ });
+ */
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ /*
+ migrationBuilder.DropTable(
+ name: "lookup");
+
+ migrationBuilder.DropTable(
+ name: "person");
+ migrationBuilder.DropTable(
+ name: "relationship");
+
+ migrationBuilder.DropTable(
+ name: "staff");
+ */
+
+ migrationBuilder.DropTable(
+ name: "personphoto");
+
+
+ }
+ }
+}
diff --git a/API/FamilyTreeAPI/Migrations/FamilyTreeDBContextModelSnapshot.cs b/API/FamilyTreeAPI/Migrations/FamilyTreeDBContextModelSnapshot.cs
new file mode 100644
index 0000000..efda4ea
--- /dev/null
+++ b/API/FamilyTreeAPI/Migrations/FamilyTreeDBContextModelSnapshot.cs
@@ -0,0 +1,226 @@
+//
+using System;
+using FamilyTreeAPI.Models;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace FamilyTreeAPI.Migrations
+{
+ [DbContext(typeof(FamilyTreeDBContext))]
+ partial class FamilyTreeDBContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.4")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.Lookup", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Code")
+ .HasMaxLength(10)
+ .HasColumnType("character varying(10)")
+ .HasColumnName("code");
+
+ b.Property("Description")
+ .HasMaxLength(80)
+ .HasColumnType("character varying(80)")
+ .HasColumnName("description");
+
+ b.Property("Lactive")
+ .HasColumnType("boolean")
+ .HasColumnName("lactive");
+
+ b.Property("Type")
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)")
+ .HasColumnName("ltype");
+
+ b.HasKey("Id");
+
+ b.ToTable("lookup", (string)null);
+ });
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.Person", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Address")
+ .HasMaxLength(120)
+ .HasColumnType("character varying(120)")
+ .HasColumnName("address");
+
+ b.Property("Alive")
+ .HasColumnType("boolean")
+ .HasColumnName("alive");
+
+ b.Property("Email")
+ .HasMaxLength(80)
+ .HasColumnType("character varying(80)")
+ .HasColumnName("email");
+
+ b.Property("FatherId")
+ .HasColumnType("integer")
+ .HasColumnName("fatherid");
+
+ b.Property("FirstName")
+ .HasMaxLength(70)
+ .HasColumnType("character varying(70)")
+ .HasColumnName("firstname");
+
+ b.Property("Image")
+ .HasMaxLength(300)
+ .HasColumnType("character varying(300)")
+ .HasColumnName("image");
+
+ b.Property("LastName")
+ .HasMaxLength(70)
+ .HasColumnType("character varying(70)")
+ .HasColumnName("lastname");
+
+ b.Property("MotherId")
+ .HasColumnType("integer")
+ .HasColumnName("motherid");
+
+ b.Property("Phone")
+ .HasMaxLength(30)
+ .HasColumnType("character varying(30)")
+ .HasColumnName("phone");
+
+ b.Property("Sex")
+ .HasMaxLength(10)
+ .HasColumnType("character varying(10)")
+ .HasColumnName("sex");
+
+ b.Property("dob")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("dob");
+
+ b.HasKey("Id");
+
+ b.ToTable("person", (string)null);
+ });
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.PersonPhoto", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ImagePhoto")
+ .IsRequired()
+ .HasColumnType("bytea")
+ .HasColumnName("imagephot");
+
+ b.Property("PersonId")
+ .HasColumnType("integer")
+ .HasColumnName("personid");
+
+ b.Property("Photo")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("photo");
+
+ b.HasKey("Id");
+
+ b.ToTable("personphoto", (string)null);
+ });
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.RelationShip", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("PersonId")
+ .HasColumnType("integer")
+ .HasColumnName("personid");
+
+ b.Property("RelatePersonId")
+ .HasColumnType("integer")
+ .HasColumnName("relatepersonid");
+
+ b.HasKey("Id");
+
+ b.ToTable("relationship", (string)null);
+ });
+
+ modelBuilder.Entity("FamilyTreeAPI.Models.staff", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Email")
+ .HasMaxLength(80)
+ .HasColumnType("character varying(80)")
+ .HasColumnName("email");
+
+ b.Property("Firstname")
+ .HasMaxLength(70)
+ .HasColumnType("character varying(70)")
+ .HasColumnName("firstname");
+
+ b.Property("Lastname")
+ .HasMaxLength(70)
+ .HasColumnType("character varying(70)")
+ .HasColumnName("lastname");
+
+ b.Property("Phone")
+ .HasMaxLength(30)
+ .HasColumnType("character varying(30)")
+ .HasColumnName("phone");
+
+ b.Property("Sactive")
+ .HasColumnType("boolean")
+ .HasColumnName("sactive");
+
+ b.Property("Spassword")
+ .HasMaxLength(200)
+ .HasColumnType("character varying(200)")
+ .HasColumnName("spassword");
+
+ b.Property("Srole")
+ .HasColumnType("integer")
+ .HasColumnName("srole");
+
+ b.Property("Stype")
+ .HasColumnType("integer")
+ .HasColumnName("stype");
+
+ b.HasKey("Id");
+
+ b.ToTable("staff", (string)null);
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/API/FamilyTreeAPI/Models/FamilyTreeDBContext.cs b/API/FamilyTreeAPI/Models/FamilyTreeDBContext.cs
index 63444af..594d434 100644
--- a/API/FamilyTreeAPI/Models/FamilyTreeDBContext.cs
+++ b/API/FamilyTreeAPI/Models/FamilyTreeDBContext.cs
@@ -21,8 +21,8 @@ namespace FamilyTreeAPI.Models
public virtual DbSet RelationShips { get; set; } = null!;
public virtual DbSet Lookups { get; set; } = null!;
public virtual DbSet staff { get; set; } = null!;
+ public virtual DbSet PersonPhotos { get; set; } = null!;
-
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
@@ -74,6 +74,18 @@ namespace FamilyTreeAPI.Models
});
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("personphoto");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.PersonId).HasColumnName("personid");
+ entity.Property(e => e.Photo).HasColumnName("photo");
+ entity.Property(e => e.ImagePhoto).HasColumnName("imagephot"); //try to store binary in table. "bytea"
+
+ });
+
+
modelBuilder.Entity(entity =>
{
entity.ToTable("lookup");
diff --git a/API/FamilyTreeAPI/Models/PersonPhoto.cs b/API/FamilyTreeAPI/Models/PersonPhoto.cs
new file mode 100644
index 0000000..252d385
--- /dev/null
+++ b/API/FamilyTreeAPI/Models/PersonPhoto.cs
@@ -0,0 +1,13 @@
+namespace FamilyTreeAPI.Models
+{
+ public class PersonPhoto
+ {
+ public int Id { get; set; }
+
+ public int PersonId { get; set; }
+ public string Photo { get; set; }
+
+ public byte[] ImagePhoto { get; set; }
+
+ }
+}