2011-01-31 34 views
1

我怎樣才能抓住一個記錄(並最終刪除它)使用linq2sql而不知道編譯時的類型?抓住linq到sql記錄由primarykey而不知道它的類型

到目前爲止,我已經得到了

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 

但當然啞不是實際的記錄,它只是一個虛擬

我不想使用直接的SQL(或executecommand)作爲在datacontext部分類中刪除業務邏輯

這可以以某種方式完成嗎?

非常感謝你!

編輯

響應striplinwarior,我修改了代碼:

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 

這並不關火刪除代碼correclty,又似乎首先嚐試添加記錄到數據庫,因爲我得到一個sqlexception,有些「不空」字段是空的,我猜對於虛擬記錄是真實的,因爲這是唯一的主鍵,否則是全空的。所以我嘗試了其他代碼ü張貼(反正我一直想要的東西),這很好!

她我當前的代碼:

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 

謝謝

回答

4

我能想到的唯一的辦法是使用模型信息從數據庫映射,以找出哪些成員表示主鍵:

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() 

(我在這裏使用LinqPad:我認爲典型的LINQ to SQL車型有可用該映射信息。)

然後使用反射在您創建的虛擬物品上設置該關鍵成員的值。之後,您需要在表中附加虛擬表格,然後將其作爲第二個參數傳遞給LINQ to SQL,表明您實際上並不想使用其當前值更新對象,但它應該跟蹤從這裏改變。

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

這有道理嗎?

編輯

當你只刪除一個對象,你不一定要得到數據庫中的記錄。如果您設置了對象的ID值並將其附加到上下文(如上所示),則LINQ to SQL會將它視爲從數據庫中檢索它。此時,調用DeleteOnSubmit應該告訴上下文根據該對象的主鍵值在SQL中構造一個DELETE語句。

但是,如果您需要檢索除刪除之外的其他用途的對象,則需要構造一個表達式來表示該對象的查詢。因此,舉例來說,如果你手工編寫查詢,你會這樣說:

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

所以要動態地構建括號內的lambda表達式,你可能會做這樣的事情:

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

然後,您需要使用反射來調用通用第一種方法:

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}) 
+0

嗨。我知道如何獲得主鍵字段的名稱。這個新的想法。但是一旦我有了這個領域的名字,我如何獲得這個記錄。這就是問題所在。謝謝。 – 2011-02-01 14:26:55