UPDATE: Ich habe in letzter Zeit ein paar positive Bewertungen zu diesem Thema erhalten, also dachte ich mir, ich lasse die Leute wissen, dass der Rat, den ich unten gebe, nicht der beste ist. Seit ich anfing, mit Entity Framework auf alten schlüssellosen Datenbanken herumzupfuschen, habe ich erkannt, dass das Beste, was Sie tun können, bei weitem ist, es durch Reverse-Code-First zu tun. Es gibt ein paar gute Artikel darüber, wie man das macht. Folgen Sie ihnen einfach, und wenn Sie dann einen Schlüssel hinzufügen möchten, verwenden Sie Datenanmerkungen, um den Schlüssel "vorzutäuschen".
Nehmen wir zum Beispiel an, ich kenne meine Tabelle Orders
hat zwar keinen Primärschlüssel, aber es ist sichergestellt, dass es immer nur eine Bestellnummer pro Kunde gibt. Da dies die ersten beiden Spalten der Tabelle sind, würde ich die ersten Klassen des Codes so einrichten, dass sie wie folgt aussehen:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
Auf diese Weise gaukeln Sie EF vor, dass es einen Cluster-Schlüssel gibt, der aus OrderNumber und Customer besteht. Dies ermöglicht Ihnen, Einfügungen, Aktualisierungen usw. in Ihrer schlüssellosen Tabelle vorzunehmen.
Wenn Sie nicht allzu vertraut mit Reverse Code First sind, suchen Sie ein gutes Tutorial über Entity Framework Code First. Dann suchen Sie nach einem Tutorial über Reverse Code First (was bedeutet, Code First mit einer bestehenden Datenbank durchzuführen). Dann kommen Sie einfach hierher zurück und sehen sich meine wichtigsten Ratschläge noch einmal an :)
Original-Antwort :
Erstens: Wie bereits von anderen gesagt, ist es am besten, der Tabelle einen Primärschlüssel hinzuzufügen. Punktum. Wenn Sie dies tun können, lesen Sie nicht weiter.
Aber wenn Sie das nicht können oder sich selbst hassen, gibt es einen Weg, es ohne den Primärschlüssel zu tun.
In meinem Fall habe ich mit einem Altsystem gearbeitet (ursprünglich flache Dateien auf einer AS400, die nach Access und dann nach T-SQL portiert wurden). Also musste ich einen Weg finden. Dies ist meine Lösung. Das Folgende funktionierte für mich mit Entity Framework 6.0 (die neueste Version von NuGet zum Zeitpunkt dieses Schreibens).
-
Klicken Sie mit der rechten Maustaste auf Ihre .edmx-Datei im Projektmappen-Explorer. Wählen Sie "Öffnen mit..." und dann "XML (Text) Editor". Wir werden den automatisch generierten Code hier von Hand bearbeiten.
-
Suchen Sie nach einer Zeile wie dieser:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">
-
entfernen store:Name="table_name"
vom Ende her.
-
Ändern Sie store:Schema="whatever"
a Schema="whatever"
-
Schauen Sie unter diese Zeile und suchen Sie die <DefiningQuery>
Tag. Darin befindet sich eine große Select-Anweisung. Entfernen Sie das Tag und seinen Inhalt.
-
Jetzt sollte Ihre Zeile etwa so aussehen:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
-
Wir haben noch etwas anderes zu ändern. Gehen Sie durch Ihre Datei und finden Sie dies:
<EntityType Name="table_name">
-
In der Nähe werden Sie wahrscheinlich einen kommentierten Text sehen, der Sie warnt, dass kein Primärschlüssel identifiziert wurde, so dass der Schlüssel abgeleitet wurde und die Definition eine schreibgeschützte Tabelle/Ansicht ist. Sie können es dabei belassen oder es löschen. Ich habe ihn gelöscht.
-
Nachstehend finden Sie die <Key>
Tag. Dies ist das, was Entity Framework verwenden wird, um Einfügungen/Aktualisierungen/Löschungen durchzuführen. STELLEN SIE ALSO SICHER, DASS SIE DIES RICHTIG MACHEN. Die Eigenschaft (oder Eigenschaften) in diesem Tag müssen eine eindeutig identifizierbare Zeile angeben. Sagen wir zum Beispiel, ich kenne meine Tabelle orders
hat zwar keinen Primärschlüssel, aber es ist sichergestellt, dass es immer nur eine Bestellnummer pro Kunde gibt.
So sieht meine aus:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
Im Ernst, machen Sie das nicht falsch. Angenommen, obwohl es keine Duplikate geben sollte, gelangen irgendwie zwei Zeilen mit derselben Bestellnummer und demselben Kundennamen in mein System. Huch! Das habe ich davon, wenn ich keinen Schlüssel verwende! Also verwende ich Entity Framework, um eine Zeile zu löschen. Da ich weiß, dass das Duplikat die einzige Bestellung ist, die heute eingegeben wurde, mache ich Folgendes:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
Wissen Sie was? Ich habe gerade sowohl das Duplikat als auch das Original gelöscht! Das liegt daran, dass ich Entity Framework mitgeteilt habe, dass order_number/cutomer_name mein Primärschlüssel ist. Als ich also sagte, dass duplicateOrder entfernt werden soll, tat es im Hintergrund so etwas wie:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
Und mit dieser Warnung... sollten Sie nun bereit sein, loszulegen!