Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Replace Azure SQL Edge with PostgreSQL #1156

Merged
merged 1 commit into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/WeatherForecast/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1"/>
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.1"/>
<PackageVersion Include="Microsoft.Fast.Components.FluentUI" Version="3.5.4"/>
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2"/>
<!-- Unit and integration test dependencies: -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.1"/>
<PackageVersion Include="Testcontainers.SqlEdge" Version="3.7.0"/>
<PackageVersion Include="Testcontainers.PostgreSql" Version="3.8.0"/>
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7"/>
<PackageVersion Include="xunit" Version="2.7.0"/>
<!-- Third-party client dependencies to connect and interact with the containers: -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Map all read-only properties. There is not [Mapped] attribute like [NotMapped].
modelBuilder.Entity<WeatherData>().Property(weatherData => weatherData.Id);
modelBuilder.Entity<WeatherData>().Property(weatherData => weatherData.Date);
modelBuilder.Entity<WeatherData>().Property(weatherData => weatherData.Period);
modelBuilder.Entity<Temperature>().Property(temperature => temperature.Id);
modelBuilder.Entity<Temperature>().Property(temperature => temperature.UnitName);
modelBuilder.Entity<Temperature>().Property(temperature => temperature.UnitSymbol);
modelBuilder.Entity<Temperature>().Property(temperature => temperature.Value);
modelBuilder.Entity<Temperature>().Property(temperature => temperature.Measured);
modelBuilder.Entity<WeatherData>().HasMany(weatherData => weatherData.Temperatures).WithOne().HasForeignKey(temperature => temperature.BelongsTo);

var weatherDataSeed = Enumerable.Range(0, 30).Select(_ => Guid.NewGuid()).Select((id, day) => new WeatherData(id, DateTime.Today.AddDays(day))).ToList();
var temperatureSeed = weatherDataSeed.SelectMany(data => Enumerable.Range(0, 23).Select(hour => Temperature.Celsius(data.Id, Random.Shared.Next(-10, 30), data.Date.AddHours(hour)))).ToList();
var weatherDataSeed = Enumerable.Range(0, 30).Select(_ => Guid.NewGuid()).Select((id, day) => new WeatherData(id, DateTimeOffset.Now.AddDays(day))).ToList();
var temperatureSeed = weatherDataSeed.SelectMany(data => Enumerable.Range(0, 23).Select(hour => Temperature.Celsius(data.Id, Random.Shared.Next(-10, 30), data.Period.AddHours(hour)))).ToList();

modelBuilder.Entity<Temperature>().HasData(temperatureSeed);
modelBuilder.Entity<WeatherData>().HasData(weatherDataSeed);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public Task<IEnumerable<WeatherData>> GetAllAsync()

public Task<IEnumerable<WeatherData>> GetAllAsync(string latitude, string longitude, DateTime from, DateTime to)
{
return Task.FromResult<IEnumerable<WeatherData>>(_context.WeatherData.Include(property => property.Temperatures).OrderBy(weatherData => weatherData.Date).Take(to.Subtract(from).Days));
return Task.FromResult<IEnumerable<WeatherData>>(_context.WeatherData.Include(property => property.Temperatures).OrderBy(weatherData => weatherData.Period).Take(to.Subtract(from).Days));
}

public Task<WeatherData> GetAsync(Guid id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace WeatherForecast.Entities;
public sealed class Temperature : HasId
{
[JsonConstructor]
public Temperature(Guid id, Guid belongsTo, string unitName, string unitSymbol, double value, DateTime measured) : base(id)
public Temperature(Guid id, Guid belongsTo, string unitName, string unitSymbol, double value, DateTimeOffset measured) : base(id)
{
BelongsTo = belongsTo;
UnitName = unitName;
Expand All @@ -13,7 +13,7 @@ public Temperature(Guid id, Guid belongsTo, string unitName, string unitSymbol,
Measured = measured;
}

public static Temperature AbsoluteZero { get; } = Kelvin(Guid.Empty, 0, DateTime.MinValue);
public static Temperature AbsoluteZero { get; } = Kelvin(Guid.Empty, 0, DateTimeOffset.MinValue);

[JsonPropertyName("belongsTo")]
public Guid BelongsTo { get; }
Expand All @@ -28,19 +28,19 @@ public Temperature(Guid id, Guid belongsTo, string unitName, string unitSymbol,
public double Value { get; }

[JsonPropertyName("measured")]
public DateTime Measured { get; }
public DateTimeOffset Measured { get; }

public static Temperature Kelvin(Guid belongsTo, double value, DateTime measured)
public static Temperature Kelvin(Guid belongsTo, double value, DateTimeOffset measured)
{
return new Temperature(Guid.NewGuid(), belongsTo, "Kelvin", "K", value, measured);
}

public static Temperature Celsius(Guid belongsTo, double value, DateTime measured)
public static Temperature Celsius(Guid belongsTo, double value, DateTimeOffset measured)
{
return new Temperature(Guid.NewGuid(), belongsTo, "degree Celsius", "°C", value, measured);
}

public static Temperature Fahrenheit(Guid belongsTo, double value, DateTime measured)
public static Temperature Fahrenheit(Guid belongsTo, double value, DateTimeOffset measured)
{
return new Temperature(Guid.NewGuid(), belongsTo, "degree Fahrenheit", "°F", value, measured);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ namespace WeatherForecast.Entities;
[PublicAPI]
public sealed class WeatherData : HasId
{
public WeatherData(Guid id, DateTime date) : this(id, date, new List<Temperature>())
public WeatherData(Guid id, DateTimeOffset period) : this(id, period, new List<Temperature>())
{
// Entity Framework constructor.
}

[JsonConstructor]
public WeatherData(Guid id, DateTime date, IList<Temperature> temperatures) : base(id)
public WeatherData(Guid id, DateTimeOffset period, IList<Temperature> temperatures) : base(id)
{
Date = date;
Period = period;
Minimum = temperatures.OrderBy(temperature => temperature.Value).DefaultIfEmpty(Temperature.AbsoluteZero).First();
Maximum = temperatures.OrderBy(temperature => temperature.Value).DefaultIfEmpty(Temperature.AbsoluteZero).Last();
Temperatures = temperatures;
}

[JsonPropertyName("date")]
public DateTime Date { get; }
[JsonPropertyName("period")]
public DateTimeOffset Period { get; }

[JsonIgnore]
public Temperature Minimum { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public sealed class WeatherForecastController : ControllerBase, IDisposable
{
private readonly ISearchCityOrZipCode _searchCityOrZipCode;

private readonly EventWaitHandle _wait = new AutoResetEvent(false);
private readonly SemaphoreSlim _wait = new SemaphoreSlim(0, 1);

private IEnumerable<WeatherData> _weatherData = Array.Empty<WeatherData>();

Expand All @@ -29,7 +29,8 @@ public async Task<ActionResult<IEnumerable<WeatherData>>> GetWeatherForecast()
await _searchCityOrZipCode.ExecuteAsync(string.Empty)
.ConfigureAwait(false);

_wait.WaitOne();
await _wait.WaitAsync()
.ConfigureAwait(false);

return Ok(_weatherData);
}
Expand All @@ -41,6 +42,6 @@ private void SearchCityOrZipCodeResultPublished(object? sender, ResultInfo<IEnum
_weatherData = result.Value;
}

_wait.Set();
_wait.Release();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ namespace WeatherForecast;

public sealed class DatabaseContainer : IHostedService
{
private readonly SqlEdgeContainer _sqlEdgeContainer = new SqlEdgeBuilder().Build();
private readonly PostgreSqlContainer _postgreSqlContainer = new PostgreSqlBuilder().Build();

public Task StartAsync(CancellationToken cancellationToken)
{
return _sqlEdgeContainer.StartAsync(cancellationToken);
return _postgreSqlContainer.StartAsync(cancellationToken);
}

public Task StopAsync(CancellationToken cancellationToken)
{
return _sqlEdgeContainer.StopAsync(cancellationToken);
return _postgreSqlContainer.StopAsync(cancellationToken);
}

public string GetConnectionString()
{
return _sqlEdgeContainer.GetConnectionString();
return _postgreSqlContainer.GetConnectionString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<h1>Weather Forecast</h1>
<FluentDataGrid Items="@_weatherData.AsQueryable()">
<ChildContent>
<PropertyColumn Title="Date" Property="@(item => item.Date.ToShortDateString())"/>
<PropertyColumn Title="Period" Property="@(item => item.Period.Date.ToShortDateString())"/>
<PropertyColumn Title="Avg °C" Property="@(item => item.Temperatures.Average(temperature => temperature.Value).ToString("0"))"/>
</ChildContent>
<EmptyContent></EmptyContent>
Expand Down
4 changes: 2 additions & 2 deletions examples/WeatherForecast/src/WeatherForecast/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
builder.Services.AddDbContext<WeatherDataContext>((services, options) =>
{
var databaseContainer = services.GetRequiredService<DatabaseContainer>();
options.UseSqlServer(databaseContainer.GetConnectionString());
options.UseNpgsql(databaseContainer.GetConnectionString());
});
}
else
{
// The application configuration includes a database connection string, use it to establish a connection and seed the database.
builder.Services.AddDbContext<WeatherDataContext>((_, options) => options.UseSqlServer(connectionString));
builder.Services.AddDbContext<WeatherDataContext>((_, options) => options.UseNpgsql(connectionString));
}

builder.Services.AddScoped<IWeatherDataReadOnlyRepository, WeatherDataReadOnlyContext>();
Expand Down
2 changes: 1 addition & 1 deletion examples/WeatherForecast/src/WeatherForecast/Usings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Fast.Components.FluentUI;
global using Testcontainers.SqlEdge;
global using Testcontainers.PostgreSql;
global using WeatherForecast;
global using WeatherForecast.Contexts;
global using WeatherForecast.Entities;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer"/>
<PackageReference Include="Microsoft.Fast.Components.FluentUI"/>
<PackageReference Include="Testcontainers.SqlEdge"/>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL"/>
<PackageReference Include="Testcontainers.PostgreSql"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../WeatherForecast.Contexts/WeatherForecast.Contexts.csproj"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
global using JetBrains.Annotations;
global using Microsoft.AspNetCore.Mvc.Testing;
global using Microsoft.Extensions.DependencyInjection;
global using Testcontainers.SqlEdge;
global using Testcontainers.PostgreSql;
global using WeatherForecast.Entities;
global using WeatherForecast.Repositories;
global using Xunit;
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ namespace WeatherForecast.InProcess.Tests;
[UsedImplicitly]
public sealed class WeatherForecastTest : IAsyncLifetime
{
private readonly SqlEdgeContainer _sqlEdgeContainer = new SqlEdgeBuilder().Build();
private readonly PostgreSqlContainer _postgreSqlContainer = new PostgreSqlBuilder().Build();

public Task InitializeAsync()
{
return _sqlEdgeContainer.StartAsync();
return _postgreSqlContainer.StartAsync();
}

public Task DisposeAsync()
{
return _sqlEdgeContainer.DisposeAsync().AsTask();
return _postgreSqlContainer.DisposeAsync().AsTask();
}

public sealed class Api : IClassFixture<WeatherForecastTest>, IDisposable
Expand All @@ -30,7 +30,7 @@ public Api(WeatherForecastTest weatherForecastTest)
Environment.SetEnvironmentVariable("ASPNETCORE_URLS", "https://+");
Environment.SetEnvironmentVariable("ASPNETCORE_Kestrel__Certificates__Default__Path", "certificate.crt");
Environment.SetEnvironmentVariable("ASPNETCORE_Kestrel__Certificates__Default__Password", "password");
Environment.SetEnvironmentVariable("ConnectionStrings__DefaultConnection", weatherForecastTest._sqlEdgeContainer.GetConnectionString());
Environment.SetEnvironmentVariable("ConnectionStrings__DefaultConnection", weatherForecastTest._postgreSqlContainer.GetConnectionString());
_webApplicationFactory = new WebApplicationFactory<Program>();
_serviceScope = _webApplicationFactory.Services.GetRequiredService<IServiceScopeFactory>().CreateScope();
_httpClient = _webApplicationFactory.CreateClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
global using DotNet.Testcontainers.Images;
global using DotNet.Testcontainers.Networks;
global using JetBrains.Annotations;
global using Testcontainers.SqlEdge;
global using Testcontainers.PostgreSql;
global using WeatherForecast.Entities;
global using Xunit;
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public sealed class WeatherForecastContainer : HttpClient, IAsyncLifetime

private readonly INetwork _weatherForecastNetwork;

private readonly IContainer _sqlEdgeContainer;
private readonly IContainer _postgreSqlContainer;

private readonly IContainer _weatherForecastContainer;

Expand All @@ -22,12 +22,12 @@ public WeatherForecastContainer()
{
const string weatherForecastStorage = "weatherForecastStorage";

const string connectionString = $"Server={weatherForecastStorage};User Id={SqlEdgeBuilder.DefaultUsername};Password={SqlEdgeBuilder.DefaultPassword};Database={SqlEdgeBuilder.DefaultDatabase};TrustServerCertificate=True";
const string connectionString = $"Host={weatherForecastStorage};Username={PostgreSqlBuilder.DefaultUsername};Password={PostgreSqlBuilder.DefaultPassword};Database={PostgreSqlBuilder.DefaultDatabase}";

_weatherForecastNetwork = new NetworkBuilder()
.Build();

_sqlEdgeContainer = new SqlEdgeBuilder()
_postgreSqlContainer = new PostgreSqlBuilder()
.WithNetwork(_weatherForecastNetwork)
.WithNetworkAliases(weatherForecastStorage)
.Build();
Expand All @@ -52,7 +52,7 @@ await Image.InitializeAsync()
await _weatherForecastNetwork.CreateAsync()
.ConfigureAwait(false);

await _sqlEdgeContainer.StartAsync()
await _postgreSqlContainer.StartAsync()
.ConfigureAwait(false);

await _weatherForecastContainer.StartAsync()
Expand All @@ -68,7 +68,7 @@ await Image.DisposeAsync()
await _weatherForecastContainer.DisposeAsync()
.ConfigureAwait(false);

await _sqlEdgeContainer.DisposeAsync()
await _postgreSqlContainer.DisposeAsync()
.ConfigureAwait(false);

await _weatherForecastNetwork.DeleteAsync()
Expand Down
Loading