AGGIORNAMENTO: Ultimamente ho ricevuto alcuni voti a riguardo, quindi ho pensato di far sapere alla gente che i consigli che fornisco di seguito non sono i migliori. Da quando inizialmente ho iniziato a fare confusione con Entity Framework su vecchi database senza chiave, sono arrivato a capire che la cosa migliore che puoi fare DA FAR è farlo prima in codice inverso. Ci sono alcuni buoni articoli là fuori su come farlo. Seguili e, quando vuoi aggiungere una chiave, usa le annotazioni dei dati per "falsificare" la chiave.
Ad esempio, supponiamo che conosca la mia tabella Orders
, sebbene non abbia una chiave primaria, è assicurato che abbia sempre un solo numero d'ordine per cliente. Dato che quelle sono le prime due colonne sul tavolo, imposterò il codice delle prime classi in questo modo:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
In questo modo, fondamentalmente sei falso EF nel credere che ci sia una chiave cluster composta da OrderNumber e Customer. Questo ti permetterà di fare inserimenti, aggiornamenti, ecc. Sulla tua tabella senza chiave.
Se non si ha troppa familiarità con il primo codice inverso, andare prima a trovare un buon tutorial su Entity Framework Code. Quindi vai a trovarne uno su Reverse Code First (che sta eseguendo Code First con un database esistente). Quindi torna qui e guarda di nuovo i miei consigli chiave. :)
Risposta originale :
Primo: come altri hanno già detto, l'opzione migliore è aggiungere una chiave primaria alla tabella. Punto. Se puoi farlo, non leggere oltre.
Ma se non puoi, o semplicemente odi te stesso, c'è un modo per farlo senza la chiave primaria.
Nel mio caso, stavo lavorando con un sistema legacy (originariamente file flat su un AS400 portati su Access e poi portati su T-SQL). Quindi ho dovuto trovare un modo. Questa è la mia soluzione Quanto segue ha funzionato per me usando Entity Framework 6.0 (l'ultimo su NuGet al momento della stesura).
Fare clic con il tasto destro del mouse sul file .edmx in Esplora soluzioni. Scegli "Apri con ...", quindi seleziona "Editor XML (testo)". Modificheremo manualmente il codice generato automaticamente qui.
Cerca una linea come questa:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">
Rimuovi store:Name="table_name"
dalla fine.
Cambia store:Schema="whatever"
inSchema="whatever"
Guarda sotto quella linea e trova il <DefiningQuery>
tag. Avrà una grande dichiarazione selezionata in esso. Rimuovi il tag e il suo contenuto.
Ora la tua linea dovrebbe assomigliare a questa:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
Abbiamo qualcos'altro da cambiare. Passa attraverso il tuo file e trova questo:
<EntityType Name="table_name">
Nelle vicinanze probabilmente vedrai del testo commentato che ti avverte che non è stata identificata una chiave primaria, quindi la chiave è stata dedotta e la definizione è una tabella / vista di sola lettura. Puoi lasciarlo o cancellarlo. L'ho cancellato.
Di seguito è riportato il <Key>
tag. Questo è ciò che Entity Framework utilizzerà per eseguire l'inserimento / aggiornamento / eliminazione. Quindi assicurati di fare questo diritto. La proprietà (o proprietà) in quel tag deve indicare una riga identificabile in modo univoco. Ad esempio, supponiamo che conosca la mia tabella orders
, sebbene non abbia una chiave primaria, è assicurato che abbia sempre un solo numero d'ordine per cliente.
Quindi il mio assomiglia a:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
Seriamente, non fare questo male. Diciamo che anche se non dovrebbero mai esserci duplicati, in qualche modo due file entrano nel mio sistema con lo stesso numero d'ordine e nome cliente. Whooops! Questo è quello che ottengo per non usare una chiave! Quindi uso Entity Framework per eliminarne uno. Poiché so che il duplicato è l'unico ordine effettuato oggi, faccio questo:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
Indovina un po? Ho appena eliminato sia il duplicato che l'originale! Questo perché ho detto a Entity Framework che order_number / cutomer_name era la mia chiave primaria. Quindi quando gli ho detto di rimuovere duplicateOrder, quello che ha fatto in background è stato qualcosa del tipo:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
E con quell'avvertimento ... ora dovresti essere bravo ad andare!