Abbiamo iniziato a utilizzare EF6 come parte della riscrittura della nostra suite di applicazioni. Ci sono molte tabelle perfettamente ragionevoli nella suite esistente e le stiamo riutilizzando usando un approccio basato sul database. Il mio problema è che EF6 sembra imporre ciò che penso siano le convenzioni in codice sul mio primo modello di database.
Considera questo esempio minimo con due tabelle definite in modo appropriato e popolate correttamente con poche righe:
CREATE TABLE [dbo].[Table1] (
[Id] INT NOT NULL PRIMARY KEY,
[Table2Reference] INT NOT NULL REFERENCES [dbo].[Table2](Id) )
CREATE TABLE [dbo].[Table2] (
[Id] INT NOT NULL PRIMARY KEY,
[SomeColumn] NVARCHAR(25) )
Dopo aver eseguito Update Model From Database otteniamo questo modello:
(Oops, non abbastanza reputazione per pubblicare immagini. È ciò che si potrebbe immaginare).
Fin qui tutto bene, ma quando scrivi codice per accedere all'entità Table1, così ...
var q = _context.Table1.ToList();
foreach (var item in q)
Debug.WriteLine("{0}", item.Table2Reference);
... compila bene ma getterà la riga ToList (). Questo perché l'SQL generato contiene una richiesta per una colonna che non esiste nemmeno:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Table2Reference] AS [Table2Reference],
[Extent1].[Table2_Id] AS [Table2_Id] <-- this one doesn't exist
FROM [dbo].[Table1] AS [Extent1]
Ho capito che questo ha qualcosa a che fare con una convenzione di denominazione in codice per le chiavi esterne. So che posso rinominare la colonna Id di Table2 a Table2Id e rinominare Table2Reference a Table2Id e funzionerà. Tuttavia, questo dovrebbe essere il database prima. C'è un modo per dire a EF di togliersi di mezzo e andare semplicemente con ciò che è effettivamente nel database predefinito? Ho scoperto presto che dovevo disattivare il nome pluralizing convention, ma non riesco a identificare una convenzione per spegnere il problema. Ho provato a rimuovere questi:
modelBuilder.Conventions.Remove<PrimaryKeyNameForeignKeyDiscoveryConvention>();
modelBuilder.Conventions.Remove<TypeNameForeignKeyDiscoveryConvention>();
modelBuilder.Conventions.Remove<NavigationPropertyNameForeignKeyDiscoveryConvention>();
Ad ogni modo, sono perplesso. C'è una soluzione facile che non comporta la modifica del database esistente?
Grazie per aver letto.
Si scopre che c'è un pezzo molto importante per un approccio al database prima di avere un file EDMX. Cioè, la stringa di connessione deve contenere la seguente sezione:
metadata = res: // /IPE.csdl|res:// /IPE.ssdl|res://*/IPE.msl; (sostituendo IPE con il nome base del tuo EDMX)
In caso contrario, EF non sarà in grado di individuare le informazioni EDMX nell'assieme e le convenzioni code-first possono entrare in gioco. Principalmente le cose funzionano, finché non lo fanno.