Skip to content

Commit 28b1acd

Browse files
committed
Initial Design Of Postgres Shared Kernel
1 parent 69c1bdb commit 28b1acd

35 files changed

+1510
-56
lines changed

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Deploy NuGet Package
22

33
env:
4-
PROJECT_PATH: './src/PandaNuGet/PandaNuGet.csproj'
4+
PROJECT_PATH: './src/SharedKernel.Postgres/SharedKernel.Postgres.csproj'
55
OUTPUT_DIR: 'nupkgs'
66
NUGET_SOURCE: 'https://api.nuget.org/v3/index.json'
77
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}

Readme.md

+91-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,99 @@
1-
# Pandatech.***
1+
# Pandatech.SharedKernel.Postgres
22

3-
## Introduction
3+
Welcome to the `Pandatech.SharedKernel.Postgres` NuGet package — a specialized extension of the Pandatech.SharedKernel
4+
designed to simplify PostgreSQL integration in your ASP.NET Core applications. This package provides a set of utilities
5+
and configurations to streamline the setup of Entity Framework Core with PostgreSQL, along with health checks and other
6+
enhancements.
47

5-
## Features
8+
Although this package is primarily intended for internal use, it is publicly available for anyone who may find it
9+
useful. We recommend forking or copying the classes in this repository and creating your own package to suit your needs.
10+
11+
## Key Features
12+
13+
- **Simplified PostgreSQL Context Setup:** Easily configure your DbContext to use PostgreSQL with optimized settings.
14+
- **Automatic Database Migration:** Automatically apply pending migrations to the database on application startup.
15+
- **Decimal Type Configuration:** Globally configure the precision and scale for decimal properties.
16+
- **PostgreSQL Health Checks:** Integrate health checks for PostgreSQL to monitor database connectivity and health.
17+
- **Exception Handling:** Utilize exception processing to handle database-specific exceptions gracefully.
18+
- **Integration with SharedKernel:** Seamlessly integrates with Pandatech.SharedKernel and other PandaTech packages.
19+
20+
## Prerequisites
21+
22+
- .NET 9.0 SDK or higher
23+
- PostgreSQL database
24+
- Entity Framework Core Tools and Design packages
625

726
## Installation
827

9-
## Usage
28+
To install the `Pandatech.SharedKernel.Postgres` package, use the following command:
29+
30+
```bash
31+
dotnet add package Pandatech.SharedKernel.Postgres
32+
```
33+
34+
Alternatively, you can add it via the NuGet Package Manager in Visual Studio, VS Code, or Rider.
35+
36+
## Getting Started
37+
38+
Follow these steps to integrate `Pandatech.SharedKernel.Postgres` into your ASP.NET Core application.
39+
40+
### Step 1: Configure Connection String
41+
42+
Add your PostgreSQL connection string to the `appsettings.{Environment}.json` file:
43+
44+
```json
45+
{
46+
"ConnectionStrings": {
47+
"Postgres": "Host=localhost;Database=mydatabase;Username=myusername;Password=mypassword"
48+
}
49+
}
50+
```
51+
52+
### Step 2: Modify Program.cs
53+
54+
Update your `Program.cs` file to include the necessary configurations:
55+
56+
```csharp
57+
using SharedKernel.Postgres.Extensions;
58+
59+
var builder = WebApplication.CreateBuilder(args);
60+
61+
// Add PostgreSQL context with the connection string
62+
builder.AddPostgresContext<MyDbContext>(builder.Configuration.GetConnectionString("Postgres")!);
63+
64+
// Optionally add Gridify for data filtering and pagination
65+
builder.AddGridify(); // From Pandatech.Gridify.Extensions
66+
67+
var app = builder.Build();
68+
69+
// Apply pending migrations on startup
70+
app.MigrateDatabase<MyDbContext>();
71+
72+
app.Run();
73+
74+
```
75+
76+
By invoking `builder.AddPostgresContext<T>()`, the package automatically integrates PostgreSQL health checks using the
77+
`AspNetCore.HealthChecks.NpgSql` package.
78+
79+
## Dependencies
80+
81+
This package relies on several NuGet packages to provide extended functionality:
82+
83+
- AspNetCore.HealthChecks.NpgSql: Health checks for PostgreSQL.
84+
- EntityFrameworkCore.Exceptions.PostgreSQL: Exception handling for EF Core and PostgreSQL.
85+
- Pandatech.EFCore.AuditBase: Audit logging for EF Core entities.
86+
- Pandatech.EFCore.PostgresExtensions: Additional extensions for EF Core and PostgreSQL.
87+
- PandaTech.FileExporter: Utilities for exporting files.
88+
- PandaTech.FluentImporter: Fluent API for importing data.
89+
- Pandatech.GridifyExtensions: Extensions for Gridify, simplifying data filtering and pagination.
90+
- Pandatech.SharedKernel: Core shared kernel functionalities.
91+
92+
## Notes
93+
94+
This library is designed primarily for internal use and, as such, does not include extensive documentation. For detailed
95+
information on the functionalities provided by the dependencies, please refer to their respective documentation.
1096

1197
## License
1298

13-
Pandatech.*** is licensed under the MIT License.
99+
Pandatech.SharedKernel.Postgres is licensed under the MIT License.

PandaNuGet.sln renamed to SharedKernel.Postgres.sln

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PandaNuGet", "src\PandaNuGet\PandaNuGet.csproj", "{25001943-A870-4E17-A9B9-0D190CEC819B}"
3+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedKernel.Postgres", "src\SharedKernel.Postgres\SharedKernel.Postgres.csproj", "{25001943-A870-4E17-A9B9-0D190CEC819B}"
44
EndProject
5-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PandaNuGet.Tests", "test\PandaNuGet.Tests\PandaNuGet.Tests.csproj", "{0305E58F-1C47-454C-B10B-A223F2561A85}"
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedKernel.Postgres.Tests", "test\SharedKernel.Postgres.Tests\SharedKernel.Postgres.Tests.csproj", "{0305E58F-1C47-454C-B10B-A223F2561A85}"
66
EndProject
7-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PandaNuGet.Demo", "test\PandaNuGet.Demo\PandaNuGet.Demo.csproj", "{8A6AA36D-1CEF-4018-9C9D-7D029F3EAECE}"
7+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedKernel.Postgres.Demo", "test\SharedKernel.Postgres.Demo\SharedKernel.Postgres.Demo.csproj", "{8A6AA36D-1CEF-4018-9C9D-7D029F3EAECE}"
88
EndProject
99
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F8A6DCFE-8924-49A4-B3E9-2034593F54E5}"
1010
EndProject
@@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1919
.editorconfig = .editorconfig
2020
EndProjectSection
2121
EndProject
22+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCore.NamingConventions.Temp", "src\EFCore.NamingConventions.Temp\EFCore.NamingConventions.Temp.csproj", "{2525193C-2D84-43F7-BC69-06F1ADA6CD7D}"
23+
EndProject
2224
Global
2325
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2426
Debug|Any CPU = Debug|Any CPU
@@ -37,10 +39,15 @@ Global
3739
{8A6AA36D-1CEF-4018-9C9D-7D029F3EAECE}.Debug|Any CPU.Build.0 = Debug|Any CPU
3840
{8A6AA36D-1CEF-4018-9C9D-7D029F3EAECE}.Release|Any CPU.ActiveCfg = Release|Any CPU
3941
{8A6AA36D-1CEF-4018-9C9D-7D029F3EAECE}.Release|Any CPU.Build.0 = Release|Any CPU
42+
{2525193C-2D84-43F7-BC69-06F1ADA6CD7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43+
{2525193C-2D84-43F7-BC69-06F1ADA6CD7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
44+
{2525193C-2D84-43F7-BC69-06F1ADA6CD7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
45+
{2525193C-2D84-43F7-BC69-06F1ADA6CD7D}.Release|Any CPU.Build.0 = Release|Any CPU
4046
EndGlobalSection
4147
GlobalSection(NestedProjects) = preSolution
4248
{25001943-A870-4E17-A9B9-0D190CEC819B} = {F8A6DCFE-8924-49A4-B3E9-2034593F54E5}
4349
{8A6AA36D-1CEF-4018-9C9D-7D029F3EAECE} = {FEE159A2-74A0-4469-9B93-52987CA1A3CA}
4450
{0305E58F-1C47-454C-B10B-A223F2561A85} = {FEE159A2-74A0-4469-9B93-52987CA1A3CA}
51+
{2525193C-2D84-43F7-BC69-06F1ADA6CD7D} = {F8A6DCFE-8924-49A4-B3E9-2034593F54E5}
4552
EndGlobalSection
4653
EndGlobal

global.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "9.0.0",
3+
"version": "9.0.100",
44
"rollForward": "latestMinor"
55
}
66
}
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Linq;
5+
using JetBrains.Annotations;
6+
using Microsoft.EntityFrameworkCore.Diagnostics;
7+
8+
// ReSharper disable once CheckNamespace
9+
namespace Microsoft.EntityFrameworkCore;
10+
11+
[DebuggerStepThrough]
12+
internal static class Check
13+
{
14+
[ContractAnnotation("value:null => halt")]
15+
public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName] string parameterName)
16+
{
17+
if (ReferenceEquals(value, null))
18+
{
19+
NotEmpty(parameterName, nameof(parameterName));
20+
21+
throw new ArgumentNullException(parameterName);
22+
}
23+
24+
return value;
25+
}
26+
27+
[ContractAnnotation("value:null => halt")]
28+
public static T NotNull<T>(
29+
[NoEnumeration] T value,
30+
[InvokerParameterName] string parameterName,
31+
string propertyName)
32+
{
33+
if (ReferenceEquals(value, null))
34+
{
35+
NotEmpty(parameterName, nameof(parameterName));
36+
NotEmpty(propertyName, nameof(propertyName));
37+
38+
throw new ArgumentException(CoreStrings.ArgumentPropertyNull(propertyName, parameterName));
39+
}
40+
41+
return value;
42+
}
43+
44+
[ContractAnnotation("value:null => halt")]
45+
public static IReadOnlyList<T> NotEmpty<T>(IReadOnlyList<T> value, [InvokerParameterName] string parameterName)
46+
{
47+
NotNull(value, parameterName);
48+
49+
if (value.Count == 0)
50+
{
51+
NotEmpty(parameterName, nameof(parameterName));
52+
53+
throw new ArgumentException(AbstractionsStrings.CollectionArgumentIsEmpty(parameterName));
54+
}
55+
56+
return value;
57+
}
58+
59+
[ContractAnnotation("value:null => halt")]
60+
public static string NotEmpty(string? value, [InvokerParameterName] string parameterName)
61+
{
62+
if (value is null)
63+
{
64+
NotEmpty(parameterName, nameof(parameterName));
65+
66+
throw new ArgumentNullException(parameterName);
67+
}
68+
69+
if (value.Trim().Length == 0)
70+
{
71+
NotEmpty(parameterName, nameof(parameterName));
72+
73+
throw new ArgumentException(AbstractionsStrings.ArgumentIsEmpty(parameterName));
74+
}
75+
76+
return value;
77+
}
78+
79+
public static string? NullButNotEmpty(string? value, [InvokerParameterName] string parameterName)
80+
{
81+
if (value is not null && value.Length == 0)
82+
{
83+
NotEmpty(parameterName, nameof(parameterName));
84+
85+
throw new ArgumentException(AbstractionsStrings.ArgumentIsEmpty(parameterName));
86+
}
87+
88+
return value;
89+
}
90+
91+
public static IReadOnlyList<T> HasNoNulls<T>(IReadOnlyList<T> value, [InvokerParameterName] string parameterName)
92+
where T : class
93+
{
94+
NotNull(value, parameterName);
95+
96+
if (value.Any(e => e == null))
97+
{
98+
NotEmpty(parameterName, nameof(parameterName));
99+
100+
throw new ArgumentException(parameterName);
101+
}
102+
103+
return value;
104+
}
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using System;
2+
3+
// ReSharper disable once CheckNamespace
4+
namespace JetBrains.Annotations;
5+
6+
[AttributeUsage(
7+
AttributeTargets.Method | AttributeTargets.Parameter |
8+
AttributeTargets.Property | AttributeTargets.Delegate |
9+
AttributeTargets.Field)]
10+
internal sealed class NotNullAttribute : Attribute
11+
{
12+
}
13+
14+
[AttributeUsage(
15+
AttributeTargets.Method | AttributeTargets.Parameter |
16+
AttributeTargets.Property | AttributeTargets.Delegate |
17+
AttributeTargets.Field)]
18+
internal sealed class CanBeNullAttribute : Attribute
19+
{
20+
}
21+
22+
[AttributeUsage(AttributeTargets.Parameter)]
23+
internal sealed class InvokerParameterNameAttribute : Attribute
24+
{
25+
}
26+
27+
[AttributeUsage(AttributeTargets.Parameter)]
28+
internal sealed class NoEnumerationAttribute : Attribute
29+
{
30+
}
31+
32+
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
33+
internal sealed class ContractAnnotationAttribute : Attribute
34+
{
35+
public string Contract { get; }
36+
37+
public bool ForceFullStates { get; }
38+
39+
public ContractAnnotationAttribute([NotNull] string contract)
40+
: this(contract, false)
41+
{
42+
}
43+
44+
public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
45+
{
46+
Contract = contract;
47+
ForceFullStates = forceFullStates;
48+
}
49+
}
50+
51+
[AttributeUsage(AttributeTargets.All)]
52+
internal sealed class UsedImplicitlyAttribute : Attribute
53+
{
54+
public UsedImplicitlyAttribute()
55+
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default)
56+
{
57+
}
58+
59+
public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
60+
: this(useKindFlags, ImplicitUseTargetFlags.Default)
61+
{
62+
}
63+
64+
public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
65+
: this(ImplicitUseKindFlags.Default, targetFlags)
66+
{
67+
}
68+
69+
public UsedImplicitlyAttribute(
70+
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
71+
{
72+
UseKindFlags = useKindFlags;
73+
TargetFlags = targetFlags;
74+
}
75+
76+
public ImplicitUseKindFlags UseKindFlags { get; }
77+
public ImplicitUseTargetFlags TargetFlags { get; }
78+
}
79+
80+
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Delegate)]
81+
internal sealed class StringFormatMethodAttribute : Attribute
82+
{
83+
public StringFormatMethodAttribute([NotNull] string formatParameterName)
84+
=> FormatParameterName = formatParameterName;
85+
86+
[NotNull]
87+
public string FormatParameterName { get; }
88+
}
89+
90+
[Flags]
91+
internal enum ImplicitUseKindFlags
92+
{
93+
Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
94+
Access = 1,
95+
Assign = 2,
96+
InstantiatedWithFixedConstructorSignature = 4,
97+
InstantiatedNoFixedConstructorSignature = 8
98+
}
99+
100+
[Flags]
101+
internal enum ImplicitUseTargetFlags
102+
{
103+
Default = Itself,
104+
Itself = 1,
105+
Members = 2,
106+
WithMembers = Itself | Members
107+
}

0 commit comments

Comments
 (0)