From b85f96deeaf2887772a579bc6177403316e3656f Mon Sep 17 00:00:00 2001 From: abigailvp Date: Tue, 12 Aug 2025 15:59:23 +0200 Subject: [PATCH 1/4] feat(schema): adding some basic tests #27 --- .../Schema/SqlGeneration/IdentityStrategy.cs | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs diff --git a/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs b/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs new file mode 100644 index 0000000..7097b4b --- /dev/null +++ b/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs @@ -0,0 +1,108 @@ +using EntityFramework.Explained._Tools.TestContexts; +using Microsoft.EntityFrameworkCore; +using QuickPulse.Explains; +using QuickPulse.Explains.Text; + +namespace EntityFramework.Explained.Schema.Conventions; + +[DocFile] +public class IdentityStrategy +{ + public class UnidentifiedThing + { + public int Id { get; set; } + } + + [Keyless] + public class ProfessionalUnidentifiedThing + { + public int Id { get; set; } + } + + [PrimaryKey(nameof(Id))] + public class Thing + { + public Guid Id { get; set; } + public SmallThing? thingy { get; set; } + } + + [Owned] + public class SmallThing + { + public string? description { get; set; } + } + + [Fact] + [DocHeader("Sql Server")] + [DocContent("throws InvalidOperationException if primary key is not defined")] + public void SqlServer_No_Pk() + { + using var context = new TestSqlServerContext(); + var ex = Assert.Throws(() => context.Database.GenerateCreateScript()); + Assert.Contains("The entity type 'Id' requires a primary key to be defined.", ex.Message); + } + + [Fact] + [DocHeader("Sql Server")] + [DocContent("generates id as a column with Primary Key constraint in table when primary key is defined of right type")] + public void SqlServer_With_Pk() + { + using var context = new TestSqlServerContext(); + var sql = context.Database.GenerateCreateScript(); + var reader = LinesReader.FromText(sql); + + Assert.Equal(" [Id] uniqueidentifier NOT NULL,", reader.SkipToLineContaining("Id")); + Assert.Equal(" CONSTRAINT [PK_Items] PRIMARY KEY ([Id])", reader.NextLine()); + } + + [Fact] + [DocHeader("Sql Server")] + [DocContent("doesn't need a pk if data annotation says so ([Keyless]. You cannot use CRUD on this table.")] + public void SqlServer_With_Keyless_Configured() + { + using var context = new TestSqlServerContext(); + var sql = context.Database.GenerateCreateScript(); + var reader = LinesReader.FromText(sql); + + Assert.Equal("CREATE TABLE [Items] (", reader.NextLine()); + Assert.Equal(" [Id] int NOT NULL", reader.NextLine()); + } + + [Fact] + [DocHeader("Sqlite")] + [DocContent("generates Id as a column with Primary Key constraint in table when primary key is defined of right type")] + public void Sqlite_With_Pk() + { + using var context = new TestSqliteContext(); + var sql = context.Database.GenerateCreateScript(); + var reader = LinesReader.FromText(sql); + + Assert.Equal(" \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY", reader.SkipToLineContaining("Id")); + } + + [Fact] + [DocHeader("Sqlite")] + [DocContent("only needs an Id for entities, not for valuetypes inside an entity.")] + public void Sqlite_Only_Id_For_Entities() + { + using var context = new TestSqliteContext(); + var sql = context.Database.GenerateCreateScript(); + var reader = LinesReader.FromText(sql); + + Assert.Equal(" \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,", reader.SkipToLineContaining("Id")); + Assert.Equal(" \"thingy_description\" TEXT NOT NULL", reader.NextLine()); + } + + [Fact] + [DocHeader("Sqlite")] + [DocContent("can only have specific types, SqlServer is even stricter in which types can be used. ")] + public void Sqlite__With_Pk() + { + using var context = new TestSqliteContext(); + var sql = context.Database.GenerateCreateScript(); + var reader = LinesReader.FromText(sql); + + Assert.Equal(" \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,", reader.SkipToLineContaining("Id")); + Assert.Equal(" \"thingy_description\" TEXT NOT NULL", reader.NextLine()); + } +} \ No newline at end of file From 76ae36e3c73a7c87c4bd4ad756baae636f947e83 Mon Sep 17 00:00:00 2001 From: abigailvp Date: Tue, 12 Aug 2025 16:24:01 +0200 Subject: [PATCH 2/4] feat(schema): tests finalised #27 --- .../Schema/SqlGeneration/IdentityStrategy.cs | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs b/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs index 7097b4b..cf90421 100644 --- a/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs +++ b/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs @@ -44,7 +44,7 @@ public void SqlServer_No_Pk() [Fact] [DocHeader("Sql Server")] - [DocContent("generates id as a column with Primary Key constraint in table when primary key is defined of right type")] + [DocContent("generates an id as a column. It also has a Primary Key constraint (id can't be null and has to be unique per record) in table when primary key is defined of right type")] public void SqlServer_With_Pk() { using var context = new TestSqlServerContext(); @@ -57,7 +57,7 @@ public void SqlServer_With_Pk() [Fact] [DocHeader("Sql Server")] - [DocContent("doesn't need a pk if data annotation says so ([Keyless]. You cannot use CRUD on this table.")] + [DocContent("doesn't need a pk if data annotation says so ([Keyless]). You cannot use CRUD on this table.")] public void SqlServer_With_Keyless_Configured() { using var context = new TestSqlServerContext(); @@ -70,7 +70,7 @@ public void SqlServer_With_Keyless_Configured() [Fact] [DocHeader("Sqlite")] - [DocContent("generates Id as a column with Primary Key constraint in table when primary key is defined of right type")] + [DocContent("generates an id as a column. It also has a Primary Key constraint (id can't be null and has to be unique per record) in table when primary key is defined of right type")] public void Sqlite_With_Pk() { using var context = new TestSqliteContext(); @@ -92,17 +92,4 @@ public void Sqlite_Only_Id_For_Entities() Assert.Equal(" \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,", reader.SkipToLineContaining("Id")); Assert.Equal(" \"thingy_description\" TEXT NOT NULL", reader.NextLine()); } - - [Fact] - [DocHeader("Sqlite")] - [DocContent("can only have specific types, SqlServer is even stricter in which types can be used. ")] - public void Sqlite__With_Pk() - { - using var context = new TestSqliteContext(); - var sql = context.Database.GenerateCreateScript(); - var reader = LinesReader.FromText(sql); - - Assert.Equal(" \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,", reader.SkipToLineContaining("Id")); - Assert.Equal(" \"thingy_description\" TEXT NOT NULL", reader.NextLine()); - } } \ No newline at end of file From c9730b9fa7fa82bc8b16b9864ddc0bc8c7e62ab0 Mon Sep 17 00:00:00 2001 From: abigailvp Date: Tue, 12 Aug 2025 16:38:00 +0200 Subject: [PATCH 3/4] feat(schema): test fixed #27 --- .../Schema/SqlGeneration/IdentityStrategy.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs b/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs index cf90421..02f5dea 100644 --- a/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs +++ b/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs @@ -77,7 +77,7 @@ public void Sqlite_With_Pk() var sql = context.Database.GenerateCreateScript(); var reader = LinesReader.FromText(sql); - Assert.Equal(" \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY", reader.SkipToLineContaining("Id")); + Assert.Equal(" \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,", reader.SkipToLineContaining("Id")); } [Fact] From b581e46c0ce37d164b86cd8d820ca82bfa700828 Mon Sep 17 00:00:00 2001 From: abigailvp Date: Tue, 12 Aug 2025 16:53:51 +0200 Subject: [PATCH 4/4] feat(schema): tests really fixed now #27 --- .../Schema/SqlGeneration/IdentityStrategy.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs b/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs index 02f5dea..aa238d6 100644 --- a/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs +++ b/EntityFramework.Explained/Schema/SqlGeneration/IdentityStrategy.cs @@ -10,7 +10,7 @@ public class IdentityStrategy { public class UnidentifiedThing { - public int Id { get; set; } + public int Name { get; set; } } [Keyless] @@ -34,12 +34,12 @@ public class SmallThing [Fact] [DocHeader("Sql Server")] - [DocContent("throws InvalidOperationException if primary key is not defined")] + [DocContent("throws InvalidOperationException if primary key is not defined or there is no property with 'id' in name")] public void SqlServer_No_Pk() { using var context = new TestSqlServerContext(); var ex = Assert.Throws(() => context.Database.GenerateCreateScript()); - Assert.Contains("The entity type 'Id' requires a primary key to be defined.", ex.Message); + Assert.Contains("The entity type 'UnidentifiedThing' requires a primary key to be defined.", ex.Message); } [Fact] @@ -52,6 +52,7 @@ public void SqlServer_With_Pk() var reader = LinesReader.FromText(sql); Assert.Equal(" [Id] uniqueidentifier NOT NULL,", reader.SkipToLineContaining("Id")); + Assert.Equal(" [thingy_description] nvarchar(max) NULL,", reader.NextLine()); Assert.Equal(" CONSTRAINT [PK_Items] PRIMARY KEY ([Id])", reader.NextLine()); } @@ -90,6 +91,6 @@ public void Sqlite_Only_Id_For_Entities() var reader = LinesReader.FromText(sql); Assert.Equal(" \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,", reader.SkipToLineContaining("Id")); - Assert.Equal(" \"thingy_description\" TEXT NOT NULL", reader.NextLine()); + Assert.Equal(" \"thingy_description\" TEXT NULL", reader.NextLine()); } } \ No newline at end of file