2016-07-29 5 views
4

Innerhalb SQL Ich habe Tabelle, die Primärschlüssel als Binär (8) haben. Als ich diese Tabelle auf meinem Modell hinzufügen Update Model from Database verwendet, kann ich sehen, dass diese Spalte hat Typ = BinaryEntityFramework Datenbank zuerst - Typ Zuordnung - Zuordnung binary (8) von SQL zu int in C#

enter image description here

und in C# ich diese Spalte als byte[] bekommen.

Kann ich diese Spalte auf int abbilden?

Ich weiß, dass ich eine Ansicht mit CAST in SQL erstellen:

SELECT 
    Client_Id, 
    CAST(Client_Id AS INT) AS NewClient_Id, 
    * /*other columns*/ 
FROM 
    dbo.Clients 

aber das ist keine Lösung, weil ich in der Lage sein muss, schreiben, nicht nur aus dieser Tabelle lesen. Ich weiß, dass ich gespeicherte Prozeduren für Einfügungen erstellen kann, aber das möchte ich vermeiden.

Ich bin usinf EntityFramewor 6.1.3.

+0

Willst du auch versuchen, ein Quart in einen Pint-Topf zu passen? 'binary (8)' enthält 8 Bytes. Ein 'int' in C# enthält 4 Bytes. Siehst du das Problem hier? –

+0

@Damien_The_Unbeliever Sorry, wenn ich etwas falsch geschrieben habe, aber ich versuche, das funktioniert zu bekommen. Ich dachte, wenn ich 'CAST' in SQL machen kann, dann kann EF vielleicht für mich das tun. Ich kann dieses 'byte []' im Code selbst in int umwandeln, aber ich dachte, dass EF dies eingebaut hat, ich weiß einfach nicht, wie ich das einschalte oder es konfiguriere. – Misiu

+0

Sie können in eine Ansicht schreiben. Sie müssen jedoch Trigger für Ihre Ansicht bereitstellen, damit der Wert zurück konvertiert werden kann. Auch binary 8 ist eine lange IIRC – Mark

Antwort

0

weiß ich, warum Sie entweder kleben nicht an int oder Byte in beide Datenbankstruktur und C# -Code der Seite

0

Nach meiner Erfahrung des Mapping-Prozess ist ganz einfach, vor allem zu verwirren, wenn eine vorhandene Karte zu aktualisieren. Aus diesem Grund würde ich Sie

long CurrentClientId = BitConverter.ToInt64(Rec.ClientId) 

auf Lese- und

Rec.ClientId = BitConverter.GetBytes(CurrentClientId) 

auf Schreib verwenden empfehlen. Möglicherweise haben Sie bereits einen Wrapper, um Datensätze zu erfassen, wenn sie in eine interne Struktur eingelesen werden, dies wäre nur ein weiterer Schritt.

Beachten Sie, dass dies nicht auf eine Byte-Reihenfolge achtet, die Sie vielleicht im Byte-Array haben, aber zumindest wird der Prozess korrekt durchlaufen.

0

Sie können die Konvertierung intern im Modell behandeln, wie folgt:

[NotMapped] 
    public long ClientId 
    { 
     get { return BitConverter.ToInt64(this.ClientIdBytes, 0); } 
     set { this.ClientIdBytes = BitConverter.GetBytes(value); } 
    } 

    [Column("ClientId")] 
    public byte[] ClientIdBytes { get; set; } 

Der Anrufer mit ClientId als lange funktioniert, aber diese Eigenschaft ist nicht auf die Datenbank abgebildet. Getter und Setter konvertieren den Wert einfach in eine zweite Eigenschaft, die im Spaltennamen der ClientId-Datenbank beibehalten wird.

+0

Wird dies mit dem ersten Ansatz der Datenbank funktionieren? – Misiu

+0

Es ist die einzige Möglichkeit, aber Sie können LINQ nicht in Entitätsabfragen schreiben, die das ClientId-Feld verwenden (d. H. Context.MyTable.Where (e => e.ClientId == 1)). Sie müssen die ganze Tabelle lesen, bevor Sie die Bedingung anwenden (zB context.MyTable.ToList(). Wo (e => e.ClientId == 1)) – bubi

+0

Vielen Dank für Ihren Vorschlag, aber ich möchte vermeiden, das ganze zu laden Tabelle in den Speicher – Misiu

2

Sie haben 3 verschiedene Lösungen

x Gespeicherte Prozeduren, aber Sie wollen sie nicht.

x Fügen Sie Ihrer Klasse eine nicht zugeordnete Eigenschaft hinzu. Das größte Problem bei dieser Lösung besteht darin, dass Sie keine Abfragen mit der nicht zugeordneten Eigenschaft ausführen können. Sie müssen alle Daten auf dem Client lesen und dann die Bedingung auf die nicht zugeordnete Eigenschaft auf dem Client anwenden (also ist Ihre App nicht skalierbar).

[NotMapped] 
public long LongClientId 
{ 
    get { return BitConverter.ToInt64(this.ClientId, 0); } 
    set { this.ClientId = BitConverter.GetBytes(value); } 
} 

Diese Abfrage wird

nicht funktionieren
context.MyDbSet.Where(m => m.LongClientId == 12).ToList(); 

Sie müssen es auf diese Weise ist

context.MyDbSet.ToList().Where(m => m.LongClientId == 12); 

Das Ergebnis dieser Abfrage ändern, dass Sie alle Tabelle Aufzeichnungen laden (Übertragung von dbms zu Ihrer App) in eine Liste als die, die Sie benötigen.

x Erstellen Sie eine Ansicht (wahrscheinlich eine indizierte Sicht), und verwenden Sie einen INSTEAD OF-Trigger.

+0

Ich habe ein Problem im EF-Repository auf GitHub erstellt, denn was ich gerne bekommen würde, ist derzeit in EF6 und EF Core nicht möglich. Ich werde wahrscheinlich die dritte Lösung wählen, weil ich nicht ganze Tabellen in den Speicher laden will ('ToList' macht das). Gespeicherte Prozeduren werden dasselbe tun, so dass die Ansicht für jetzt die beste Lösung ist. Ich werde das offen lassen, vielleicht gibt es eine bessere Lösung. – Misiu