Frage

Wie kann ich einen Datensatz (und löschen sie schließlich löschen) mit linq2SQL abrufen, ohne den Typ zur Kompilierung zu kennen?

Bisher habe ich

Sub Delete(ByVal RecordType As String, ByVal ID As Integer)
    Dim dummy = Activator.CreateInstance(MyAssembly, RecordType).Unwrap
    Dim tbl = GetTable(dummy.GetType)
    tbl.DeleteOnSubmit(dummy)
End Sub

Aber natürlich ist der Dummy keine tatsächliche Aufzeichnung, es ist nur ein Dummy

Ich möchte keine Direct SQL (oder ExecuteCommand) verwenden, da bei der Löschung in der DataContext Partial Class eine Geschäftslogik vorliegt

Kann das irgendwie getan werden?

Danke sehr!

BEARBEITEN

Als Antwort auf Striplinwarior habe ich meinen Code bearbeitet, um:

Sub Delete(ByVal RecordType As ObjectType, ByVal ID As Integer)
    Dim dummy = Activator.CreateInstance(ObjectType.Account.GetType.Assembly.FullName, RecordType.ToString).Unwrap
    SetObjProperty(dummy, PrimaryKeyField(RecordType), ID)
    Dim tbl = GetTable(dummy.GetType)
    tbl.Attach(dummy)
    tbl.DeleteOnSubmit(dummy)
    SubmitChanges()
End Sub

Dies schießt den Korrektur des Löschcode -Correclty ab, scheint aber auch zu versuchen, den Datensatz zuerst zur DB hinzuzufügen, da ich eine SQLEXception erhalte, dass einige "nicht null" -Felder leer sind, was ich für den Dummy -Datensatz wie die wahre Dummy -Datensatz ist Das einzige, was dies hat, ist der Primärkey, sonst ist alles leer. Also habe ich den anderen Code ausprobiert, den du gepostet hast (etwas, das ich sowieso schon immer haben wollte) und das funktioniert ausgezeichnet!

Ihre mein aktueller Code:

Function LoadRecord(ByVal RecordType As String, ByVal RecordID As Integer) As Object
    Dim dummy = Activator.CreateInstance(AssemblyName, RecordType).Unwrap
    Dim rowType = dummy.GetType
    Dim eParam = Expression.Parameter(rowType, "e")
    Dim idm = rowType.GetProperty(PrimaryKeyField(RecordType))
    Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idm), Expression.Constant(RecordID)), eParam)
    Dim firstMethod = GetType(Queryable).GetMethods().[Single](Function(m) m.Name = "Single" AndAlso m.GetParameters().Count() = 2).MakeGenericMethod(rowType)
    Dim tbl = GetTable(rowType)
    Dim obj = firstMethod.Invoke(Nothing, New Object() {tbl, lambda})
    Return obj
End Function
Sub Delete(ByVal RecordType As String, ByVal RecordID As Integer)
    Dim obj = LoadRecord(RecordType, RecordID)
    Dim tbl = GetTable(obj.GetType)
    tbl.DeleteOnSubmit(obj)
    SubmitChanges()
End Sub

Danke

War es hilfreich?

Lösung

Die einzige Möglichkeit, wie ich mir vorstellen kann, besteht darin, die Modellinformationen aus Ihrer Datenbankzuordnung zu verwenden, um herauszufinden, welches Mitglied den Primärschlüssel darstellt:

Dim primaryKey = (From t In db.Mapping.GetTables() _
            Where t.RowType.Type = tableType _
            Let keyMember = (From dm In t.RowType.DataMembers where dm.IsPrimaryKey).FirstOrDefault() _
            Select keyMember.Member.Name).First()

(Ich verwende hier Linqpad: Ich gehe davon aus, dass typische Linq zu SQL -Modellen diese Zuordnungsinformationen verfügbar haben.)

Verwenden Sie dann Reflection, um den Wert dieses Schlüsselelements auf dem von Ihnen erstellten Dummy -Element festzulegen. Danach müssen Sie den Dummy an den Tisch befestigen, bevor Sie versuchen, sie zu löschen false Als zweiter Parameter, der SQL zu Linq anweist, möchten Sie das Objekt nicht mit seinen aktuellen Werten aktualisieren, aber dass es Änderungen von hier an verfolgen sollte.

tbl.Attach(dummy, false) 
tbl.DeleteOnSubmit(dummy)
db.SubmitChanges()

Ist das sinnvoll?

Bearbeiten

Wenn Sie nur ein Objekt löschen, müssen Sie nicht unbedingt den Datensatz aus der Datenbank erhalten. Wenn Sie den ID -Wert des Objekts festlegen und dann an den Kontext anhängen (wie oben gezeigt), behandelt LINQ ihn so, als würde er aus der Datenbank abgerufen. Zu diesem Zeitpunkt sollte das Aufrufen von Deleteonsubmit den Kontext mitteilen, dass er a konstruieren soll DELETE Anweisung in SQL basierend auf dem primären Schlüsselwert dieses Objekts.

Wenn Sie das Objekt jedoch für einen anderen Zweck als das Löschen abrufen müssen, müssen Sie einen Ausdruck konstruieren, um die Abfrage für dieses Objekt darzustellen. Wenn Sie beispielsweise die Abfrage manuell schreiben würden, würden Sie so etwas sagen wie:

Dim obj = tbl.First(Function(e) e.Id = ID)

Um den Lambda -Ausdruck dynamisch in den Klammern zu erstellen, können Sie so etwas tun:

Dim eParam = Expression.Parameter(rowType, "e")
Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idMember), Expression.Constant(ID)), eParam)

Dann müssten Sie Reflexion verwenden, um die generische erste Methode aufzurufen:

Dim firstMethod = GetType(Queryable).GetMethods().[Single](Function(m) m.Name = "Single" AndAlso m.GetParameters().Count() = 2).MakeGenericMethod(rowType)
Dim obj = firstMethod.Invoke(Nothing, New Object() {tbl, lambda})
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top