diff --git a/src/Nox.Generator/Domain/ModelGenerator/EntitiesGenerator.cs b/src/Nox.Generator/Domain/ModelGenerator/EntitiesGenerator.cs
index 9b25f29693..e223da7688 100644
--- a/src/Nox.Generator/Domain/ModelGenerator/EntitiesGenerator.cs
+++ b/src/Nox.Generator/Domain/ModelGenerator/EntitiesGenerator.cs
@@ -27,6 +27,7 @@ private static void GenerateEntity(SourceProductionContext context, string solut
var code = new CodeBuilder($"{entity.Name}.g.cs", context);
code.AppendLine($"using Nox.Types;");
+ code.AppendLine($"using System;");
code.AppendLine($"using System.Collections.Generic;");
code.AppendLine();
code.AppendLine($"namespace {solutionNameSpace}.Domain;");
diff --git a/src/Nox.Generator/Infrastructure/Persistence/DbContextGenerator/DbContextGenerator.cs b/src/Nox.Generator/Infrastructure/Persistence/DbContextGenerator/DbContextGenerator.cs
index ac12826106..4ab0836c19 100644
--- a/src/Nox.Generator/Infrastructure/Persistence/DbContextGenerator/DbContextGenerator.cs
+++ b/src/Nox.Generator/Infrastructure/Persistence/DbContextGenerator/DbContextGenerator.cs
@@ -24,7 +24,7 @@ public static void Generate(SourceProductionContext context, string solutionName
code.AppendLine(@"using Microsoft.EntityFrameworkCore;");
code.AppendLine(@"using Nox.Solution;");
code.AppendLine(@"using Nox.Types.EntityFramework.vNext;");
- code.AppendLine(@"using SampleWebApp.Domain;");
+ code.AppendLine($@"using {solutionNameSpace}.Domain;");
code.AppendLine();
code.AppendLine($"namespace {solutionNameSpace}.Infrastructure.Persistence;");
code.AppendLine();
@@ -83,8 +83,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
}
}
- base.OnModelCreating(modelBuilder);
}
+
+ base.OnModelCreating(modelBuilder);
}
}
");
diff --git a/src/SampleWebApp/Examples/SampleWebAppDbContextExample.cs b/src/SampleWebApp/Examples/SampleWebAppDbContextExample.cs
index 83eb2c9f20..664a93388f 100644
--- a/src/SampleWebApp/Examples/SampleWebAppDbContextExample.cs
+++ b/src/SampleWebApp/Examples/SampleWebAppDbContextExample.cs
@@ -49,8 +49,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
_databaseConfigurator.ConfigureEntity(modelBuilder.Entity(type), entity);
}
}
-
- base.OnModelCreating(modelBuilder);
}
+
+ base.OnModelCreating(modelBuilder);
}
}
\ No newline at end of file
diff --git a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Country.g.cs b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Country.g.cs
index 6805e60b72..7fde1e2354 100644
--- a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Country.g.cs
+++ b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Country.g.cs
@@ -3,6 +3,7 @@
#nullable enable
using Nox.Types;
+using System;
using System.Collections.Generic;
namespace SampleWebApp.Domain;
diff --git a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/CountryLocalNames.g.cs b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/CountryLocalNames.g.cs
index 4a0eb3b9e7..79c7b172ac 100644
--- a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/CountryLocalNames.g.cs
+++ b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/CountryLocalNames.g.cs
@@ -3,6 +3,7 @@
#nullable enable
using Nox.Types;
+using System;
using System.Collections.Generic;
namespace SampleWebApp.Domain;
diff --git a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Currency.g.cs b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Currency.g.cs
index 296af5eefa..b8cd178735 100644
--- a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Currency.g.cs
+++ b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Currency.g.cs
@@ -3,6 +3,7 @@
#nullable enable
using Nox.Types;
+using System;
using System.Collections.Generic;
namespace SampleWebApp.Domain;
diff --git a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/SampleWebAppDbContext.g.cs b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/SampleWebAppDbContext.g.cs
index 8cca3953cd..25db3cec68 100644
--- a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/SampleWebAppDbContext.g.cs
+++ b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/SampleWebAppDbContext.g.cs
@@ -52,8 +52,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
}
}
- base.OnModelCreating(modelBuilder);
}
+
+ base.OnModelCreating(modelBuilder);
}
}
diff --git a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Store.g.cs b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Store.g.cs
index 462ee71e47..fd77ec669a 100644
--- a/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Store.g.cs
+++ b/src/SampleWebApp/Generated/Nox.Generator/Nox.Generator.NoxCodeGenerator/Store.g.cs
@@ -3,6 +3,7 @@
#nullable enable
using Nox.Types;
+using System;
using System.Collections.Generic;
namespace SampleWebApp.Domain;
diff --git a/tests/Nox.Generator.Tests/Database/Design/test.solution.nox.yaml b/tests/Nox.Generator.Tests/Database/Design/test.solution.nox.yaml
new file mode 100644
index 0000000000..406937e071
--- /dev/null
+++ b/tests/Nox.Generator.Tests/Database/Design/test.solution.nox.yaml
@@ -0,0 +1,237 @@
+#
+# workplace.solution.nox.yaml
+#
+# yaml-language-server: $schema=https://noxorg.dev/schemas/solution.json
+#
+
+name: TestDatabaseWebApp
+
+description: Sample Nox solution yaml configuration
+
+variables:
+ DATABASE_PROVIDER: slqServer
+ DATABASE_SERVER: localhost
+ DATABASE_USER: sa
+ DATABASE_PASSWORD: Developer*123
+ DATABASE_PORT: "5432"
+
+environments:
+
+ - name: dev
+ description: Used for development and testing
+
+ - name: test
+ description: Test environment
+
+ - name: uat
+ description: For them end users to check it works
+
+ - name: prod
+ description: Production environment used for, well - the real thing!
+ isProduction: true
+
+versionControl:
+ provider: azureDevops
+ host: https://dev.azure.com/iwgplc
+ folders:
+ sourceCode: /src
+ containers: /docker
+
+team:
+
+ - name: Andre Sharpe
+ userName: andre.sharpe@iwgplc.com
+ roles: [architect, owner, administrator, developer, manager]
+
+ - name: Jan Schutte
+ userName: jan.schutte@iwgplc.com
+ roles: [architect, administrator, developer, devOpsEngineer]
+
+ - name: Anton Du Plessis
+ userName: anton.duplessis@iwgplc.com
+ roles: [projectManager]
+
+ - name: Morne Van Zyl
+ userName: morne.vanzyl@iwgplc.com
+ roles: [technicalWriter]
+
+ - name: Dmytro Dorodnykh
+ userName: dmytro.dorodnykh@iwgplc.com
+ roles: [developer]
+
+ - name: Oleksandr Vlasenko
+ userName: oleksandr.vlasenko@regus.com
+ roles: [architect, developer]
+
+domain:
+
+ entities:
+
+ - name: TestEntity
+ description: Entity created for testing database
+
+ userInterface:
+ icon: world
+
+ persistence:
+ isVersioned: true
+ tableName: TestEntity
+ schema: dbo
+ create:
+ isEnabled: true
+ raiseEvents: true
+ read:
+ isEnabled: true
+ update:
+ isEnabled: true
+ raiseEvents: true
+ delete:
+ isEnabled: true
+ raiseEvents: true
+ useSoftDelete: true
+
+ keys:
+
+ - name: Id
+ type: text
+ textTypeOptions:
+ isUnicode: false
+ minLength: 2
+ maxLength: 2
+
+ attributes:
+
+ - name: TextTestField
+ type: text
+ textTypeOptions:
+ minLength: 4
+ maxLength: 63
+ isRequired: true
+
+ - name: NumberTestField
+ type: number
+ numberTypeOptions:
+ minValue: 4
+ maxValue: 894
+ isRequired: true
+
+ - name: MoneyTestField
+ type: money
+
+ #- name: CountryCode2TestField
+ # type: countryCode2
+
+ #- name: GeoCoordTestField
+ # type: latLong
+
+ #- name: AreaTestField
+ # type: area
+
+ #- name: BooleanTestField
+ # type: boolean
+
+ #- name: CountryCode3TestField
+ # type: countryCode3
+
+ #- name: CountryNumberTestField
+ # type: countryNumber
+
+ #- name: CurrencyCodeTestField
+ # type: currencyCode
+
+ #- name: CurrencyNumberTestField
+ # type: currencyNumber
+
+ #- name: DateTimeTestField
+ # type: dateTime
+
+ #- name: DateTimeRangeTestField
+ # type: dateTimeRange
+
+ #- name: DistanceTestField
+ # type: distance
+
+ #- name: EmailTestField
+ # type: email
+
+ #- name: EncryptedTextTestField
+ # type: encryptedText
+
+ #- name: GuidTestField
+ # type: guid
+
+ #- name: HashedTextTestField
+ # type: hashedText
+
+ #- name: InternetDomainTestField
+ # type: internetDomain
+
+ #- name: IpAddressTestField
+ # type: ipAddress
+
+ #- name: LengthTestField
+ # type: length
+
+ #- name: MacAddressTestField
+ # type: macAddress
+
+ #- name: MonthTestField
+ # type: month
+
+ #- name: NuidTestField
+ # type: nuid
+
+ #- name: PasswordTestField
+ # type: password
+
+ #- name: PercentageTestField
+ # type: percentage
+
+ #- name: PhoneNumberTestField
+ # type: phoneNumber
+
+ #- name: StreetAddressTestField
+ # type: streetAddress
+
+ #- name: TempratureTestField
+ # type: temperature
+
+ #- name: UriTestField
+ # type: uri
+
+ #- name: VolumeTestField
+ # type: volume
+
+ #- name: WeightTestField
+ # type: weight
+
+ #- name: YearTestField
+ # type: year
+
+ #- name: CultureCodeTestField
+ # type: cultureCode
+
+ #- name: LanguageCodeTestField
+ # type: languageCode
+
+infrastructure:
+
+ persistence:
+ databaseServer:
+ name: SampleCurrencyDb
+
+ # Sql Server
+ serverUri: sqlserver.iwgplc.com
+ provider: sqlServer
+ port: 1433
+ user: sqluser
+ password: sqlpassword
+
+ messaging:
+ integrationEventServer:
+ name: IntegrationBus
+ provider: rabbitMq
+ serverUri: rabbitmq://localhost
+ port: 5672
+ user: guest
+ password: guest
diff --git a/tests/Nox.Generator.Tests/Database/Models/AuditableEntityBase.cs b/tests/Nox.Generator.Tests/Database/Models/AuditableEntityBase.cs
new file mode 100644
index 0000000000..f76e75eed7
--- /dev/null
+++ b/tests/Nox.Generator.Tests/Database/Models/AuditableEntityBase.cs
@@ -0,0 +1,40 @@
+// Generated
+
+#nullable enable
+
+using System;
+
+namespace TestDatabaseWebApp.Domain;
+
+public partial class AuditableEntityBase
+{
+ ///
+ /// The date and time when this entity was first created (in Coordinated Universal Time).
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// The user that created the entity.
+ ///
+ public string? CreatedBy { get; set; }
+
+ ///
+ /// The date and time when this entity was last updated (in Coordinated Universal Time).
+ ///
+ public DateTime? UpdatedAtUtc { get; set; }
+
+ ///
+ /// The user that last updated the entity.
+ ///
+ public string? UpdatedBy { get; set; }
+
+ ///
+ /// The date and time when this entity was deleted (in Coordinated Universal Time).
+ ///
+ public DateTime? DeletedAtUtc { get; set; }
+
+ ///
+ /// The user that deleted the entity.
+ ///
+ public string? DeletedBy { get; set; }
+}
diff --git a/tests/Nox.Generator.Tests/Database/Models/TestDatabaseWebAppDbContext.g.cs b/tests/Nox.Generator.Tests/Database/Models/TestDatabaseWebAppDbContext.g.cs
new file mode 100644
index 0000000000..0dc5cd59d3
--- /dev/null
+++ b/tests/Nox.Generator.Tests/Database/Models/TestDatabaseWebAppDbContext.g.cs
@@ -0,0 +1,56 @@
+// Generated
+
+#nullable enable
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Nox.Solution;
+using Nox.Types.EntityFramework.vNext;
+using System;
+using TestDatabaseWebApp.Domain;
+
+namespace TestDatabaseWebApp.Infrastructure.Persistence;
+
+public partial class TestDatabaseWebAppDbContext : DbContext
+{
+ private NoxSolution _noxSolution { get; set; }
+ private INoxDatabaseConfigurator _databaseConfigurator { get; set; }
+
+ public TestDatabaseWebAppDbContext(
+ DbContextOptions options,
+ NoxSolution noxSolution,
+ INoxDatabaseConfigurator databaseConfigurator
+ ) : base(options)
+ {
+ _noxSolution = noxSolution;
+ _databaseConfigurator = databaseConfigurator;
+ }
+
+ public DbSet TestEntities { get; set; } = null!;
+
+
+ public static void RegisterDbContext(IServiceCollection services)
+ {
+ services.AddDbContext();
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ if (_noxSolution.Domain != null)
+ {
+ foreach (var entity in _noxSolution.Domain.Entities)
+ {
+ var type = Type.GetType("TestDatabaseWebApp.Domain." + entity.Name);
+
+ if (type != null)
+ {
+ _databaseConfigurator.ConfigureEntity(modelBuilder.Entity(type), entity);
+ }
+ }
+
+ }
+
+ base.OnModelCreating(modelBuilder);
+ }
+}
+
diff --git a/tests/Nox.Generator.Tests/Database/Models/TestEntity.cs b/tests/Nox.Generator.Tests/Database/Models/TestEntity.cs
new file mode 100644
index 0000000000..b08f576244
--- /dev/null
+++ b/tests/Nox.Generator.Tests/Database/Models/TestEntity.cs
@@ -0,0 +1,36 @@
+// Generated
+
+#nullable enable
+
+using Nox.Types;
+using System;
+using System.Collections.Generic;
+
+namespace TestDatabaseWebApp.Domain;
+
+///
+/// Entity created for testing database.
+///
+public partial class TestEntity : AuditableEntityBase
+{
+
+ ///
+ /// (Optional)
+ ///
+ public Text Id { get; set; } = null!;
+
+ ///
+ /// (Required)
+ ///
+ public Text TextTestField { get; set; } = null!;
+
+ ///
+ /// (Required)
+ ///
+ public Number NumberTestField { get; set; } = null!;
+
+ ///
+ /// (Optional)
+ ///
+ public Money? MoneyTestField { get; set; } = null!;
+}
diff --git a/tests/Nox.Generator.Tests/Database/SqliteIntegrationTests.cs b/tests/Nox.Generator.Tests/Database/SqliteIntegrationTests.cs
new file mode 100644
index 0000000000..7fcd9dc9c6
--- /dev/null
+++ b/tests/Nox.Generator.Tests/Database/SqliteIntegrationTests.cs
@@ -0,0 +1,74 @@
+using FluentAssertions;
+using Nox.Types;
+using NoxSourceGeneratorTests.DatabaseTests;
+using System.Linq;
+using TestDatabaseWebApp.Domain;
+using Xunit;
+
+namespace Nox.Generator.Test.DatabaseTests;
+
+public class SqliteIntegrationTests : SqliteTestBase
+{
+ [Fact]
+ public void GeneratedEntity_CanSaveAndReadFields_AllTypes()
+ {
+ // TODO:
+ // array
+ // color
+ // colour
+ // autoNumber
+ // collection
+ // entity
+ // file
+ // formula
+ // image
+ // imagePng
+ // imageJpg
+ // imageSvg
+ // object
+ // user
+ // cultureCode
+ // languageCode
+ // yaml
+ // uri
+ // url
+ // date
+ // dateTimeDuration
+ // dateTimeSchedule
+ // html
+ // json
+ // time
+ // translatedText
+ // markdown
+ // jwtToken
+
+ // TODO: commented types
+
+ var text = "TestTextValue";
+ var number = 123;
+ var money = 10;
+ var currencyCode = CurrencyCode.UAH;
+
+ var newItem = new TestEntity()
+ {
+ Id = Text.From(text),
+ TextTestField = Text.From(text),
+ NumberTestField = Number.From(number),
+ MoneyTestField = Money.From(money, currencyCode),
+ };
+ DbContext.TestEntities.Add(newItem);
+ DbContext.SaveChanges();
+
+ // Force the recreation of DBContext and ensure we have fresh data from database
+ RecreateDbContext();
+
+ var testEntity = DbContext.TestEntities.First();
+
+ // TODO: make it work without .Value
+ testEntity.Id.Value.Should().Be(text);
+ testEntity.TextTestField.Value.Should().Be(text);
+ testEntity.NumberTestField.Value.Should().Be(number);
+ testEntity.MoneyTestField.Value.Amount.Should().Be(money);
+ testEntity.MoneyTestField.Value.CurrencyCode.Should().Be(currencyCode);
+ }
+}
\ No newline at end of file
diff --git a/tests/Nox.Generator.Tests/Database/SqliteTestBase.cs b/tests/Nox.Generator.Tests/Database/SqliteTestBase.cs
new file mode 100644
index 0000000000..7a2998941d
--- /dev/null
+++ b/tests/Nox.Generator.Tests/Database/SqliteTestBase.cs
@@ -0,0 +1,55 @@
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
+using Nox.Solution;
+using Nox.Types.EntityFramework.Sqlite;
+using System;
+using TestDatabaseWebApp.Infrastructure.Persistence;
+
+namespace NoxSourceGeneratorTests.DatabaseTests;
+
+public abstract class SqliteTestBase : IDisposable
+{
+ //private const string _inMemoryConnectionStringTemplate = "DataSource=:memory:";
+ private const string _inMemoryConnectionStringTemplate = @"DataSource=test_database_{0}.db";
+ private static string _inMemoryConnectionString = string.Empty;
+ private const string _testSolutionFile = @"./Database/Design/test.solution.nox.yaml";
+ private readonly SqliteConnection _connection;
+
+ protected TestDatabaseWebAppDbContext DbContext;
+
+ protected SqliteTestBase()
+ {
+ _inMemoryConnectionString = string.Format(_inMemoryConnectionStringTemplate, DateTime.UtcNow.Ticks);
+ _connection = new SqliteConnection(_inMemoryConnectionString);
+ _connection.Open();
+ DbContext = CreateDbContext(_connection);
+ }
+
+ private static TestDatabaseWebAppDbContext CreateDbContext(SqliteConnection connection)
+ {
+ var databaseConfigurator = new SqliteDatabaseConfigurator();
+ var solution = new NoxSolutionBuilder()
+ .UseYamlFile(_testSolutionFile)
+ .Build();
+ var options = new DbContextOptionsBuilder()
+ .UseSqlite(connection)
+ .Options;
+ var dbContext = new TestDatabaseWebAppDbContext(options, solution, databaseConfigurator);
+ dbContext.Database.EnsureCreated();
+ return dbContext;
+ }
+
+ internal void RecreateDbContext()
+ {
+ var previousDbContext = DbContext;
+ DbContext = CreateDbContext(_connection);
+ previousDbContext.Dispose();
+ }
+
+ public void Dispose()
+ {
+ GC.SuppressFinalize(this);
+ DbContext?.Dispose();
+ _connection.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/tests/Nox.Generator.Tests/Nox.Generator.Tests.csproj b/tests/Nox.Generator.Tests/Nox.Generator.Tests.csproj
index 6f5f7daf9d..5522aa9b93 100644
--- a/tests/Nox.Generator.Tests/Nox.Generator.Tests.csproj
+++ b/tests/Nox.Generator.Tests/Nox.Generator.Tests.csproj
@@ -2,7 +2,7 @@
net7.0
- false
+ false
@@ -13,6 +13,9 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
@@ -30,7 +33,10 @@
+
+
+
@@ -38,6 +44,7 @@
+
@@ -74,6 +81,9 @@
+
+ Always
+
Always