Skip to content

Commit 97b962d

Browse files
okipol88msallin
authored andcommitted
81: Added possibility to use pure autoincrement db column type.
1 parent 9f4ce4d commit 97b962d

File tree

15 files changed

+165
-40
lines changed

15 files changed

+165
-40
lines changed

SQLite.CodeFirst.Console/Entity/Team.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace SQLite.CodeFirst.Console.Entity
66
{
77
public class Team : IEntity
88
{
9+
[Autoincrement]
910
public int Id { get; set; }
1011

1112
[Index("IX_Team_TeamsName")] // Test for named index.

SQLite.CodeFirst.Test/IntegrationTests/SqlGenerationTest.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ namespace SQLite.CodeFirst.Test.IntegrationTests
1414
public class SqlGenerationTest
1515
{
1616
private const string ReferenceSql =
17-
@"CREATE TABLE ""MyTable"" ([Id] int NOT NULL, [Name] nvarchar NOT NULL, PRIMARY KEY(Id), FOREIGN KEY (Id) REFERENCES ""Coaches""(Id));
18-
CREATE TABLE ""Coaches"" ([Id] INTEGER, [FirstName] nvarchar (50) COLLATE NOCASE, [LastName] nvarchar (50), [Street] nvarchar (100), [City] nvarchar NOT NULL, PRIMARY KEY(Id));
19-
CREATE TABLE ""TeamPlayer"" ([Id] INTEGER, [Number] int NOT NULL, [TeamId] int NOT NULL, [FirstName] nvarchar (50) COLLATE NOCASE, [LastName] nvarchar (50), [Street] nvarchar (100), [City] nvarchar NOT NULL, [Mentor_Id] int, PRIMARY KEY(Id), FOREIGN KEY (Mentor_Id) REFERENCES ""TeamPlayer""(Id), FOREIGN KEY (TeamId) REFERENCES ""MyTable""(Id) ON DELETE CASCADE);
17+
@"CREATE TABLE ""MyTable"" ([Id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [Name] nvarchar NOT NULL, FOREIGN KEY (Id) REFERENCES ""Coaches""(Id));
18+
CREATE TABLE ""Coaches"" ([Id] INTEGER PRIMARY KEY, [FirstName] nvarchar (50) COLLATE NOCASE, [LastName] nvarchar (50), [Street] nvarchar (100), [City] nvarchar NOT NULL);
19+
CREATE TABLE ""TeamPlayer"" ([Id] INTEGER PRIMARY KEY, [Number] int NOT NULL, [TeamId] int NOT NULL, [FirstName] nvarchar (50) COLLATE NOCASE, [LastName] nvarchar (50), [Street] nvarchar (100), [City] nvarchar NOT NULL, [Mentor_Id] int, FOREIGN KEY (Mentor_Id) REFERENCES ""TeamPlayer""(Id), FOREIGN KEY (TeamId) REFERENCES ""MyTable""(Id) ON DELETE CASCADE);
2020
CREATE TABLE ""Stadions"" ([Name] nvarchar (128) NOT NULL, [Street] nvarchar (128) NOT NULL, [City] nvarchar (128) NOT NULL, [Team_Id] int NOT NULL, PRIMARY KEY(Name, Street, City), FOREIGN KEY (Team_Id) REFERENCES ""MyTable""(Id) ON DELETE CASCADE);
21-
CREATE TABLE ""Foos"" ([FooId] INTEGER, [Name] nvarchar, [FooSelf1Id] int, [FooSelf2Id] int, [FooSelf3Id] int, PRIMARY KEY(FooId), FOREIGN KEY (FooSelf1Id) REFERENCES ""Foos""(FooId), FOREIGN KEY (FooSelf2Id) REFERENCES ""Foos""(FooId), FOREIGN KEY (FooSelf3Id) REFERENCES ""Foos""(FooId));
22-
CREATE TABLE ""FooSelves"" ([FooSelfId] INTEGER, [FooId] int NOT NULL, [Number] int NOT NULL, PRIMARY KEY(FooSelfId), FOREIGN KEY (FooId) REFERENCES ""Foos""(FooId) ON DELETE CASCADE);
23-
CREATE TABLE ""FooSteps"" ([FooStepId] INTEGER, [FooId] int NOT NULL, [Number] int NOT NULL, PRIMARY KEY(FooStepId), FOREIGN KEY (FooId) REFERENCES ""Foos""(FooId) ON DELETE CASCADE);
21+
CREATE TABLE ""Foos"" ([FooId] INTEGER PRIMARY KEY, [Name] nvarchar, [FooSelf1Id] int, [FooSelf2Id] int, [FooSelf3Id] int, FOREIGN KEY (FooSelf1Id) REFERENCES ""Foos""(FooId), FOREIGN KEY (FooSelf2Id) REFERENCES ""Foos""(FooId), FOREIGN KEY (FooSelf3Id) REFERENCES ""Foos""(FooId));
22+
CREATE TABLE ""FooSelves"" ([FooSelfId] INTEGER PRIMARY KEY, [FooId] int NOT NULL, [Number] int NOT NULL, FOREIGN KEY (FooId) REFERENCES ""Foos""(FooId) ON DELETE CASCADE);
23+
CREATE TABLE ""FooSteps"" ([FooStepId] INTEGER PRIMARY KEY, [FooId] int NOT NULL, [Number] int NOT NULL, FOREIGN KEY (FooId) REFERENCES ""Foos""(FooId) ON DELETE CASCADE);
2424
CREATE INDEX ""IX_MyTable_Id"" ON ""MyTable"" (Id);
2525
CREATE INDEX IX_Team_TeamsName ON ""MyTable"" (Name);
2626

SQLite.CodeFirst.Test/SQLite.CodeFirst.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
<Compile Include="IntegrationTests\MemoryDbTest.cs" />
9898
<Compile Include="Properties\AssemblyInfo.cs" />
9999
<Compile Include="UnitTests\Statement\ColumnConstraint\MaxLengthConstraint.cs" />
100+
<Compile Include="UnitTests\Statement\ColumnConstraint\PrimaryKeyConstraintTest.cs" />
100101
<Compile Include="UnitTests\Statement\ColumnConstraint\ColumnConstraintCollectionTest.cs" />
101102
<Compile Include="UnitTests\Statement\ColumnConstraint\NotNullConstraintTest.cs" />
102103
<Compile Include="UnitTests\Statement\ColumnConstraint\CollateConstraintTest.cs" />
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using SQLite.CodeFirst.Statement.ColumnConstraint;
3+
4+
namespace SQLite.CodeFirst.Test.UnitTests.Statement.ColumnConstraint
5+
{
6+
[TestClass]
7+
public class PrimaryKeyConstraintTest
8+
{
9+
[TestMethod]
10+
public void CreateStatement_StatementIsCorrect_WithAutoincrement()
11+
{
12+
var primaryKeyConstraint = new PrimaryKeyConstraint { Autoincrement = true };
13+
string output = primaryKeyConstraint.CreateStatement();
14+
Assert.AreEqual(output, "PRIMARY KEY AUTOINCREMENT");
15+
}
16+
17+
[TestMethod]
18+
public void CreateStatement_StatementIsCorrect()
19+
{
20+
var primaryKeyConstraint = new PrimaryKeyConstraint();
21+
string output = primaryKeyConstraint.CreateStatement();
22+
Assert.AreEqual(output, "PRIMARY KEY");
23+
}
24+
}
25+
}

SQLite.CodeFirst.Test/UnitTests/Statement/PrimaryKeyStatementTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public void CreateStatementWithOneKeyTest()
1212
{
1313
const string keyMember1 = "keyMember1";
1414

15-
var primaryKeyStatement = new PrimaryKeyStatement(new List<string> { keyMember1 });
15+
var primaryKeyStatement = new CompositePrimaryKeyStatement(new List<string> { keyMember1 });
1616
Assert.AreEqual(primaryKeyStatement.Count, 1);
1717
Assert.AreEqual(primaryKeyStatement.CreateStatement(), "PRIMARY KEY(keyMember1)");
1818
}
@@ -23,7 +23,7 @@ public void CreateStatementWithTwoKeyTest()
2323
const string keyMember1 = "keyMember1";
2424
const string keyMember2 = "keyMember2";
2525

26-
var primaryKeyStatement = new PrimaryKeyStatement(new List<string> { keyMember1, keyMember2 });
26+
var primaryKeyStatement = new CompositePrimaryKeyStatement(new List<string> { keyMember1, keyMember2 });
2727
Assert.AreEqual(primaryKeyStatement.Count, 2);
2828
Assert.AreEqual(primaryKeyStatement.CreateStatement(), "PRIMARY KEY(keyMember1, keyMember2)");
2929
}

SQLite.CodeFirst/Internal/Builder/ColumnStatementCollectionBuilder.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Collections.Generic;
22
using System.Data.Entity.Core.Metadata.Edm;
3-
using System.Globalization;
43
using System.Linq;
54
using SQLite.CodeFirst.Extensions;
65
using SQLite.CodeFirst.Statement;
@@ -11,10 +10,12 @@ namespace SQLite.CodeFirst.Builder
1110
internal class ColumnStatementCollectionBuilder : IStatementBuilder<ColumnStatementCollection>
1211
{
1312
private readonly IEnumerable<EdmProperty> properties;
13+
private readonly IEnumerable<EdmProperty> keyMembers;
1414

15-
public ColumnStatementCollectionBuilder(IEnumerable<EdmProperty> properties)
15+
public ColumnStatementCollectionBuilder(IEnumerable<EdmProperty> properties, IEnumerable<EdmProperty> keyMembers)
1616
{
1717
this.properties = properties;
18+
this.keyMembers = keyMembers;
1819
}
1920

2021
public ColumnStatementCollection BuildStatement()
@@ -39,6 +40,7 @@ private IEnumerable<ColumnStatement> CreateColumnStatements()
3940
AddNullConstraintIfNecessary(property, columnStatement);
4041
AddUniqueConstraintIfNecessary(property, columnStatement);
4142
AddCollationConstraintIfNecessary(property, columnStatement);
43+
AddPrimaryKeyConstraintAndAdjustTypeIfNecessary(property, columnStatement);
4244

4345
yield return columnStatement;
4446
}
@@ -57,7 +59,7 @@ private static void AdjustDatatypeForAutogenerationIfNecessary(EdmProperty prope
5759
if (property.StoreGeneratedPattern == StoreGeneratedPattern.Identity)
5860
{
5961
// Must be INTEGER else SQLite will not generate the Ids
60-
columnStatement.TypeName = columnStatement.TypeName.ToUpperInvariant() == "INT" ? "INTEGER" : columnStatement.TypeName;
62+
ConvertIntegerType(columnStatement);
6163
}
6264
}
6365

@@ -87,5 +89,25 @@ private static void AddUniqueConstraintIfNecessary(EdmProperty property, ColumnS
8789
columnStatement.ColumnConstraints.Add(new UniqueConstraint { OnConflict = value.OnConflict });
8890
}
8991
}
92+
93+
private void AddPrimaryKeyConstraintAndAdjustTypeIfNecessary(EdmProperty property, ColumnStatement columnStatement)
94+
{
95+
// Only handle a single primary key this way.
96+
if (keyMembers.Count() != 1 || !property.Equals(keyMembers.Single()))
97+
{
98+
return;
99+
}
100+
101+
ConvertIntegerType(columnStatement);
102+
var primaryKeyConstraint = new PrimaryKeyConstraint();
103+
primaryKeyConstraint.Autoincrement = property.GetCustomAnnotation<AutoincrementAttribute>() != null;
104+
columnStatement.ColumnConstraints.Add(primaryKeyConstraint);
105+
}
106+
107+
private static void ConvertIntegerType(ColumnStatement columnStatement)
108+
{
109+
const string integerType = "INTEGER";
110+
columnStatement.TypeName = columnStatement.TypeName.ToUpperInvariant() == "INT" ? integerType : columnStatement.TypeName;
111+
}
90112
}
91113
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Collections.Generic;
2+
using System.Data.Entity.Core.Metadata.Edm;
3+
using System.Linq;
4+
using SQLite.CodeFirst.Statement;
5+
6+
namespace SQLite.CodeFirst.Builder
7+
{
8+
internal class CompositePrimaryKeyStatementBuilder : IStatementBuilder<CompositePrimaryKeyStatement>
9+
{
10+
private readonly IEnumerable<EdmMember> keyMembers;
11+
12+
public CompositePrimaryKeyStatementBuilder(IEnumerable<EdmMember> keyMembers)
13+
{
14+
this.keyMembers = keyMembers;
15+
}
16+
17+
public CompositePrimaryKeyStatement BuildStatement()
18+
{
19+
return new CompositePrimaryKeyStatement(keyMembers.Select(km => km.Name));
20+
}
21+
}
22+
}

SQLite.CodeFirst/Internal/Builder/CreateTableStatementBuilder.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using SQLite.CodeFirst.Builder.NameCreators;
44
using SQLite.CodeFirst.Statement;
55
using SQLite.CodeFirst.Utility;
6+
using SQLite.CodeFirst.Extensions;
7+
using System.Linq;
68

79
namespace SQLite.CodeFirst.Builder
810
{
@@ -19,13 +21,22 @@ public CreateTableStatementBuilder(EntitySet entitySet, AssociationTypeContainer
1921

2022
public CreateTableStatement BuildStatement()
2123
{
22-
var simpleColumnCollection = new ColumnStatementCollectionBuilder(entitySet.ElementType.Properties).BuildStatement();
23-
var primaryKeyStatement = new PrimaryKeyStatementBuilder(entitySet.ElementType.KeyMembers).BuildStatement();
24+
var keyMembers = entitySet.ElementType.KeyMembers.Cast<EdmProperty>().ToArray();
25+
26+
// Only create a CompositePrimaryKeyStatement if there is a composite primary key.
27+
// If there is just one key member this is handled using a constraint.
28+
CompositePrimaryKeyStatement compositePrimaryKeyStatement = null;
29+
if (keyMembers.Length > 1)
30+
{
31+
compositePrimaryKeyStatement = new CompositePrimaryKeyStatementBuilder(keyMembers).BuildStatement();
32+
}
33+
34+
var simpleColumnCollection = new ColumnStatementCollectionBuilder(entitySet.ElementType.Properties, keyMembers).BuildStatement();
2435
var foreignKeyCollection = new ForeignKeyStatementBuilder(associationTypeContainer.GetAssociationTypes(entitySet.Name)).BuildStatement();
2536

2637
var columnStatements = new List<IStatement>();
2738
columnStatements.AddRange(simpleColumnCollection);
28-
columnStatements.Add(primaryKeyStatement);
39+
columnStatements.AddIfNotNull(compositePrimaryKeyStatement);
2940
columnStatements.AddRange(foreignKeyCollection);
3041

3142
return new CreateTableStatement

SQLite.CodeFirst/Internal/Builder/PrimaryKeyStatementBuilder.cs

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Collections.Generic;
2+
3+
namespace SQLite.CodeFirst.Extensions
4+
{
5+
public static class ListExtensions
6+
{
7+
public static void AddIfNotNull<T>(this ICollection<T> list, T element)
8+
{
9+
if (list == null || element == null)
10+
{
11+
return;
12+
}
13+
14+
list.Add(element);
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)