Skip to content

Commit

Permalink
Added database objects for the Page
Browse files Browse the repository at this point in the history
  • Loading branch information
csharpfritz committed Oct 31, 2024
1 parent 66ebc17 commit 69200da
Show file tree
Hide file tree
Showing 10 changed files with 453 additions and 134 deletions.
14 changes: 14 additions & 0 deletions SharpSite.Abstractions/IPageRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Linq.Expressions;

namespace SharpSite.Abstractions;

public interface IPageRepository
{

Task<Page> AddPage(Page page);
Task DeletePage(int id);
Task<Page?> GetPage(string slug);
Task<IEnumerable<Page>> GetPages();
Task<IEnumerable<Page>> GetPages(Expression<Func<Page, bool>> where);

}
19 changes: 19 additions & 0 deletions SharpSite.Abstractions/Page.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;

namespace SharpSite.Abstractions;

public class Page
{

[Key]
public int Id {get; set;}

[Required, MinLength(4), MaxLength(100)]
public string Title {get; set;} = string.Empty;

[Required]
public required string Slug {get; set;}

public string Content {get; set;} = string.Empty;

}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;

#nullable disable

namespace SharpSite.Data.Postgres.Migrations
{
/// <inheritdoc />
public partial class AddPagetodatabase : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Pages",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Title = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
Slug = table.Column<string>(type: "text", nullable: false),
Content = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Pages", x => x.Id);
});

migrationBuilder.CreateIndex(
name: "IX_Pages_Slug",
table: "Pages",
column: "Slug",
unique: true);
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Pages");
}
}
}
29 changes: 29 additions & 0 deletions SharpSite.Data.Postgres/Migrations/PgContextModelSnapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,35 @@ protected override void BuildModel(ModelBuilder modelBuilder)

NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);

modelBuilder.Entity("SharpSite.Data.Postgres.PgPage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Content")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.HasKey("Id");
b.HasIndex("Slug")
.IsUnique();
b.ToTable("Pages");
});

modelBuilder.Entity("SharpSite.Data.Postgres.PgPost", b =>
{
b.Property<string>("Slug")
Expand Down
68 changes: 38 additions & 30 deletions SharpSite.Data.Postgres/PgContext.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace SharpSite.Data.Postgres;

public class PgContext : DbContext
{

public PgContext(DbContextOptions<PgContext> options) : base(options) { }

public DbSet<PgPost> Posts => Set<PgPost>();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<PgPost>()
.Property(e => e.Published)
.HasConversion(new DateTimeOffsetConverter());
}

}

public class DateTimeOffsetConverter : ValueConverter<DateTimeOffset, DateTimeOffset>
{
public DateTimeOffsetConverter() : base(
v => v.UtcDateTime,
v => v)
{
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace SharpSite.Data.Postgres;

public class PgContext : DbContext
{

public PgContext(DbContextOptions<PgContext> options) : base(options) { }

public DbSet<PgPage> Pages => Set<PgPage>();

public DbSet<PgPost> Posts => Set<PgPost>();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{

modelBuilder.Entity<PgPage>()
.HasIndex(p => p.Slug)
.IsUnique();

modelBuilder
.Entity<PgPost>()
.Property(e => e.Published)
.HasConversion(new DateTimeOffsetConverter());

}

}

public class DateTimeOffsetConverter : ValueConverter<DateTimeOffset, DateTimeOffset>
{
public DateTimeOffsetConverter() : base(
v => v.UtcDateTime,
v => v)
{
}
}
44 changes: 44 additions & 0 deletions SharpSite.Data.Postgres/PgPage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using SharpSite.Abstractions;
using System.ComponentModel.DataAnnotations;

namespace SharpSite.Data.Postgres;

public class PgPage
{

[Key]
public int Id {get; set;}

[Required, MinLength(4), MaxLength(100)]
public string Title {get; set;} = string.Empty;

[Required]
public required string Slug {get; set;}

public string Content {get; set;} = string.Empty;

public static explicit operator PgPage(Page page)
{

return new PgPage
{
Id = page.Id,
Title = page.Title,
Slug = page.Slug,
Content = page.Content
};

}

public static explicit operator Page(PgPage page)
{
return new Page
{
Id = page.Id,
Title = page.Title,
Slug = page.Slug,
Content = page.Content
};
}

}
75 changes: 75 additions & 0 deletions SharpSite.Data.Postgres/PgPageRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using SharpSite.Abstractions;

namespace SharpSite.Data.Postgres;

public class PgPageRepository(PgContext Context) : IPageRepository
{
public async Task<Page> AddPage(Page page)
{

// Add the page to the database
await Context.Pages.AddAsync((PgPage)page);
await Context.SaveChangesAsync();

return page;

}

public async Task DeletePage(int id)
{
// delete the page identified with a given id
var page = Context.Pages.Find(id);

if (page == null)
{
throw new Exception("Page not found");
}

Context.Pages.Remove(page);
await Context.SaveChangesAsync();

}

public async Task<Page?> GetPage(string slug)
{

// get the page with a given slug
var page = await Context.Pages
.AsNoTracking()
.FirstOrDefaultAsync(p => p.Slug == slug);

// check for a page with the given slug
if (page == null)
{
return null;
}

return (Page?)page;

}

public async Task<IEnumerable<Page>> GetPages()
{
// get all pages from the database
return (await Context.Pages.AsNoTracking().ToListAsync())
.Select(p => (Page)p)
.ToList();

}

public async Task<IEnumerable<Page>> GetPages(Expression<Func<Page, bool>> where)
{

// get all pages from the database that satisfy the given condition
return await Context.Pages
.AsNoTracking()
.Where(p => where.Compile().Invoke((Page)p))
.Select(p => (Page)p)
.ToListAsync();

}

}
Loading

0 comments on commit 69200da

Please sign in to comment.