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+ }
0 commit comments