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

.NET 8 Upgrade #357

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace WesternStatesWater.WestDaat.Accessors.Extensions
{
public static class EnumerableExtensions
{
public static IEnumerable<T> ToEnumerable<T>(this IAsyncEnumerable<T> asyncEnumerable)
{
var enumerator = asyncEnumerable.GetAsyncEnumerator();
try
{
while (enumerator.MoveNextAsync().AsTask().GetAwaiter().GetResult())
{
yield return enumerator.Current;
}
}
finally
{
enumerator.DisposeAsync().AsTask().GetAwaiter().GetResult();
}
}
}
}
27 changes: 10 additions & 17 deletions src/API/WesternStatesWater.WestDaat.Accessors/SiteAccessor.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using AutoMapper.QueryableExtensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Data;
using WesternStatesWater.WestDaat.Accessors.EntityFramework;
using WesternStatesWater.WestDaat.Accessors.Mapping;
using WesternStatesWater.WestDaat.Common;
using WesternStatesWater.WestDaat.Common.DataContracts;

namespace WesternStatesWater.WestDaat.Accessors
Expand All @@ -20,7 +18,7 @@ public SiteAccessor(ILogger<SiteAccessor> logger, IDatabaseContextFactory databa

async Task<Site> ISiteAccessor.GetSiteByUuid(string siteUuid)
{
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();
return await db.SitesDim
.Where(x => x.SiteUuid == siteUuid)
.ProjectTo<Site>(DtoMapper.Configuration)
Expand All @@ -29,8 +27,7 @@ async Task<Site> ISiteAccessor.GetSiteByUuid(string siteUuid)

async Task<SiteDigest> ISiteAccessor.GetSiteDigestByUuid(string siteUuid)
{
using var db = _databaseContextFactory.Create();

await using var db = _databaseContextFactory.Create();
return await db.SitesDim
.Where(x => x.SiteUuid == siteUuid)
.ProjectTo<SiteDigest>(DtoMapper.Configuration)
Expand All @@ -48,7 +45,7 @@ async Task<List<Site>> ISiteAccessor.GetSites()

public async Task<SiteDetails> GetSiteDetailsByUuid(string siteUuid)
{
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();
return await db.SitesDim
.Where(x => x.SiteUuid == siteUuid)
.ProjectTo<SiteDetails>(DtoMapper.Configuration)
Expand All @@ -57,26 +54,25 @@ public async Task<SiteDetails> GetSiteDetailsByUuid(string siteUuid)

async Task<SiteLocation> ISiteAccessor.GetWaterSiteLocationByUuid(string siteUuid)
{
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();
return await db.SitesDim.Where(x => x.SiteUuid == siteUuid)
.ProjectTo<SiteLocation>(DtoMapper.Configuration)
.SingleAsync();
}

public async Task<List<WaterSourceInfoListItem>> GetWaterSiteSourceInfoListByUuid(string siteUuid)
{
using var db = _databaseContextFactory.Create();

await using var db = _databaseContextFactory.Create();
return await db.SitesDim.Where(x => x.SiteUuid == siteUuid)
.SelectMany(x => x.WaterSourceBridgeSitesFact
.SelectMany(x => x.WaterSourceBridgeSitesFact
.Select(a => a.WaterSource))
.ProjectTo<WaterSourceInfoListItem>(DtoMapper.Configuration)
.ToListAsync();
.ProjectTo<WaterSourceInfoListItem>(DtoMapper.Configuration)
.ToListAsync();
}

public async Task<List<WaterRightInfoListItem>> GetWaterRightInfoListByUuid(string siteUuid)
{
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();
return await db.AllocationAmountsFact
.Where(x => x.AllocationBridgeSitesFact.Any(y => y.Site.SiteUuid == siteUuid))
.ProjectTo<WaterRightInfoListItem>(DtoMapper.Configuration)
Expand All @@ -95,10 +91,7 @@ public IEnumerable<GeoConnex> GetJSONLDData()
SiteName = a.SiteName,
});

foreach (var geoConnexItem in query)
{
yield return geoConnexItem;
}
return query;
}
}
}
34 changes: 16 additions & 18 deletions src/API/WesternStatesWater.WestDaat.Accessors/SystemAccessor.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using AutoMapper.QueryableExtensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Data;
using WesternStatesWater.WestDaat.Accessors.EntityFramework;
using WesternStatesWater.WestDaat.Accessors.Mapping;
using WesternStatesWater.WestDaat.Common.DataContracts;
Expand All @@ -19,8 +18,7 @@ public SystemAccessor(ILogger<SystemAccessor> logger, IDatabaseContextFactory da

async Task<List<BeneficialUseItem>> ISystemAccessor.GetAvailableBeneficialUseNormalizedNames()
{
using var db = _databaseContextFactory.Create();

await using var db = _databaseContextFactory.Create();
return await db.BeneficialUsesCV
.ProjectTo<BeneficialUseItem>(DtoMapper.Configuration)
.Distinct()
Expand All @@ -32,32 +30,32 @@ async Task<List<BeneficialUseItem>> ISystemAccessor.GetAvailableBeneficialUseNor

async Task<List<string>> ISystemAccessor.GetAvailableWaterSourceTypeNormalizedNames()
{
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();
return await db.WaterSourceType
.Select(a => a.WaDEName.Length > 0 ? a.WaDEName : a.Name)
.Distinct()
.OrderBy(a => a)
.ToListAsync();
.Select(a => a.WaDEName.Length > 0 ? a.WaDEName : a.Name)
.Distinct()
.OrderBy(a => a)
.ToListAsync();
}

async Task<List<string>> ISystemAccessor.GetAvailableOwnerClassificationNormalizedNames()
{
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();
return await db.OwnerClassificationCv
.Select(a => a.WaDEName.Length > 0 ? a.WaDEName : a.Name)
.Distinct()
.OrderBy(a => a)
.ToListAsync();
.Select(a => a.WaDEName.Length > 0 ? a.WaDEName : a.Name)
.Distinct()
.OrderBy(a => a)
.ToListAsync();
}

async Task<List<string>> ISystemAccessor.GetAvailableStateNormalizedNames()
{
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();
return await db.State
.Select(a => a.WaDEName.Length > 0 ? a.WaDEName : a.Name)
.Distinct()
.OrderBy(a => a)
.ToListAsync();
.Select(a => a.WaDEName.Length > 0 ? a.WaDEName : a.Name)
.Distinct()
.OrderBy(a => a)
.ToListAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
using Microsoft.Extensions.Logging;
using NetTopologySuite.Geometries;
using System.Collections.Concurrent;
using System.Data;
using System.Transactions;
using NetTopologySuite.Geometries.Utilities;
using WesternStatesWater.WestDaat.Accessors.CsvModels;
using WesternStatesWater.WestDaat.Accessors.EntityFramework;
using WesternStatesWater.WestDaat.Accessors.Extensions;
using WesternStatesWater.WestDaat.Accessors.Mapping;
using WesternStatesWater.WestDaat.Common.Configuration;
using WesternStatesWater.WestDaat.Common.DataContracts;
Expand All @@ -31,10 +32,10 @@ public WaterAllocationAccessor(ILogger<WaterAllocationAccessor> logger, IDatabas
public async Task<AnalyticsSummaryInformation[]> GetAnalyticsSummaryInformation(WaterRightsSearchCriteria searchCriteria)
{
using var ts = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled);
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();

// db.database does not pick up transaction from transactionScope if we do not open connection
db.Database.OpenConnection();
await db.Database.OpenConnectionAsync();
var predicate = BuildWaterRightsSearchPredicate(searchCriteria, db);

var analyticsSummary = await db.AllocationAmountsFact
Expand All @@ -61,46 +62,39 @@ public async Task<AnalyticsSummaryInformation[]> GetAnalyticsSummaryInformation(
public async Task<Geometry> GetWaterRightsEnvelope(WaterRightsSearchCriteria searchCriteria)
{
using var ts = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled);
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();

// db.database does not pick up transaction from transactionScope if we do not open connection
db.Database.OpenConnection();
await db.Database.OpenConnectionAsync();
var predicate = BuildWaterRightsSearchPredicate(searchCriteria, db);

//EF Core 7 is supposed to support geometry::EnvelopeAggregate (https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/whatsnew#spatial-aggregate-functions).
//It does work with the basic style that is referenced in the docs.
//However, as soon as you try to aggregate with a SelectMany or nested queries, it either fails to translate or pulls all records into memory and performs the aggregation locally (without erroring which is weird).
//Thus, we hack this together instead. Hopefully EF gets better at translating these aggregates and we can go back to more native EF methods.
var siteIdsCommand = db.AllocationAmountsFact
// Get SiteIds based on search predicate
var siteIds = db.AllocationAmountsFact
.AsNoTracking()
.Where(predicate)
.SelectMany(a => a.AllocationBridgeSitesFact.Select(b => b.SiteId))
.CreateDbCommand();

siteIdsCommand.CommandText = "select geometry::EnvelopeAggregate(coalesce(geometry, sitepoint)).ToString() Geometry " +
"from core.Sites_Dim sdf " +
$"where sdf.SiteId in ({siteIdsCommand.CommandText})";
.SelectMany(a => a.AllocationBridgeSitesFact.Select(b => b.SiteId));

object[] parameters = new object[siteIdsCommand.Parameters.Count];
for (var i = 0; i < siteIdsCommand.Parameters.Count; i++)
{
parameters[i] = siteIdsCommand.Parameters[i];
}
// Retrieve geometries based on the SiteIds
var geometries = db.SitesDim
.AsNoTracking()
.Where(sdf => siteIds.Contains(sdf.SiteId))
.Select(sdf => sdf.Geometry ?? sdf.SitePoint);

var geometry = (await siteIdsCommand.ExecuteScalarAsync()) as string;
// Combine geometries using EnvelopeCombiner
var geometry = EnvelopeCombiner.CombineAsGeometry(geometries);

ts.Complete();

return GeometryHelpers.GetGeometryByWkt(geometry);
return geometry.IsEmpty ? null : GeometryHelpers.GetGeometryByWkt(geometry.ToString());
}

public async Task<WaterRightsSearchResults> FindWaterRights(WaterRightsSearchCriteria searchCriteria, int pageNumber)
{
using var ts = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled);
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();

// db.database does not pick up transaction from transactionScope if we do not open connection
db.Database.OpenConnection();
await db.Database.OpenConnectionAsync();
var predicate = BuildWaterRightsSearchPredicate(searchCriteria, db);

var waterRightDetails = await db.AllocationAmountsFact
Expand Down Expand Up @@ -264,10 +258,10 @@ public Organization GetWaterAllocationAmountOrganizationById(long allocationAmou
{
using var db = _databaseContextFactory.Create();
var org = db.AllocationAmountsFact
.Where(a => a.AllocationAmountId == allocationAmountId)
.Select(a => a.Organization)
.ProjectTo<Organization>(DtoMapper.Configuration)
.Single();
.Where(a => a.AllocationAmountId == allocationAmountId)
.Select(a => a.Organization)
.ProjectTo<Organization>(DtoMapper.Configuration)
.Single();

return org;
}
Expand All @@ -285,21 +279,21 @@ public async Task<List<SiteInfoListItem>> GetWaterRightSiteInfoById(string alloc
{
using var db = _databaseContextFactory.Create();
return await db.AllocationBridgeSitesFact
.Where(x => x.AllocationAmount.AllocationUuid == allocationUuid)
.Select(x => x.Site)
.ProjectTo<SiteInfoListItem>(DtoMapper.Configuration)
.ToListAsync();
.Where(x => x.AllocationAmount.AllocationUuid == allocationUuid)
.Select(x => x.Site)
.ProjectTo<SiteInfoListItem>(DtoMapper.Configuration)
.ToListAsync();
}

public async Task<List<WaterSourceInfoListItem>> GetWaterRightSourceInfoById(string allocationUuid)
{
using var db = _databaseContextFactory.Create();
return await db.AllocationBridgeSitesFact.Where(x => x.AllocationAmount.AllocationUuid == allocationUuid)
.SelectMany(x => x.Site.WaterSourceBridgeSitesFact
.SelectMany(x => x.Site.WaterSourceBridgeSitesFact
.Select(a => a.WaterSource))
.ProjectTo<WaterSourceInfoListItem>(DtoMapper.Configuration)
.Distinct()
.ToListAsync();
.ProjectTo<WaterSourceInfoListItem>(DtoMapper.Configuration)
.Distinct()
.ToListAsync();
}

public async Task<List<AllocationAmount>> GetAllWaterAllocations()
Expand All @@ -317,16 +311,16 @@ public async Task<List<SiteLocation>> GetWaterRightSiteLocationsById(string allo
{
using var db = _databaseContextFactory.Create();
return await db.AllocationBridgeSitesFact
.Where(x => x.AllocationAmount.AllocationUuid == allocationUuid)
.Select(x => x.Site)
.Where(x => x.Longitude.HasValue && x.Latitude.HasValue)
.ProjectTo<SiteLocation>(DtoMapper.Configuration)
.ToListAsync();
.Where(x => x.AllocationAmount.AllocationUuid == allocationUuid)
.Select(x => x.Site)
.Where(x => x.Longitude.HasValue && x.Latitude.HasValue)
.ProjectTo<SiteLocation>(DtoMapper.Configuration)
.ToListAsync();
}

public async Task<List<WaterRightsDigest>> GetWaterRightsDigestsBySite(string siteUuid)
{
using var db = _databaseContextFactory.Create();
await using var db = _databaseContextFactory.Create();
db.Database.SetCommandTimeout(int.MaxValue);
return await db.AllocationAmountsFact
.Where(x => x.AllocationBridgeSitesFact.Any(y => y.Site.SiteUuid == siteUuid))
Expand Down Expand Up @@ -373,6 +367,7 @@ private async IAsyncEnumerable<WaterAllocations> BuildWaterAllocationsModel(Wate
yield return allocation.Map<WaterAllocations>();
}
}

private async IAsyncEnumerable<Sites> BuildSitesModel(WaterRightsSearchCriteria searchCriteria)
{
var (db, filteredSites) = GetFilteredSites(searchCriteria);
Expand Down Expand Up @@ -427,15 +422,14 @@ internal IEnumerable<WaterSources> GetWaterSources(WaterRightsSearchCriteria sea
.AsEnumerable();
}

internal IEnumerable<PodSiteToPouSiteRelationships> GetPodSiteToPouSiteRelationships(WaterRightsSearchCriteria searchCriteria)
private IEnumerable<PodSiteToPouSiteRelationships> GetPodSiteToPouSiteRelationships(WaterRightsSearchCriteria searchCriteria)
{
var (db, filteredSites) = GetFilteredSites(searchCriteria);

return db.PODSiteToPOUSiteFact
.AsNoTracking()
.Where(a => filteredSites
.Any(b => b.SiteId == a.PODSiteId)
|| filteredSites.Any(b => b.SiteId == a.POUSiteId))
.Where(a => filteredSites.Any(b => b.SiteId == a.PODSiteId)
|| filteredSites.Any(b => b.SiteId == a.POUSiteId))
.ProjectTo<PodSiteToPouSiteRelationships>(DtoMapper.Configuration)
.AsEnumerable();
}
Expand Down
Loading
Loading