Skip to content

Commit 0b1e823

Browse files
committed
Merge pull request #39 from msallin/Issue_21
Issue 21
2 parents 8873148 + b35c2f5 commit 0b1e823

File tree

11 files changed

+158
-22
lines changed

11 files changed

+158
-22
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace SQLite.CodeFirst.Console.Entity
2+
{
3+
public class Coach : Person
4+
{
5+
public virtual Team Team { get; set; }
6+
}
7+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace SQLite.CodeFirst.Console.Entity
4+
{
5+
public abstract class Person : IEntity
6+
{
7+
public int Id { get; set; }
8+
9+
[MaxLength(50)]
10+
public string FirstName { get; set; }
11+
12+
[MaxLength(50)]
13+
public string LastName { get; set; }
14+
15+
[MaxLength(100)]
16+
public string Street { get; set; }
17+
18+
[Required]
19+
public string City { get; set; }
20+
}
21+
}

SQLite.CodeFirst.Console/Entity/Player.cs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,12 @@
1-
using System.ComponentModel.DataAnnotations;
2-
using System.ComponentModel.DataAnnotations.Schema;
1+
using System.ComponentModel.DataAnnotations.Schema;
32

43
namespace SQLite.CodeFirst.Console.Entity
54
{
65
[Table("TeamPlayer")]
7-
public class Player : IEntity
6+
public class Player : Person
87
{
9-
public int Id { get; set; }
10-
11-
[Index] // Automatically named 'IX_TeamPlayer_FirstName'
12-
[MaxLength(50)]
13-
public string FirstName { get; set; }
14-
15-
[Index("IX_TeamPlayer_LN")] // Test for named index
16-
[MaxLength(50)]
17-
public string LastName { get; set; }
18-
19-
[MaxLength(100)]
20-
public string Street { get; set; }
21-
22-
[Required]
23-
public string City { get; set; }
8+
[Index] // Automatically named 'IX_TeamPlayer_Number'
9+
public int Number { get; set; }
2410

2511
public virtual Team Team { get; set; }
2612
}

SQLite.CodeFirst.Console/Entity/Stadion.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class Stadion
88
[Key]
99
[Column(Order = 1)]
1010
[Index("IX_Stadion_Main", Order = 2)] // Test for combined, named index
11-
public string Name { get; set; }
11+
public string Name { get; set; }
1212

1313
[Key]
1414
[Column(Order = 2)]

SQLite.CodeFirst.Console/Entity/Team.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
using System.Collections.Generic;
22
using System.ComponentModel.DataAnnotations;
3+
using System.ComponentModel.DataAnnotations.Schema;
34

45
namespace SQLite.CodeFirst.Console.Entity
56
{
67
public class Team : IEntity
78
{
89
public int Id { get; set; }
910

11+
[Index("IX_Team_TeamsName")] // Test for named index.
1012
[Required]
1113
public string Name { get; set; }
1214

15+
public virtual Coach Coach { get; set; }
16+
1317
public virtual ICollection<Player> Players { get; set; }
1418

1519
public virtual Stadion Stadion { get; set; }

SQLite.CodeFirst.Console/FootballDbContext.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,26 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder)
2929
private static void ConfigureTeamEntity(DbModelBuilder modelBuilder)
3030
{
3131
modelBuilder.Entity<Team>();
32+
33+
modelBuilder.Entity<Team>()
34+
.HasOptional(p => p.Coach)
35+
.WithMany()
36+
.WillCascadeOnDelete(false);
3237
}
3338

3439
private static void ConfigureStadionEntity(DbModelBuilder modelBuilder)
3540
{
3641
modelBuilder.Entity<Stadion>();
3742
}
3843

44+
private static void ConfigureCoachEntity(DbModelBuilder modelBuilder)
45+
{
46+
modelBuilder.Entity<Coach>()
47+
.HasRequired(p => p.Team)
48+
.WithMany()
49+
.WillCascadeOnDelete(true);
50+
}
51+
3952
private static void ConfigurePlayerEntity(DbModelBuilder modelBuilder)
4053
{
4154
modelBuilder.Entity<Player>()
@@ -48,28 +61,38 @@ private static void ConfigurePlayerEntity(DbModelBuilder modelBuilder)
4861
public class FootballDbInitializer : SqliteDropCreateDatabaseAlways<FootballDbContext>
4962
{
5063
public FootballDbInitializer(DbModelBuilder modelBuilder)
51-
: base(modelBuilder) { }
64+
: base(modelBuilder)
65+
{ }
5266

5367
protected override void Seed(FootballDbContext context)
5468
{
5569
context.Set<Team>().Add(new Team
5670
{
5771
Name = "YB",
72+
Coach = new Coach
73+
{
74+
City = "Zürich",
75+
FirstName = "Masssaman",
76+
LastName = "Nachn",
77+
Street = "Testingstreet 844"
78+
},
5879
Players = new List<Player>
5980
{
6081
new Player
6182
{
6283
City = "Bern",
6384
FirstName = "Marco",
6485
LastName = "Bürki",
65-
Street = "Wunderstrasse 43"
86+
Street = "Wunderstrasse 43",
87+
Number = 12
6688
},
6789
new Player
6890
{
6991
City = "Berlin",
7092
FirstName = "Alain",
7193
LastName = "Rochat",
72-
Street = "Wonderstreet 13"
94+
Street = "Wonderstreet 13",
95+
Number = 14
7396
}
7497
},
7598
Stadion = new Stadion

SQLite.CodeFirst.Console/Program.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,19 @@ private static void DisplaySeededData(FootballDbContext context)
4141
System.Console.WriteLine("\t\t City: {0}", team.Stadion.City);
4242
System.Console.WriteLine();
4343

44+
System.Console.WriteLine("\t\t Coach:");
45+
System.Console.WriteLine("\t\t Id: {0}", team.Coach.Id);
46+
System.Console.WriteLine("\t\t FirstName: {0}", team.Coach.FirstName);
47+
System.Console.WriteLine("\t\t LastName: {0}", team.Coach.LastName);
48+
System.Console.WriteLine("\t\t Street: {0}", team.Coach.Street);
49+
System.Console.WriteLine("\t\t City: {0}", team.Coach.City);
50+
System.Console.WriteLine();
51+
4452
foreach (var player in team.Players)
4553
{
4654
System.Console.WriteLine("\t\t Player:");
4755
System.Console.WriteLine("\t\t Id: {0}", player.Id);
56+
System.Console.WriteLine("\t\t Number: {0}", player.Number);
4857
System.Console.WriteLine("\t\t FirstName: {0}", player.FirstName);
4958
System.Console.WriteLine("\t\t LastName: {0}", player.LastName);
5059
System.Console.WriteLine("\t\t Street: {0}", player.Street);

SQLite.CodeFirst.Console/SQLite.CodeFirst.Console.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@
6262
<Reference Include="System.Xml" />
6363
</ItemGroup>
6464
<ItemGroup>
65+
<Compile Include="Entity\Coach.cs" />
6566
<Compile Include="Entity\IEntity.cs" />
67+
<Compile Include="Entity\Person.cs" />
6668
<Compile Include="Entity\Player.cs" />
6769
<Compile Include="Entity\Stadion.cs" />
6870
<Compile Include="Entity\Team.cs" />
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using SQLite.CodeFirst.Extensions;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.ComponentModel.DataAnnotations.Schema;
5+
using System.Data.Entity.Core.Metadata.Edm;
6+
using System.Data.Entity.Infrastructure;
7+
using System.Data.Entity.Infrastructure.Annotations;
8+
using System.Data.Entity.ModelConfiguration.Conventions;
9+
using System.Linq;
10+
11+
namespace SQLite.CodeFirst.Convention
12+
{
13+
/// <summary>
14+
/// Renames the indicies, generated by the
15+
/// <see cref="ForeignKeyIndexConvention"/>-Convention, to match the scheme: "IX_{TableName}_{PropertyName}".
16+
/// This is necessary because in SQLite an index-name must be unique.
17+
/// Must be added right after the <see cref="ForeignKeyIndexConvention"/>-Convention.
18+
/// </summary>
19+
public class SqliteForeignKeyIndexConvention : IStoreModelConvention<AssociationType>
20+
{
21+
private const string IndexAnnotationName = "http://schemas.microsoft.com/ado/2013/11/edm/customannotation:Index";
22+
23+
public virtual void Apply(AssociationType item, DbModel model)
24+
{
25+
if (item == null)
26+
{
27+
throw new ArgumentNullException("item");
28+
}
29+
if (model == null)
30+
{
31+
throw new ArgumentNullException("model");
32+
}
33+
if (item.Constraint == null)
34+
{
35+
return;
36+
}
37+
38+
for (int i = 0; i < item.Constraint.ToProperties.Count; i++)
39+
{
40+
EdmProperty edmProperty = item.Constraint.ToProperties[i];
41+
var annotation = GetAnnotation(edmProperty.MetadataProperties, IndexAnnotationName);
42+
if (annotation != null)
43+
{
44+
// The original attribute is removed. The none-ForeignKeyIndicies will be remained and readded without any modification
45+
// and the foreignKeyIncidies will be readded with the correct name.
46+
edmProperty.RemoveAnnotation(IndexAnnotationName);
47+
48+
// The schema for the automatically generated index name is "IX_{TableName}_{PropertyName}"
49+
var noneForeignKeyIndicies = annotation.Indexes.Where(index => index.Name != "IX_" + edmProperty.Name);
50+
IndexAnnotation newIndexAnnotation = new IndexAnnotation(noneForeignKeyIndicies);
51+
52+
// The schema for a FK index, which is generated by the Entity Framework, is "IX_{PropertyName}"
53+
var foreignKeyIndicies = annotation.Indexes.Where(index => index.Name == "IX_" + edmProperty.Name);
54+
foreach (var foreignKeyIndex in foreignKeyIndicies)
55+
{
56+
var indexAttribute = new IndexAttribute(string.Format("IX_{0}_{1}", item.Constraint.ToRole.GetEntityType().GetTableName(), edmProperty.Name));
57+
IndexAnnotation foreignKeyIndexAnnotation = new IndexAnnotation(indexAttribute);
58+
newIndexAnnotation = (IndexAnnotation)newIndexAnnotation.MergeWith(foreignKeyIndexAnnotation);
59+
}
60+
61+
edmProperty.AddAnnotation(IndexAnnotationName, newIndexAnnotation);
62+
}
63+
}
64+
}
65+
66+
private static IndexAnnotation GetAnnotation(IEnumerable<MetadataProperty> metadataProperties, string name)
67+
{
68+
foreach (MetadataProperty metadataProperty in metadataProperties)
69+
{
70+
if (metadataProperty.Name.Equals(name, StringComparison.Ordinal))
71+
{
72+
return (IndexAnnotation)metadataProperty.Value;
73+
}
74+
}
75+
return null;
76+
}
77+
}
78+
}

SQLite.CodeFirst/SQLite.CodeFirst.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
<Compile Include="Builder\ForeignKeyStatementBuilder.cs" />
7878
<Compile Include="Builder\CreateDatabaseStatementBuilder.cs" />
7979
<Compile Include="Builder\PrimaryKeyStatementBuilder.cs" />
80+
<Compile Include="Convention\SqliteForeignKeyIndexConvention.cs" />
8081
<Compile Include="Extensions\EntityTypeExtension.cs" />
8182
<Compile Include="SqliteCreateDatabaseIfNotExists.cs" />
8283
<Compile Include="SqliteDropCreateDatabaseAlways.cs" />

0 commit comments

Comments
 (0)