UPDATE: Ich habe in letzter Zeit ein paar positive Stimmen dazu bekommen, also dachte ich mir, ich würde die Leute wissen lassen, dass der Rat, den ich unten gebe, nicht der beste ist. Seit ich anfänglich damit angefangen habe, Entity Framework für alte schlüssellose Datenbanken zu verwenden, habe ich festgestellt, dass das Beste, was Sie bei weitem tun können, darin besteht, es zuerst mit dem umgekehrten Code zuerst auszuführen. Es gibt ein paar gute Artikel darüber, wie das geht. Folgen Sie ihnen einfach, und wenn Sie einen Schlüssel hinzufügen möchten, verwenden Sie Datenanmerkungen, um den Schlüssel zu "fälschen".
Nehmen wir zum Beispiel an, ich weiß, dass meine Tabelle Orders
, obwohl sie keinen Primärschlüssel hat, immer nur eine Bestellnummer pro Kunde hat. Da dies die ersten beiden Spalten in der Tabelle sind, habe ich die Code-First-Klassen so eingerichtet, dass sie folgendermaßen aussehen:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
Auf diese Weise täuschen Sie EF im Grunde vor, dass es einen Clustered Key gibt, der aus OrderNumber und Customer besteht. Auf diese Weise können Sie Einfügungen, Aktualisierungen usw. für Ihren schlüssellosen Tisch vornehmen.
Wenn Sie mit Reverse Code First nicht allzu vertraut sind, finden Sie ein gutes Tutorial zu Entity Framework Code First. Suchen Sie dann einen unter Reverse Code First (der Code First mit einer vorhandenen Datenbank ausführt). Dann komm einfach zurück und schau dir noch einmal meine wichtigsten Ratschläge an. :) :)
Ursprüngliche Antwort :
Erstens: Wie andere bereits gesagt haben, besteht die beste Option darin, der Tabelle einen Primärschlüssel hinzuzufügen. Punkt. Wenn Sie dies tun können, lesen Sie nicht weiter.
Aber wenn Sie nicht können oder sich einfach nur hassen, gibt es eine Möglichkeit, dies ohne den Primärschlüssel zu tun.
In meinem Fall arbeitete ich mit einem Legacy-System (ursprünglich flache Dateien auf einem AS400, der auf Access portiert und dann auf T-SQL portiert wurde). Also musste ich einen Weg finden. Das ist meine Lösung. Das Folgende funktionierte für mich mit Entity Framework 6.0 (das neueste auf NuGet zum Zeitpunkt dieses Schreibens).
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf Ihre EDMX-Datei. 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">
store:Name="table_name"
Vom Ende entfernen .
Wechseln Sie store:Schema="whatever"
zuSchema="whatever"
Schauen Sie unter diese Zeile und finden Sie das <DefiningQuery>
Tag. Es wird eine große alte select-Anweisung enthalten. Entfernen Sie das Tag und seinen Inhalt.
Jetzt sollte Ihre Linie ungefähr so aussehen:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
Wir müssen noch etwas ändern. Gehen Sie Ihre Datei durch und finden Sie Folgendes:
<EntityType Name="table_name">
In der Nähe wird wahrscheinlich ein kommentierter Text angezeigt, der Sie darauf hinweist, dass kein Primärschlüssel identifiziert wurde. Daher wurde der Schlüssel abgeleitet und die Definition ist eine schreibgeschützte Tabelle / Ansicht. Sie können es verlassen oder löschen. Ich habe es gelöscht.
Unten ist das <Key>
Tag. Dies wird Entity Framework zum Einfügen / Aktualisieren / Löschen verwenden. Stellen Sie also sicher, dass Sie dies richtig machen. Die Eigenschaft (oder Eigenschaften) in diesem Tag müssen eine eindeutig identifizierbare Zeile angeben. Nehmen wir zum Beispiel an, ich weiß, dass meine Tabelle orders
, obwohl sie keinen Primärschlüssel hat, immer nur eine Bestellnummer pro Kunde hat.
Meins sieht also so aus:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
Im Ernst, mach das nicht falsch. Nehmen wir an, obwohl es niemals Duplikate geben sollte, gelangen irgendwie zwei Zeilen mit derselben Bestellnummer und demselben Kundennamen in mein System. Whooops! Das bekomme ich, wenn ich keinen Schlüssel benutze! Also benutze ich Entity Framework, um eines zu löschen. Da ich weiß, dass das Duplikat die einzige Bestellung ist, die heute aufgegeben wird, mache ich Folgendes:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
Erraten 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 ihm sagte, er solle duplicateOrder entfernen, war das im Hintergrund ungefähr so:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
Und mit dieser Warnung ... sollten Sie jetzt bereit sein zu gehen!