Skip to content

Commit b9db2ac

Browse files
committed
Support for multiple, none integer, primary keys by using the "Key" annotation.
1 parent a7697d8 commit b9db2ac

15 files changed

+149
-79
lines changed

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ I started with the [code](https://gist.github.com/flaub/1968486e1b3f2b9fddaf) fr
66

77
Currently the following is supported:
88
- Tables from classes (with table annotation)
9-
- Columns from properties
10-
- ForeignKey constraint (1-n relationships)
11-
- Cascade on delete
12-
- PrimaryKey constraint (An int PrimaryKey will automatically be incremented)
9+
- Columns from properties (with key annotation)
10+
- Auto increment (An int PrimaryKey will automatically be incremented)
11+
- ForeignKey constraint (1-n relationships, support for 'Cascade on delete')
1312
- Not Null constraint
1413

1514
I tried to write the code in a extensible way.
1615
The logic is devided into two main parts. Builder and Statement.
17-
The Builder-Part knows how to translate the EdmModel into statements where a statement class creates the SQLite-SQL-Code. The structure of the statements is influenced by the [SQLite Language Specification](https://www.sqlite.org/lang.html).
16+
The Builder knows how to translate the EdmModel into statements where a statement class creates the SQLite-DDL-Code.
17+
The structure of the statements is influenced by the [SQLite Language Specification](https://www.sqlite.org/lang.html).
18+
You will find an extensive usage of the composite pattern.
1819

1920
## How to use
2021
If you want to let the Entity Framework create the database, if it does not exist, just set `SqliteContextInitializer<>` as your `IDbInitializer`.
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-

1+
using System.ComponentModel.DataAnnotations;
2+
using System.ComponentModel.DataAnnotations.Schema;
3+
24
namespace SQLite.CodeFirst.Console.Entity
35
{
4-
public class Player : IEntity
6+
public class Player
57
{
6-
public int Id { get; set; }
7-
public string Name { get; set; }
8+
[Key]
9+
[Column(Order = 1)]
10+
public string FirstName { get; set; }
11+
[Key]
12+
[Column(Order = 2)]
13+
public string LastName { get; set; }
814
public Team Team { get; set; }
915
}
1016
}

SQLite.CodeFirst.Console/TestDbContext.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System;
2-
using System.Data.Entity;
3-
using System.Data.Entity.ModelConfiguration.Configuration;
1+
using System.Data.Entity;
42
using System.Data.Entity.ModelConfiguration.Conventions;
53
using SQLite.CodeFirst.Console.Entity;
64

@@ -32,8 +30,7 @@ private static void ConfigurePlayerEntity(DbModelBuilder modelBuilder)
3230
{
3331
modelBuilder.RegisterEntityType(typeof(Player));
3432

35-
modelBuilder.Entity<Player>().HasKey(player => player.Id);
36-
modelBuilder.Entity<Player>().Property(player => player.Name).HasMaxLength(10);
33+
modelBuilder.Entity<Player>().Property(player => player.FirstName).HasMaxLength(10);
3734

3835
modelBuilder.Entity<Player>().ToTable("TeamPlayer");
3936

SQLite.CodeFirst/Builder/ColumnCollectionBuilder.cs renamed to SQLite.CodeFirst/Builder/ColumnStatementCollectionBuilder.cs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,18 @@
66

77
namespace SQLite.CodeFirst.Builder
88
{
9-
internal class ColumnCollectionBuilder : IStatementBuilder<ColumnCollection>
9+
internal class ColumnStatementCollectionBuilder : IStatementBuilder<ColumnStatementCollection>
1010
{
1111
private readonly IEnumerable<EdmProperty> properties;
1212

13-
public ColumnCollectionBuilder(IEnumerable<EdmProperty> properties)
13+
public ColumnStatementCollectionBuilder(IEnumerable<EdmProperty> properties)
1414
{
1515
this.properties = properties;
1616
}
1717

18-
public ColumnCollection BuildStatement()
18+
public ColumnStatementCollection BuildStatement()
1919
{
20-
var columnDefStatement = new ColumnCollection
21-
{
22-
ColumnStatements = CreateColumnStatements().ToList()
23-
};
24-
20+
var columnDefStatement = new ColumnStatementCollection(CreateColumnStatements().ToList());
2521
return columnDefStatement;
2622
}
2723

@@ -33,24 +29,20 @@ private IEnumerable<ColumnStatement> CreateColumnStatements()
3329
{
3430
ColumnName = property.Name,
3531
TypeName = property.TypeName,
36-
ColumnConstraints = new ColumnConstraintCollection
37-
{
38-
ColumnConstraints = new List<IColumnConstraint>()
39-
}
32+
ColumnConstraints = new ColumnConstraintCollection()
4033
};
4134

35+
AdjustDatatypeForAutogenerationIfNecessary(property, columnStatement);
4236
AddNullConstraintIfNecessary(property, columnStatement);
43-
AddPrimaryKeyIfNecessary(property, columnStatement);
4437

4538
yield return columnStatement;
4639
}
4740
}
4841

49-
private static void AddPrimaryKeyIfNecessary(EdmProperty property, ColumnStatement columnStatement)
42+
private static void AdjustDatatypeForAutogenerationIfNecessary(EdmProperty property, ColumnStatement columnStatement)
5043
{
5144
if (property.StoreGeneratedPattern == StoreGeneratedPattern.Identity)
5245
{
53-
columnStatement.ColumnConstraints.ColumnConstraints.Add(new PrimaryKeyConstraint());
5446
// Must be INTEGER else SQLite will not generate the Ids
5547
columnStatement.TypeName = columnStatement.TypeName.ToLower() == "int" ? "INTEGER" : columnStatement.TypeName;
5648
}
@@ -59,8 +51,10 @@ private static void AddPrimaryKeyIfNecessary(EdmProperty property, ColumnStateme
5951
private static void AddNullConstraintIfNecessary(EdmProperty property, ColumnStatement columnStatement)
6052
{
6153
if (!property.Nullable && property.StoreGeneratedPattern != StoreGeneratedPattern.Identity)
54+
{
6255
// Only mark it as NotNull if it should not be generated.
63-
columnStatement.ColumnConstraints.ColumnConstraints.Add(new NotNullConstraint());
56+
columnStatement.ColumnConstraints.Add(new NotNullConstraint());
57+
}
6458
}
6559
}
6660
}

SQLite.CodeFirst/Builder/CreateDatabaseStatementBuilder.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ public CreateDatabaseStatementBuilder(EdmModel edmModel)
1616

1717
public CreateDatabaseStatement BuildStatement()
1818
{
19-
var createDatabaseStatement = new CreateDatabaseStatement
20-
{
21-
CreateTableStatements = GetCreateTableStatements()
22-
};
23-
19+
var createDatabaseStatement = new CreateDatabaseStatement(GetCreateTableStatements());
2420
return createDatabaseStatement;
2521
}
2622

SQLite.CodeFirst/Builder/CreateTableStatementBuilder.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@ public CreateTableStatementBuilder(EntityType entityType, IEnumerable<Associatio
1818

1919
public CreateTableStatement BuildStatement()
2020
{
21-
var simpleColumnCollection = new ColumnCollectionBuilder(entityType.Properties).BuildStatement();
22-
var foreignKeyCollection = new ForeignKeyCollectionBuilder(associationTypes).BuildStatement();
23-
var columnCollection = new ColumnCollection
24-
{
25-
ColumnStatements = simpleColumnCollection.ColumnStatements.Concat(foreignKeyCollection.ColumnStatements)
26-
};
21+
var simpleColumnCollection = new ColumnStatementCollectionBuilder(entityType.Properties).BuildStatement();
22+
var primaryKeyStatement = new PrimaryKeyStatementBuilder(entityType.KeyMembers).BuildStatement();
23+
var foreignKeyCollection = new ForeignKeyStatementBuilder(associationTypes).BuildStatement();
24+
25+
List<IStatement> columnStatements = new List<IStatement>();
26+
columnStatements.AddRange(simpleColumnCollection);
27+
columnStatements.Add(primaryKeyStatement);
28+
columnStatements.AddRange(foreignKeyCollection);
2729

2830
return new CreateTableStatement
2931
{
3032
TableName = GetTableName(),
31-
ColumnCollection = columnCollection
33+
ColumnStatementCollection = new ColumnStatementCollection(columnStatements)
3234
};
3335
}
3436

SQLite.CodeFirst/Builder/ForeignKeyCollectionBuilder.cs renamed to SQLite.CodeFirst/Builder/ForeignKeyStatementBuilder.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,18 @@
55

66
namespace SQLite.CodeFirst.Builder
77
{
8-
internal class ForeignKeyCollectionBuilder : IStatementBuilder<ColumnCollection>
8+
internal class ForeignKeyStatementBuilder : IStatementBuilder<ColumnStatementCollection>
99
{
1010
private readonly IEnumerable<AssociationType> associationTypes;
1111

12-
public ForeignKeyCollectionBuilder(IEnumerable<AssociationType> associationTypes)
12+
public ForeignKeyStatementBuilder(IEnumerable<AssociationType> associationTypes)
1313
{
1414
this.associationTypes = associationTypes;
1515
}
1616

17-
public ColumnCollection BuildStatement()
17+
public ColumnStatementCollection BuildStatement()
1818
{
19-
var columnDefStatement = new ColumnCollection
20-
{
21-
ColumnStatements = GetForeignKeyStatements().ToList()
22-
};
23-
19+
var columnDefStatement = new ColumnStatementCollection(GetForeignKeyStatements().ToList());
2420
return columnDefStatement;
2521
}
2622

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 PrimaryKeyStatementBuilder : IStatementBuilder<PrimaryKeyStatement>
9+
{
10+
private readonly IEnumerable<EdmMember> keyMembers;
11+
12+
public PrimaryKeyStatementBuilder(IEnumerable<EdmMember> keyMembers)
13+
{
14+
this.keyMembers = keyMembers;
15+
}
16+
17+
public PrimaryKeyStatement BuildStatement()
18+
{
19+
return new PrimaryKeyStatement(keyMembers.Select(km => km.Name));
20+
}
21+
}
22+
}

SQLite.CodeFirst/SQLite.CodeFirst.csproj

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,14 @@
4646
<Reference Include="System" />
4747
<Reference Include="System.Core" />
4848
<Reference Include="System.Data" />
49+
<Reference Include="System.Data.Entity" />
4950
</ItemGroup>
5051
<ItemGroup>
51-
<Compile Include="Builder\ColumnCollectionBuilder.cs" />
52-
<Compile Include="Builder\ForeignKeyCollectionBuilder.cs" />
52+
<Compile Include="Builder\ColumnStatementCollectionBuilder.cs" />
53+
<Compile Include="Builder\ForeignKeyStatementBuilder.cs" />
5354
<Compile Include="Builder\CreateDatabaseStatementBuilder.cs" />
55+
<Compile Include="Builder\PrimaryKeyStatementBuilder.cs" />
56+
<Compile Include="Statement\PrimaryKeyStatement.cs" />
5457
<Compile Include="Properties\AssemblyInfo.cs" />
5558
<Compile Include="SqliteConnectionStringParser.cs" />
5659
<Compile Include="SqliteContextInitializer.cs" />
@@ -60,7 +63,7 @@
6063
<Compile Include="Statement\ForeignKeyStatement.cs" />
6164
<Compile Include="Statement\ColumnConstraint\IColumnConstraint.cs" />
6265
<Compile Include="Statement\ColumnConstraint\NotNullConstraint.cs" />
63-
<Compile Include="Statement\ColumnCollection.cs" />
66+
<Compile Include="Statement\ColumnStatementCollection.cs" />
6467
<Compile Include="Statement\ColumnStatement.cs" />
6568
<Compile Include="Statement\CreateDatabaseStatement.cs" />
6669
<Compile Include="Statement\CreateTableStatement.cs" />

SQLite.CodeFirst/Statement/ColumnCollection.cs

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)