AddToList Template

This commit is contained in:
CodeLiturgy 2022-09-08 04:15:44 +01:00
parent a5e377e66f
commit 924865066d
16 changed files with 195 additions and 112 deletions

View File

@ -34,12 +34,13 @@
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AdditionalFiles Include="Context\Templates\AddToEntityTemplate.csx" /> <AdditionalFiles Include="Context\Templates\AddToTemplate.csx" />
<AdditionalFiles Include="Context\Templates\UpdateEntityTemplate.csx" /> <AdditionalFiles Include="Context\Templates\UpdateTemplate.csx" />
<AdditionalFiles Include="Context\Templates\GetOneByTemplate.csx" /> <AdditionalFiles Include="Context\Templates\GetOneByTemplate.csx" />
<AdditionalFiles Include="Context\Templates\GetManyTemplate.csx" /> <AdditionalFiles Include="Context\Templates\GetManyTemplate.csx" />
<AdditionalFiles Include="Context\Templates\GetOneTemplate.csx" /> <AdditionalFiles Include="Context\Templates\GetOneTemplate.csx" />
<AdditionalFiles Include="Context\Templates\GetListTemplate.csx" />
<AdditionalFiles Include="Context\Templates\AddToListTemplate.csx" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,7 +1,7 @@
using BlueWest.Data; using BlueWest.Data;
using BlueWest.WebApi.EF.Model; using BlueWest.WebApi.EF.Model;
using BlueWest.EfMethods; using BlueWest.EfMethods;
using BlueWest.WebApi.Extensions; using BlueWest.WebApi.Context.Extensions;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@ -16,28 +16,18 @@ namespace BlueWest.WebApi.EF
{ {
#region Countries #region Countries
/// <summary> /// <summary>
/// Countries Database Table /// Countries
/// </summary> /// </summary>
[EfGetOneBy( [EfGetOneBy(nameof(Country.Id), typeof(CountryUnique))]
nameof(Country.Id),
typeof(CountryUnique))]
[EfGetOne(typeof(CountryUnique))] [EfGetOne(typeof(CountryUnique))]
[EfAddMethods(createType: typeof(CountryCreate), returnType: typeof(CountryUnique))]
[EfAddMethods( [EfUpdateMethods( updateType: typeof(CountryUpdate), returnType: typeof(CountryUnique), keyPropertyMemberName: nameof(Country.Id))]
createType: typeof(CountryCreate),
returnType: typeof(CountryUnique))
]
[EfUpdateMethods(
updateType: typeof(CountryUpdate),
returnType: typeof(CountryUnique),
keyPropertyMemberName: nameof(Country.Id))
]
[EfGetMany(typeof(CountryUnique))] [EfGetMany(typeof(CountryUnique))]
[EfAddToList(nameof(Country.Currencies), typeof(CurrencyCreate), typeof(CurrencyUnique), nameof(Country.Id))]
[EfGetList(nameof(Country.Currencies), typeof(CurrencyUnique), nameof(Country.Id))]
public DbSet<Country> Countries { get; set; } public DbSet<Country> Countries { get; set; }
@ -50,20 +40,11 @@ namespace BlueWest.WebApi.EF
/// </summary> /// </summary>
[EfAddMethods(typeof(CurrencyCreate), typeof(CurrencyUnique))] [EfAddMethods(typeof(CurrencyCreate), typeof(CurrencyUnique))]
[EfUpdateMethods( updateType: typeof(CurrencyUpdate), returnType: typeof(CurrencyUnique), keyPropertyMemberName: nameof(Currency.Id))]
[EfUpdateMethods( [EfGetOneBy(nameof(Currency.Id), typeof(CurrencyUnique))]
updateType: typeof(CurrencyUpdate), [EfGetOne(typeof(CurrencyUnique))]
returnType: typeof(CurrencyUnique), [EfGetList(nameof(Currency.Countries), typeof(CountryUnique), nameof(Currency.Id))
keyPropertyMemberName: nameof(Currency.Id))
] ]
[EfGetOneBy(
nameof(Currency.Id),
typeof(CurrencyUnique))]
[EfGetOne(
typeof(CurrencyUnique))]
public DbSet<Currency> Currencies { get; set; } public DbSet<Currency> Currencies { get; set; }
#endregion #endregion

View File

@ -0,0 +1,59 @@
using System.Collections.Generic;
using BlueWest.Data;
using Microsoft.EntityFrameworkCore;
namespace BlueWest.WebApi.Context.Extensions
{
public static class ModelBuilderCountryDbContextExtensions
{ /// <summary>
/// Setup the database model
/// </summary>
/// <param name="modelBuilder"></param>
public static void AddCurrencyAndCountryData(this ModelBuilder modelBuilder)
{
var currencies = new List<Currency>();
var usaCountry = new Country();
usaCountry.Id = 1;
usaCountry.Code = 1;
usaCountry.Name = "United States";
usaCountry.Alpha2Code = "US";
usaCountry.StateName = "United States of America";
usaCountry.TLD = "us";
var germanyCountry = new Country();
germanyCountry.Id = 2;
germanyCountry.Code = 2;
germanyCountry.Name = "Germany";
germanyCountry.Alpha2Code = "DE";
germanyCountry.StateName = "Germany";
germanyCountry.TLD = "de";
var dolar = new Currency();
dolar.Id = 1;
dolar.Code = "USD";
dolar.Countries = new List<Country>();
dolar.Countries.Add(usaCountry);
dolar.Num = 1;
var euro = new Currency();
euro.Id = 2;
euro.Code = "EUR";
euro.Countries = new List<Country>();
euro.Countries.Add(germanyCountry);
euro.Num = 2;
modelBuilder
.Entity<Currency>()
.HasData(currencies.ToArray());
}
}
}

View File

@ -123,10 +123,6 @@ namespace BlueWest.WebApi.EF.Model
#endregion #endregion
#region Migrations
#endregion
} }
} }

View File

@ -9,16 +9,27 @@ namespace BlueWest.WebApi.EF
/// </summary> /// </summary>
public sealed class FinanceDbContext : DbContext public sealed class FinanceDbContext : DbContext
{ {
#region Transactions
/// <summary> /// <summary>
/// Table storing transactions /// Table storing transactions
/// </summary> /// </summary>
public DbSet<FinanceOp> Transactions { get; set; } public DbSet<FinanceOp> Transactions { get; set; }
#endregion
#region TransactionType
/// <summary> /// <summary>
/// Table storing transaction types. /// Table storing transaction types.
/// </summary> /// </summary>
public DbSet<FinanceOpType> TransactionTypes { get; set; } public DbSet<FinanceOpType> TransactionTypes { get; set; }
#endregion
#region Initialization
/// <summary> /// <summary>
/// CompanyDbContext constructor. /// CompanyDbContext constructor.
/// </summary> /// </summary>
@ -37,6 +48,9 @@ namespace BlueWest.WebApi.EF
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureCurrentDbModel(); modelBuilder.ConfigureCurrentDbModel();
} }
#endregion
} }
} }

View File

@ -1,26 +1,26 @@
/// <summary>
/// Adds a new item into {listPropertyName} from {entityTypeName}.
/// </summary>
/// <param name="dbContext">The database context.</param>
/// <param name="{primaryKeyVarName}">The {entityTypeName} key to get</param>
/// <param name="{listItemCreateVarName}">The item to add to {listPropertyName}.</param>
/// <returns>The success of the operation, a message, and a projection of the added item. </returns>
public static (bool, string, {returnTypeFullName}) Add{listEntityTypeName}To{entityTypeName}(this {contextFullName} dbContext, public static (bool, string, {returnTypeFullName}) Add{listEntityTypeName}To{entityTypeName}(this {contextFullName} dbContext,
{keyTypeFullName} {keyVarName}, {listEntityCreateFullName} {listItemCreateVarName}, Expression<Func<{entityTypeFullName},bool>>[] duplicationValidations) {primaryKeyFullName} {primaryKeyVarName}, {listEntityCreateFullName} {listItemCreateVarName})
{ {
var entityQuery = from aEntity in dbContext.{propertyName} var entityQuery = from aEntity in dbContext.{propertyName}
where aEntity.{keyVarName} == {keyVarName} where aEntity.{primaryKeyPropertyName} == {primaryKeyVarName}
let itemsInList = aEntity.{entityListMemberName} let itemsInList = aEntity.{listPropertyName}
select aEntity; select aEntity;
var entity = entityQuery.FirstOrDefault(); var entity = entityQuery.FirstOrDefault();
if (entity == null) return (false, $"{nameof(country)} Not found.", null); if (entity == null) return (false, $"{entityTypeName} Not found.", null);
foreach (var duplicationValidation in duplicationValidations)
{
var entityToGet = dbContext.{entityListMemberName}.FirstOrDefault(duplicationValidation);
if (entityToGet != null)
{
return (false, $"Duplication Validation failed: {nameof(duplicationValidation.Body.ToString)}", null);
}
}
var newListItem = new {listEntityFullName}({listItemCreateVarName}); var newListItem = new {listEntityFullName}({listItemCreateVarName});
entity.{entityListMemberName}.Add({listItemCreateVarName}); entity.{listPropertyName}.Add(newListItem);
var success = dbContext.SaveChanges() >= 0; var success = dbContext.SaveChanges() >= 0;
return !success ? (false, "Error saving changes.", null) : (true, string.Empty, new {returnTypeFullName}(newListItem));
return !success ? (false, "Error saving changes in the Database. Action: Create {listEntityTypeName} in {entityTypeName}.", null) :
(true, string.Empty, new {returnTypeFullName}(newListItem));
} }

View File

@ -4,7 +4,6 @@
/// <param name="dbContext">The database context.</param> /// <param name="dbContext">The database context.</param>
/// <param name="{toCreateVarName}">Projection data of {entityTypeName}</param> /// <param name="{toCreateVarName}">Projection data of {entityTypeName}</param>
/// <returns>The added data.</returns> /// <returns>The added data.</returns>
public static (bool, {returnTypeFullName}) Add{entityTypeName}(this {contextFullName} dbContext, {createTypeFullName} {toCreateVarName}) public static (bool, {returnTypeFullName}) Add{entityTypeName}(this {contextFullName} dbContext, {createTypeFullName} {toCreateVarName})
{ {
var {newEntityVarName} = new {entityTypeFullName}({toCreateVarName}); var {newEntityVarName} = new {entityTypeFullName}({toCreateVarName});

View File

@ -0,0 +1,34 @@
/// <summary>
/// Gets {listPropertyName} in {entityTypeName}.
/// </summary>
/// <param name="dbContext">The database context.</param>
/// <param name="{primaryKeyVarName}">The {entityTypeName} key to get</param>
/// <param name="skip">How many {propertyName} to skip.</param>
/// <param name="take">How many {propertyName} to take. (Default = 50)</param>
/// <param name="orderDir">Optional Order direction</param>
/// <param name="where">Optional where predicate.</param>
/// <param name="orderBy">Optional order by predicate.</param>
/// <returns>A bool if there's at least one record found and the resulting array. </returns>
public static (bool, {returnTypeFullName}[]) Get{entityTypeName}{listPropertyName}(this {contextFullName} dbContext, {primaryKeyFullName} {primaryKeyVarName},
int skip = 0, int take = 50, int orderDir = 1,
Expression<Func<{returnTypeFullName}, bool>> orderBy = null)
{
var {entityObjectVarName} = dbContext.{propertyName}.FirstOrDefault(d => d.{primaryKeyPropertyName} == {primaryKeyVarName});
if ({entityObjectVarName} == null) return (false, null);
var currentTake = take;
if (take > 200) currentTake = 200;
var query = dbContext
.{propertyName}
.Where(data => data.{primaryKeyPropertyName} == {primaryKeyVarName})
.SelectMany(o => o.{listPropertyName})
.Select(x => new {returnTypeFullName}(x))
.Skip(skip)
.Take(currentTake);
if(orderBy != null) query = orderDir == 1 ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
return (query.Any(), query.ToArray());
}

View File

@ -4,7 +4,6 @@
/// <param name="dbContext">The database context.</param> /// <param name="dbContext">The database context.</param>
/// <param name="{byParamVarName}">By {byParamPropertyName} parameter type.</param> /// <param name="{byParamVarName}">By {byParamPropertyName} parameter type.</param>
/// <returns>A bool if the result is successfull, and the first occurrence of {entityTypeName}> </returns> /// <returns>A bool if the result is successfull, and the first occurrence of {entityTypeName}> </returns>
public static (bool, {returnTypeFullName}) GetOne{entityTypeName}By{byParamPropertyName} (this {contextFullName} dbContext, {byParamFullType} {byParamVarName}) public static (bool, {returnTypeFullName}) GetOne{entityTypeName}By{byParamPropertyName} (this {contextFullName} dbContext, {byParamFullType} {byParamVarName})
{ {
var {findEntityVarName} = dbContext.{propertyName} var {findEntityVarName} = dbContext.{propertyName}

View File

@ -4,8 +4,8 @@
/// <param name="dbContext">The database context.</param> /// <param name="dbContext">The database context.</param>
/// <param name="with">FirstOrDefault argument to pass.</param> /// <param name="with">FirstOrDefault argument to pass.</param>
/// <returns>A bool if the first occurrence of {returnTypeName} is returned.</returns> /// <returns>A bool if the first occurrence of {returnTypeName} is returned.</returns>
public static (bool, {returnTypeFullName}) Get{entityTypeName}With (this {contextFullName} dbContext,
public static (bool, {returnTypeFullName}) Get{entityTypeName}With (this {contextFullName} dbContext, Expression<Func<{returnTypeFullName},bool>> with) Expression<Func<{returnTypeFullName},bool>> with)
{ {
var {findEntityVarName} = var {findEntityVarName} =
dbContext.{propertyName} dbContext.{propertyName}

View File

@ -32,6 +32,8 @@ namespace BlueWest.WebApi.Controllers
#endregion #endregion
#region GetCountries
/// <summary> /// <summary>
/// Get countries /// Get countries
/// </summary> /// </summary>
@ -44,12 +46,17 @@ namespace BlueWest.WebApi.Controllers
int take = 50, int take = 50,
int orderDir = 1) int orderDir = 1)
{ {
var (success, countries) = _dbContext.GetCountries(skip, take); var (success, countries) = _dbContext.GetCountries(skip, take);
if (!success) return new NotFoundResult(); if (!success) return new NotFoundResult();
return Ok(countries); return Ok(countries);
} }
#endregion
#region GetCountryById
/// <summary> /// <summary>
/// Get Country by Id /// Get Country by Id
@ -71,6 +78,9 @@ namespace BlueWest.WebApi.Controllers
return new NotFoundResult(); return new NotFoundResult();
} }
#endregion
/// <summary> /// <summary>
/// Get currencies of a countryId /// Get currencies of a countryId
@ -80,22 +90,33 @@ namespace BlueWest.WebApi.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[HttpGet("{countryId}/currencies")] [HttpGet("{countryId}/currencies")]
public ActionResult GetCountryCurrencies(int countryId) public ActionResult GetCountryCurrencies(int countryId, int skip = 0, int take = 50, int orderDir = 1, Expression<Func<CurrencyUnique, bool>> orderBy = null)
{ {
var countryObj = _dbContext.Countries.FirstOrDefault(d => d.Id == countryId); var countryObj = _dbContext.Countries.FirstOrDefault(d => d.Id == countryId);
if (countryObj == null) return new NotFoundResult(); if (countryObj == null) return new NotFoundResult();
var array = _dbContext var currentTake = take;
if (take > 200) currentTake = 200;
var query = _dbContext
.Countries .Countries
.Where(data => data.Id == countryId) .Where(data => data.Id == countryId)
.SelectMany(o => o.Currencies) .SelectMany(o => o.Currencies)
.Select(x => new CurrencyUnique(x)) .Select(x => new CurrencyUnique(x))
.ToArray(); .Skip(skip)
.Take(currentTake);
return Ok(array); if(orderBy != null)
{
if (orderDir == 1) query = query.OrderBy(orderBy);
else query = query.OrderByDescending(orderBy);
} }
return Ok(query.ToArray());
}
#region AddCountry
/// <summary> /// <summary>
/// Add Country /// Add Country
@ -128,6 +149,11 @@ namespace BlueWest.WebApi.Controllers
return CreatedAtRoute(nameof(GetCountryById), new {countryId = country.Id}, country); return CreatedAtRoute(nameof(GetCountryById), new {countryId = country.Id}, country);
} }
#endregion
#region UpdateCountry
/// <summary> /// <summary>
/// Updates a Country /// Updates a Country
/// </summary> /// </summary>
@ -149,6 +175,9 @@ namespace BlueWest.WebApi.Controllers
return new NotFoundResult(); return new NotFoundResult();
} }
#endregion
#region AddCurrencyToCountry
/// <summary> /// <summary>
/// Adds a currency to Country /// Adds a currency to Country
@ -159,7 +188,7 @@ namespace BlueWest.WebApi.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status409Conflict)] [ProducesResponseType(StatusCodes.Status409Conflict)]
[HttpPost("{countryId}/currencies")] [HttpPost("{countryId}/currencies")]
public ActionResult AddCurrency(int countryId, CurrencyCreate currencyCreate) public ActionResult AddCurrencyToCountry(int countryId, CurrencyCreate currencyCreate)
{ {
/*var (result, message, country) = _dbContext.AddCurrency(countryId, currencyCreate, /*var (result, message, country) = _dbContext.AddCurrency(countryId, currencyCreate,
new Expression<Func<Currency, bool>>[] new Expression<Func<Currency, bool>>[]
@ -174,9 +203,12 @@ namespace BlueWest.WebApi.Controllers
} }
return Ok(country);*/ return Ok(country);*/
return null; throw new NotImplementedException();
} }
#endregion
} }
} }

View File

@ -1,34 +0,0 @@
using System.Collections.Generic;
using BlueWest.Data;
using BlueWest.WebApi.EF.Model;
using Microsoft.EntityFrameworkCore;
namespace BlueWest.WebApi.Extensions
{
public static class ModelBuilderMigrationExtensions
{
/// <summary>
/// Setup the database model
/// </summary>
/// <param name="modelBuilder"></param>
public static void AddCurrencyAndCountryData(this ModelBuilder modelBuilder)
{
var countriesToAdd = new List<Country>();
var country = new Country();
country.Id = 1;
country.Code = 1;
country.Name = "United States";
country.Alpha2Code = "US";
country.StateName = "United States of America";
countriesToAdd.Add(country);
modelBuilder
.Entity<Country>()
.HasData(countriesToAdd.ToArray());
}
}
}

View File

@ -80,11 +80,13 @@ namespace BlueWest.WebApi
public static IServiceCollection PrepareSqlLiteDatabasePool(this IServiceCollection serviceCollection, public static IServiceCollection PrepareSqlLiteDatabasePool(this IServiceCollection serviceCollection,
IConfiguration configuration, IWebHostEnvironment environment) IConfiguration configuration, IWebHostEnvironment environment)
{ {
var sqliteConString = "Data Source=BlueWest.Api.db";
return serviceCollection return serviceCollection
.AddDbContextPool<UserDbContext>(options => options.UseSqlite("Data Source=BlueWest.Api.db")) .AddDbContextPool<UserDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<CountryDbContext>(options => options.UseSqlite("Data Source=BlueWest.Api.db")) .AddDbContextPool<CountryDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<FinanceDbContext>(options => options.UseSqlite("Data Source=BlueWest.Api.db")) .AddDbContextPool<FinanceDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<CompanyDbContext>(options => options.UseSqlite("Data Source=BlueWest.Api.db")); .AddDbContextPool<CompanyDbContext>(options => options.UseSqlite(sqliteConString));
} }
} }

@ -1 +1 @@
Subproject commit ba851c4f946fd370f888a8aa902ac5f46a982e73 Subproject commit e85e5d18a2df4957905fda02e216850385bb29da

@ -1 +1 @@
Subproject commit 33fbb36fb85cabaa8995ac8e16e5ed6fdd733805 Subproject commit dc23c797975f1e4d835b5e67a5c0972813567ce1