Ho alcuni modelli EF Core che sono stati costruiti utilizzando dotnet ef dbContext scaffold
per produrre modelli utilizzando un approccio al primo database. Il mio problema è che il database usa una chiave primaria intera, usata per collegare le tabelle insieme ma ha un indice basato su stringhe che dovrebbe essere usato come indice sensato per la ricerca nella tabella.
Tuttavia: quando tento di utilizzare FindAsync("abc000")
viene visualizzato un errore completamente previsto The key value at position 0 of the call to 'DbSet<Entity>.Find' was of type 'string', which does not match the property type of 'long'.
Quindi, due domande:
Sembrano così:
class Entity
{
long Id;
string Key;
};
E in OnModelCreating:
modelBuilder.Entity<Entity>(entity =>
{
entity.ToTable("tb_entity", "main");
entity.HasIndex(e => e.Key)
.HasName("uq_entity_key")
.IsUnique();
entity.Property(e => e.Id).HasColumnName("_id");
entity.Property(e => e.Key)
.HasColumnName("key")
.HasMaxLength(255);
}
L'SQL che ha creato le tabelle assomiglia a:
CREATE TABLE [tb_entity]
(
_id BIGINT PRIMARY KEY IDENTITY(1,1),
key NVARCHAR(255) CONSTRAINT uq_entity_key UNIQUE NOT NULL,
);
- In che modo EF ha capito qual era la chiave primaria?
Se non specificato esplicitamente tramite l'attributo [Key]
o l'API fluente di HasKey
, è per convenzione :
Per convenzione, una proprietà denominata
Id
o<type name>Id
verrà configurata come chiave di un'entità.
Puoi vedere quell'informazione esaminando
var pk = context.Model.FindEntityType(typeof(Entity)).FindPrimaryKey();
- C'è un modo in cui posso ridigitare questo in modo da poter usare "Trova" per cercare entità per nome, ma mantenere le chiavi primarie autoincremento?
Puoi mentire EF Core usando le annotazioni di dati / API fluente che il PK Entity
è Name
, ma io non lo consiglio perché ciò porterà a presupposti sbagliati per le relazioni FK, e in generale è negativo.
Invece, semplicemente non usare i metodi Find
/ FindAsync
che sono dedicati ai PK. First
, FirstOrDefault
, Single
e SingleOrDefault
(e le loro controparti Async
) consentono la ricerca in base a qualsiasi criterio, ad esempio invece di FindAsync("abc000")
si utilizzerà FirstOrDefaultAsync(e => e.Name == "abc000")
.
L'unica differenza è che Find
i metodi prima ricerca nella cache locale, che non ha molto beneficio nella maggior parte degli scenari di utilizzo. Dall'altro lato, Find
metodi non supportano eager loading, mentre la successiva fanno. Le versioni successive vengono eseguite rispetto al database e poiché esiste un indice univoco su quella colonna, dovrebbero essere sufficientemente performanti.
- Sono stupido per aver preferito le chiavi integer di incremento automatico come i campi in cui unire le tabelle?
Questo è un design db piuttosto standard e di solito è preferibile rispetto ai PK naturali, non vedo alcun problema.