Skip to content

Commit 082b07b

Browse files
committed
Merge branch 'master' into Index_Implementation
2 parents 343e5d9 + f85bcca commit 082b07b

13 files changed

+228
-93
lines changed

README.md

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,62 @@
11
# SQLite CodeFirst
2+
**Release Build** [![Build status](https://ci.appveyor.com/api/projects/status/2qavdqctw0ehscm6/branch/master?svg=true)](https://ci.appveyor.com/project/msallin/sqlitecodefirst-nv6vn/branch/master)
3+
4+
**CI Build** [![Build status](https://ci.appveyor.com/api/projects/status/oc1miog385h801qe?svg=true)](https://ci.appveyor.com/project/msallin/sqlitecodefirst)
5+
26
Creates a [SQLite Database](https://sqlite.org/) from Code, using [Entity Framework](https://msdn.microsoft.com/en-us/data/ef.aspx) CodeFirst.
37

4-
This Project ships a `SqliteContextInitializer` which creates a new SQLite Database, based on your model/code.
8+
This Project ships several `IDbInitializer` which creates a new SQLite Database, based on your model/code.
59
I started with the [code](https://gist.github.com/flaub/1968486e1b3f2b9fddaf) from [flaub](https://github.com/flaub).
610

711
Currently the following is supported:
812
- Tables from classes (supported annotations: `Table`)
9-
- Columns from properties (supported annotations: `Column`, `Key`, `MaxLength`, `Required`)
13+
- Columns from properties (supported annotations: `Column`, `Key`, `MaxLength`, `Required`, `NotMapped`, `DatabaseGenerated`)
1014
- PrimaryKey constraint (`Key` annotation, key composites are supported)
1115
- ForeignKey constraint (1-n relationships, support for 'Cascade on delete')
1216
- Not Null constraint
1317
- Auto increment (An int PrimaryKey will automatically be incremented)
1418

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

2125
## How to use
22-
If you want to let the Entity Framework create the database, if it does not exist, just set `SqliteContextInitializer<>` as your `IDbInitializer`.
26+
Either get the assembly from the latest [release](https://github.com/msallin/SQLiteCodeFirst/releases) or install the NuGet-Package [SQLite.CodeFirst](https://www.nuget.org/packages/SQLite.CodeFirst/).
27+
28+
If you want to let the Entity Framework create the database, if it does not exist, just set `SqliteDropCreateDatabaseAlways<>` or `SqliteCreateDatabaseIfNotExists<>` as your `IDbInitializer<>`.
2329
```csharp
2430
public class MyDbContext : DbContext
2531
{
26-
public TestDbContext()
32+
public MyDbContext()
2733
: base("ConnectionStringName") { }
2834

2935
protected override void OnModelCreating(DbModelBuilder modelBuilder)
3036
{
31-
var sqliteConnectionInitializer = new SqliteContextInitializer<TestDbContext>(
37+
var sqliteConnectionInitializer = new SqliteCreateDatabaseIfNotExists<MyDbContext>(
3238
Database.Connection.ConnectionString, modelBuilder);
3339
Database.SetInitializer(sqliteConnectionInitializer);
3440
}
3541
}
3642
```
3743

38-
In a more advanced szenario you may want to populate some core- or test-data after the database was created.
39-
To do this, inherit from `SqliteContextInitializer<>` and override the `Seed(TestDbContext context)` function.
44+
In a more advanced scenario you may want to populate some core- or test-data after the database was created.
45+
To do this, inherit from `SqliteDropCreateDatabaseAlways<>` or `SqliteCreateDatabaseIfNotExists<>` and override the `Seed(MyDbContext context)` function.
4046
This function will be called, in a own transaction, right after the database was created. This function is only executed if a new database was successfully created.
4147
```csharp
42-
public class TestDbContextInitializer : SqliteContextInitializer<TestDbContext>
48+
public class MyDbContextContextInitializer : SqliteDropCreateDatabaseAlways<MyDbContext>
4349
{
44-
public TestDbContextInitializer(string connectionString, DbModelBuilder modelBuilder)
50+
public MyDbContextInitializer(string connectionString, DbModelBuilder modelBuilder)
4551
: base(connectionString, modelBuilder) { }
4652

47-
protected override void Seed(TestDbContext context)
53+
protected override void Seed(MyDbContext context)
4854
{
4955
context.Set<Player>().Add(new Player());
5056
}
5157
}
5258
```
59+
60+
## Hints
61+
If you try to reinstall the NuGet-Packages (e.g. if you want to downgrade to .NET 4.0) the app.config will be overwritten and you may gettubg an exception when you try to run the console project.
62+
In this case please check the following issue: https://github.com/msallin/SQLiteCodeFirst/issues/13.

SQLite.CodeFirst.Console/FootballDbContext.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder)
2222

2323
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
2424

25-
var sqliteConnectionInitializer = new TestDbContextInitializer(Database.Connection.ConnectionString, modelBuilder);
26-
Database.SetInitializer(sqliteConnectionInitializer);
25+
var initializer = new FootballDbInitializer(Database.Connection.ConnectionString, modelBuilder);
26+
Database.SetInitializer(initializer);
2727
}
2828

2929
private static void ConfigureTeamEntity(DbModelBuilder modelBuilder)
@@ -45,9 +45,9 @@ private static void ConfigurePlayerEntity(DbModelBuilder modelBuilder)
4545
}
4646
}
4747

48-
public class TestDbContextInitializer : SqliteContextInitializer<FootballDbContext>
48+
public class FootballDbInitializer : SqliteDropCreateDatabaseAlways<FootballDbContext>
4949
{
50-
public TestDbContextInitializer(string connectionString, DbModelBuilder modelBuilder)
50+
public FootballDbInitializer(string connectionString, DbModelBuilder modelBuilder)
5151
: base(connectionString, modelBuilder) { }
5252

5353
protected override void Seed(FootballDbContext context)

SQLite.CodeFirst.Console/Program.cs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System.IO;
2-
using SQLite.CodeFirst.Console.Entity;
1+
using SQLite.CodeFirst.Console.Entity;
32

43
namespace SQLite.CodeFirst.Console
54
{
@@ -9,27 +8,13 @@ static void Main()
98
{
109
System.Console.WriteLine("Starting Demo Application");
1110

12-
ClearExistingDbFile();
13-
1411
var context = CreateAndSeedDatabase();
1512

1613
DisplaySeededData(context);
1714

1815
PressEnterToExit();
1916
}
2017

21-
private static void ClearExistingDbFile()
22-
{
23-
System.Console.WriteLine("Check for existing db file.");
24-
const string SqliteFilePath = @".\footballDb.sqlite";
25-
if (File.Exists(SqliteFilePath))
26-
{
27-
System.Console.WriteLine("Delete existing db file.");
28-
File.Delete(SqliteFilePath);
29-
}
30-
System.Console.WriteLine();
31-
}
32-
3318
private static FootballDbContext CreateAndSeedDatabase()
3419
{
3520
System.Console.WriteLine("Create and seed the database.");
Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
using System.Reflection;
2-
using System.Runtime.CompilerServices;
32
using System.Runtime.InteropServices;
43

5-
// General Information about an assembly is controlled through the following
6-
// set of attributes. Change these attribute values to modify the information
7-
// associated with an assembly.
8-
[assembly: AssemblyTitle("SQLite.CodeFirst.Console")]
9-
[assembly: AssemblyDescription("")]
10-
[assembly: AssemblyConfiguration("")]
11-
[assembly: AssemblyCompany("")]
4+
[assembly: AssemblyTitle("SQLite.CodeFirst")]
5+
[assembly: AssemblyDescription("A console application which demonstrates how to use QLite.CodeFirst.")]
126
[assembly: AssemblyProduct("SQLite.CodeFirst")]
13-
[assembly: AssemblyCopyright("Copyright © 2015")]
14-
[assembly: AssemblyTrademark("")]
15-
[assembly: AssemblyCulture("")]
7+
[assembly: AssemblyCopyright("Copyright © Marc Sallin")]
168

179
// Setting ComVisible to false makes the types in this assembly not visible
1810
// to COM components. If you need to access a type in this assembly from
@@ -22,15 +14,6 @@
2214
// The following GUID is for the ID of the typelib if this project is exposed to COM
2315
[assembly: Guid("945f6a68-1bcd-47ff-a551-a2820b88ff8c")]
2416

25-
// Version information for an assembly consists of the following four values:
26-
//
27-
// Major Version
28-
// Minor Version
29-
// Build Number
30-
// Revision
31-
//
32-
// You can specify all the values or you can default the Build and Revision Numbers
33-
// by using the '*' as shown below:
34-
// [assembly: AssemblyVersion("1.0.*")]
3517
[assembly: AssemblyVersion("1.0.0.0")]
3618
[assembly: AssemblyFileVersion("1.0.0.0")]
19+
[assembly: AssemblyInformationalVersion("1.0.0.0")]

SQLite.CodeFirst.sln

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{01B97A
1414
.nuget\NuGet.targets = .nuget\NuGet.targets
1515
EndProjectSection
1616
EndProject
17+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{7031BD3C-AE76-43CD-91B6-B6BCD823968C}"
18+
ProjectSection(SolutionItems) = preProject
19+
release_appveyor.yml = release_appveyor.yml
20+
EndProjectSection
21+
EndProject
1722
Global
1823
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1924
Debug|Any CPU = Debug|Any CPU
Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
using System.Reflection;
2-
using System.Runtime.CompilerServices;
32
using System.Runtime.InteropServices;
43

5-
// General Information about an assembly is controlled through the following
6-
// set of attributes. Change these attribute values to modify the information
7-
// associated with an assembly.
84
[assembly: AssemblyTitle("SQLite.CodeFirst")]
9-
[assembly: AssemblyDescription("")]
10-
[assembly: AssemblyConfiguration("")]
11-
[assembly: AssemblyCompany("")]
5+
[assembly: AssemblyDescription(
6+
"Creates a SQLite Database from Code, using Entity Framework CodeFirst. " +
7+
"This Project ships several IDbInitializer which creates " +
8+
"a new SQLite Database, based on your model/code.")]
129
[assembly: AssemblyProduct("SQLite.CodeFirst")]
13-
[assembly: AssemblyCopyright("Copyright © 2015")]
14-
[assembly: AssemblyTrademark("")]
15-
[assembly: AssemblyCulture("")]
10+
[assembly: AssemblyCopyright("Copyright © Marc Sallin")]
11+
[assembly: AssemblyCompany("Marc Sallin")]
1612

1713
// Setting ComVisible to false makes the types in this assembly not visible
1814
// to COM components. If you need to access a type in this assembly from
@@ -22,15 +18,7 @@
2218
// The following GUID is for the ID of the typelib if this project is exposed to COM
2319
[assembly: Guid("46603902-448a-4c50-87ec-09cb792b740f")]
2420

25-
// Version information for an assembly consists of the following four values:
26-
//
27-
// Major Version
28-
// Minor Version
29-
// Build Number
30-
// Revision
31-
//
32-
// You can specify all the values or you can default the Build and Revision Numbers
33-
// by using the '*' as shown below:
34-
// [assembly: AssemblyVersion("1.0.*")]
21+
// Will be replaced by the build server
3522
[assembly: AssemblyVersion("1.0.0.0")]
3623
[assembly: AssemblyFileVersion("1.0.0.0")]
24+
[assembly: AssemblyInformationalVersion("1.0.0.0")]

SQLite.CodeFirst/SQLite.CodeFirst.csproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,20 @@
4646
<Reference Include="System" />
4747
<Reference Include="System.Core" />
4848
<Reference Include="System.Data" />
49-
<Reference Include="System.Data.Entity" />
5049
</ItemGroup>
5150
<ItemGroup>
5251
<Compile Include="Builder\ColumnStatementCollectionBuilder.cs" />
5352
<Compile Include="Builder\ForeignKeyStatementBuilder.cs" />
5453
<Compile Include="Builder\CreateDatabaseStatementBuilder.cs" />
5554
<Compile Include="Builder\PrimaryKeyStatementBuilder.cs" />
55+
<Compile Include="SqliteCreateDatabaseIfNotExists.cs" />
56+
<Compile Include="SqliteDropCreateDatabaseAlways.cs" />
5657
<Compile Include="Statement\ColumnConstraint\MaxLengthConstraint.cs" />
5758
<Compile Include="Statement\CreateIndexStatement.cs" />
5859
<Compile Include="Statement\PrimaryKeyStatement.cs" />
5960
<Compile Include="Properties\AssemblyInfo.cs" />
6061
<Compile Include="SqliteConnectionStringParser.cs" />
61-
<Compile Include="SqliteContextInitializer.cs" />
62+
<Compile Include="SqliteInitializerBase.cs" />
6263
<Compile Include="Builder\IStatementBuilder.cs" />
6364
<Compile Include="SqliteDatabaseCreator.cs" />
6465
<Compile Include="Statement\ColumnConstraint\ColumnConstraintCollection.cs" />
@@ -74,6 +75,7 @@
7475
</ItemGroup>
7576
<ItemGroup>
7677
<None Include="packages.config" />
78+
<None Include="SQLite.CodeFirst.csproj.nuspec" />
7779
</ItemGroup>
7880
<ItemGroup />
7981
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
3+
<metadata>
4+
<id>$id$</id>
5+
<version>$version$</version>
6+
<authors>$author$</authors>
7+
<owners>$author$</owners>
8+
<licenseUrl>https://github.com/msallin/SQLiteCodeFirst/blob/master/LICENSE</licenseUrl>
9+
<projectUrl>https://github.com/msallin/SQLiteCodeFirst</projectUrl>
10+
<requireLicenseAcceptance>false</requireLicenseAcceptance>
11+
<description>$description$</description>
12+
<summary>Creates a SQLite Database from Code, using Entity Framework CodeFirst.</summary>
13+
<releaseNotes />
14+
<copyright>Copyright (C) Marc Sallin</copyright>
15+
<tags>SQLite EntityFramework EF CodeFirst</tags>
16+
<dependencies>
17+
<dependency id="EntityFramework" version="6.1" />
18+
</dependencies>
19+
<frameworkAssemblies>
20+
<frameworkAssembly assemblyName="System" targetFramework="" />
21+
<frameworkAssembly assemblyName="System.Core" targetFramework="" />
22+
<frameworkAssembly assemblyName="System.Data" targetFramework="" />
23+
</frameworkAssemblies>
24+
</metadata>
25+
<files>
26+
<file src="bin\$configuration$\$id$.dll" target="lib\net45\SQLite.CodeFirst.dll" />
27+
</files>
28+
</package>

SQLite.CodeFirst/SqliteConnectionStringParser.cs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23

34
namespace SQLite.CodeFirst
45
{
56
internal static class SqliteConnectionStringParser
67
{
8+
private const string DataDirectoryToken = "|datadirectory|";
79
private const char KeyValuePairSeperator = ';';
810
private const char KeyValueSeperator = '=';
911
private const int KeyPosition = 0;
@@ -26,7 +28,53 @@ public static IDictionary<string, string> ParseSqliteConnectionString(string con
2628

2729
public static string GetDataSource(string connectionString)
2830
{
29-
return ParseSqliteConnectionString(connectionString)["data source"];
31+
var path = ExpandDataDirectory(ParseSqliteConnectionString(connectionString)["data source"]);
32+
return path;
33+
}
34+
35+
private static string ExpandDataDirectory(string path)
36+
{
37+
if (path == null || !path.StartsWith(DataDirectoryToken, StringComparison.OrdinalIgnoreCase))
38+
{
39+
return path;
40+
}
41+
42+
string fullPath;
43+
44+
// find the replacement path
45+
object rootFolderObject = AppDomain.CurrentDomain.GetData("DataDirectory");
46+
string rootFolderPath = (rootFolderObject as string);
47+
if (rootFolderObject != null && rootFolderPath == null)
48+
{
49+
throw new InvalidOperationException("The value stored in the AppDomains 'DataDirectory' variable has to be a string!");
50+
}
51+
if (string.IsNullOrEmpty(rootFolderPath))
52+
{
53+
rootFolderPath = AppDomain.CurrentDomain.BaseDirectory;
54+
}
55+
56+
// We don't know if rootFolderpath ends with '\', and we don't know if the given name starts with onw
57+
int fileNamePosition = DataDirectoryToken.Length; // filename starts right after the '|datadirectory|' keyword
58+
bool rootFolderEndsWith = (0 < rootFolderPath.Length) && rootFolderPath[rootFolderPath.Length - 1] == '\\';
59+
bool fileNameStartsWith = (fileNamePosition < path.Length) && path[fileNamePosition] == '\\';
60+
61+
// replace |datadirectory| with root folder path
62+
if (!rootFolderEndsWith && !fileNameStartsWith)
63+
{
64+
// need to insert '\'
65+
fullPath = rootFolderPath + '\\' + path.Substring(fileNamePosition);
66+
}
67+
else if (rootFolderEndsWith && fileNameStartsWith)
68+
{
69+
// need to strip one out
70+
fullPath = rootFolderPath + path.Substring(fileNamePosition + 1);
71+
}
72+
else
73+
{
74+
// simply concatenate the strings
75+
fullPath = rootFolderPath + path.Substring(fileNamePosition);
76+
}
77+
return fullPath;
3078
}
3179
}
3280
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Data.Entity;
2+
using System.IO;
3+
4+
namespace SQLite.CodeFirst
5+
{
6+
public class SqliteCreateDatabaseIfNotExists<TContext> : SqliteInitializerBase<TContext>
7+
where TContext : DbContext
8+
{
9+
public SqliteCreateDatabaseIfNotExists(string connectionString, DbModelBuilder modelBuilder)
10+
: base(connectionString, modelBuilder) { }
11+
12+
public override void InitializeDatabase(TContext context)
13+
{
14+
bool dbExists = File.Exists(DatabaseFilePath);
15+
if (dbExists)
16+
{
17+
return;
18+
}
19+
20+
base.InitializeDatabase(context);
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)