Skip to content

Commit 9f4ce4d

Browse files
authored
Merge pull request #80 from msallin/#76
#76: Ability to use SQLite.CodeFirst with :memory:
2 parents 4f174a3 + 69e1138 commit 9f4ce4d

32 files changed

+464
-132
lines changed

SQLite.CodeFirst.Console/FootballDbContext.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
1-
using System.Data.Entity;
1+
using System.Data.Common;
2+
using System.Data.Entity;
23

34
namespace SQLite.CodeFirst.Console
45
{
56
public class FootballDbContext : DbContext
67
{
7-
public FootballDbContext()
8-
: base("footballDb")
8+
public FootballDbContext(string nameOrConnectionString)
9+
: base(nameOrConnectionString)
10+
{
11+
Configure();
12+
}
13+
14+
public FootballDbContext(DbConnection connection, bool contextOwnsConnection)
15+
: base(connection, contextOwnsConnection)
16+
{
17+
Configure();
18+
}
19+
20+
private void Configure()
921
{
1022
Configuration.ProxyCreationEnabled = true;
1123
Configuration.LazyLoadingEnabled = true;
Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Collections.Generic;
21
using System.Data.Entity;
32
using SQLite.CodeFirst.Console.Entity;
43

@@ -12,42 +11,7 @@ public FootballDbInitializer(DbModelBuilder modelBuilder)
1211

1312
protected override void Seed(FootballDbContext context)
1413
{
15-
context.Set<Team>().Add(new Team
16-
{
17-
Name = "YB",
18-
Coach = new Coach
19-
{
20-
City = "Zürich",
21-
FirstName = "Masssaman",
22-
LastName = "Nachn",
23-
Street = "Testingstreet 844"
24-
},
25-
Players = new List<Player>
26-
{
27-
new Player
28-
{
29-
City = "Bern",
30-
FirstName = "Marco",
31-
LastName = "Bürki",
32-
Street = "Wunderstrasse 43",
33-
Number = 12
34-
},
35-
new Player
36-
{
37-
City = "Berlin",
38-
FirstName = "Alain",
39-
LastName = "Rochat",
40-
Street = "Wonderstreet 13",
41-
Number = 14
42-
}
43-
},
44-
Stadion = new Stadion
45-
{
46-
Name = "Stade de Suisse",
47-
City = "Bern",
48-
Street = "Papiermühlestrasse 71"
49-
}
50-
});
14+
// Here you can seed your core data if you have any.
5115
}
5216
}
5317
}

SQLite.CodeFirst.Console/Program.cs

Lines changed: 86 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,107 @@
1-
using SQLite.CodeFirst.Console.Entity;
1+
using System.Collections.Generic;
2+
using System.Data.Entity;
3+
using System.Data.SQLite;
4+
using System.Linq;
5+
using SQLite.CodeFirst.Console.Entity;
26

37
namespace SQLite.CodeFirst.Console
48
{
59
public static class Program
610
{
7-
static void Main()
11+
private static void Main()
812
{
9-
System.Console.WriteLine("Starting Demo Application");
13+
StartDemoUseInMemory();
14+
StartDemoUseFile();
15+
PressEnterToExit();
16+
}
1017

11-
var context = CreateAndSeedDatabase();
18+
private static void StartDemoUseInMemory()
19+
{
20+
System.Console.WriteLine("Starting Demo Application (In Memory)");
21+
System.Console.WriteLine(string.Empty);
1222

13-
DisplaySeededData(context);
23+
using (var sqLiteConnection = new SQLiteConnection("data source=:memory:"))
24+
{
25+
// This is required if a in memory db is used.
26+
sqLiteConnection.Open();
1427

15-
PressEnterToExit();
28+
using (var context = new FootballDbContext(sqLiteConnection, false))
29+
{
30+
CreateAndSeedDatabase(context);
31+
DisplaySeededData(context);
32+
}
33+
}
1634
}
1735

18-
private static FootballDbContext CreateAndSeedDatabase()
36+
private static void StartDemoUseFile()
37+
{
38+
System.Console.WriteLine("Starting Demo Application (File)");
39+
System.Console.WriteLine(string.Empty);
40+
41+
using (var context = new FootballDbContext("footballDb"))
42+
{
43+
CreateAndSeedDatabase(context);
44+
DisplaySeededData(context);
45+
}
46+
}
47+
48+
private static void CreateAndSeedDatabase(DbContext context)
1949
{
2050
System.Console.WriteLine("Create and seed the database.");
21-
var context = new FootballDbContext();
51+
52+
if (context.Set<Team>().Count() != 0)
53+
{
54+
return;
55+
}
56+
57+
context.Set<Team>().Add(new Team
58+
{
59+
Name = "YB",
60+
Coach = new Coach
61+
{
62+
City = "Zürich",
63+
FirstName = "Masssaman",
64+
LastName = "Nachn",
65+
Street = "Testingstreet 844"
66+
},
67+
Players = new List<Player>
68+
{
69+
new Player
70+
{
71+
City = "Bern",
72+
FirstName = "Marco",
73+
LastName = "Bürki",
74+
Street = "Wunderstrasse 43",
75+
Number = 12
76+
},
77+
new Player
78+
{
79+
City = "Berlin",
80+
FirstName = "Alain",
81+
LastName = "Rochat",
82+
Street = "Wonderstreet 13",
83+
Number = 14
84+
}
85+
},
86+
Stadion = new Stadion
87+
{
88+
Name = "Stade de Suisse",
89+
City = "Bern",
90+
Street = "Papiermühlestrasse 71"
91+
}
92+
});
93+
94+
context.SaveChanges();
95+
2296
System.Console.WriteLine("Completed.");
2397
System.Console.WriteLine();
24-
return context;
2598
}
2699

27-
private static void DisplaySeededData(FootballDbContext context)
100+
private static void DisplaySeededData(DbContext context)
28101
{
29102
System.Console.WriteLine("Display seeded data.");
30103

31-
foreach (var team in context.Set<Team>())
104+
foreach (Team team in context.Set<Team>())
32105
{
33106
System.Console.WriteLine("\t Team:");
34107
System.Console.WriteLine("\t Id: {0}", team.Id);
@@ -49,7 +122,7 @@ private static void DisplaySeededData(FootballDbContext context)
49122
System.Console.WriteLine("\t\t City: {0}", team.Coach.City);
50123
System.Console.WriteLine();
51124

52-
foreach (var player in team.Players)
125+
foreach (Player player in team.Players)
53126
{
54127
System.Console.WriteLine("\t\t Player:");
55128
System.Console.WriteLine("\t\t Id: {0}", player.Id);
@@ -70,4 +143,4 @@ private static void PressEnterToExit()
70143
System.Console.ReadLine();
71144
}
72145
}
73-
}
146+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System.Collections.Generic;
2+
using System.Data.Common;
3+
using System.Data.SQLite;
4+
using System.Linq;
5+
using Microsoft.VisualStudio.TestTools.UnitTesting;
6+
using SQLite.CodeFirst.Console;
7+
using SQLite.CodeFirst.Console.Entity;
8+
9+
namespace SQLite.CodeFirst.Test.IntegrationTests
10+
{
11+
[TestClass]
12+
public class MemoryDbTest
13+
{
14+
[TestMethod]
15+
public void CreateInMemoryDatabaseTest()
16+
{
17+
using (DbConnection connection = new SQLiteConnection("data source=:memory:"))
18+
{
19+
// This is important! Else the in memory database will not work.
20+
connection.Open();
21+
22+
using (var context = new FootballDbContext(connection, false))
23+
{
24+
context.Set<Team>().Add(new Team
25+
{
26+
Name = "New",
27+
Coach = new Coach
28+
{
29+
City = "New",
30+
FirstName = "New",
31+
LastName = "New",
32+
Street = "New"
33+
},
34+
Players = new List<Player>
35+
{
36+
new Player
37+
{
38+
City = "New",
39+
FirstName = "New",
40+
LastName = "New",
41+
Street = "New",
42+
Number = 1
43+
},
44+
new Player
45+
{
46+
City = "New",
47+
FirstName = "New",
48+
LastName = "New",
49+
Street = "New",
50+
Number = 2
51+
}
52+
},
53+
Stadion = new Stadion
54+
{
55+
Name = "New",
56+
City = "New",
57+
Street = "New"
58+
}
59+
});
60+
61+
context.SaveChanges();
62+
}
63+
64+
using (var context = new FootballDbContext(connection, false))
65+
{
66+
Assert.AreEqual(1, context.Set<Team>().Count());
67+
}
68+
}
69+
}
70+
}
71+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using System;
2+
using System.Data.Common;
3+
using System.Data.Entity;
4+
using System.Data.Entity.Infrastructure;
5+
using System.Data.SQLite;
6+
using System.Linq;
7+
using Microsoft.VisualStudio.TestTools.UnitTesting;
8+
using SQLite.CodeFirst.Console;
9+
using SQLite.CodeFirst.Console.Entity;
10+
11+
namespace SQLite.CodeFirst.Test.IntegrationTests
12+
{
13+
[TestClass]
14+
public class SqlGenerationTest
15+
{
16+
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);
20+
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);
24+
CREATE INDEX ""IX_MyTable_Id"" ON ""MyTable"" (Id);
25+
CREATE INDEX IX_Team_TeamsName ON ""MyTable"" (Name);
26+
27+
CREATE INDEX ""IX_TeamPlayer_Number"" ON ""TeamPlayer"" (Number);
28+
CREATE UNIQUE INDEX IX_TeamPlayer_NumberPerTeam ON ""TeamPlayer"" (Number, TeamId);
29+
CREATE INDEX ""IX_TeamPlayer_Mentor_Id"" ON ""TeamPlayer"" (Mentor_Id);
30+
CREATE UNIQUE INDEX IX_Stadion_Main ON ""Stadions"" (Street, Name);
31+
CREATE INDEX ""IX_Stadion_Team_Id"" ON ""Stadions"" (Team_Id);
32+
CREATE INDEX ""IX_Foo_FooSelf1Id"" ON ""Foos"" (FooSelf1Id);
33+
CREATE INDEX ""IX_Foo_FooSelf2Id"" ON ""Foos"" (FooSelf2Id);
34+
CREATE INDEX ""IX_Foo_FooSelf3Id"" ON ""Foos"" (FooSelf3Id);
35+
CREATE INDEX ""IX_FooSelf_FooId"" ON ""FooSelves"" (FooId);
36+
CREATE INDEX ""IX_FooStep_FooId"" ON ""FooSteps"" (FooId);";
37+
38+
private static string generatedSql;
39+
40+
// Does not work on the build server. No clue why.
41+
[Ignore]
42+
[TestMethod]
43+
public void SqliteSqlGeneratorTest()
44+
{
45+
using (DbConnection connection = new SQLiteConnection("data source=:memory:"))
46+
{
47+
// This is important! Else the in memory database will not work.
48+
connection.Open();
49+
50+
using (var context = new DummyDbContext(connection))
51+
{
52+
// ReSharper disable once UnusedVariable
53+
Player fo = context.Set<Player>().FirstOrDefault();
54+
55+
Assert.IsTrue(string.Equals(ReferenceSql.Trim(), generatedSql.Trim(), StringComparison.OrdinalIgnoreCase));
56+
}
57+
}
58+
}
59+
60+
private class DummyDbContext : DbContext
61+
{
62+
public DummyDbContext(DbConnection connection)
63+
: base(connection, false)
64+
{
65+
}
66+
67+
protected override void OnModelCreating(DbModelBuilder modelBuilder)
68+
{
69+
// This configuration contains all supported cases.
70+
// So it makes a perfect test to validate whether the
71+
// generated SQL is correct.
72+
ModelConfiguration.Configure(modelBuilder);
73+
var initializer = new AssertInitializer(modelBuilder);
74+
Database.SetInitializer(initializer);
75+
}
76+
}
77+
78+
private class AssertInitializer : SqliteInitializerBase<DummyDbContext>
79+
{
80+
public AssertInitializer(DbModelBuilder modelBuilder)
81+
: base(modelBuilder)
82+
{
83+
}
84+
85+
public override void InitializeDatabase(DummyDbContext context)
86+
{
87+
DbModel model = ModelBuilder.Build(context.Database.Connection);
88+
var sqliteSqlGenerator = new SqliteSqlGenerator();
89+
generatedSql = sqliteSqlGenerator.Generate(model.StoreModel);
90+
base.InitializeDatabase(context);
91+
}
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)