Единственный способ, которым я могу придумать, - это использовать информацию о модели из сопоставления вашей базы данных, чтобы выяснить, какой элемент представляет первичный ключ:
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 эта информация о сопоставлении доступна).
Затем используйте отражение, чтобы установить значение этого ключевого элемента для фиктивного элемента, который вы создали. После этого вам нужно присоединить фиктивную таблицу к таблице, прежде чем пытаться ее удалить, передав false
в качестве второго параметра, чтобы сообщить LINQ to SQL, что вы на самом деле не хотите обновлять объект, используя его текущие значения, но что он следует отслеживать изменения с этого момента.
tbl.Attach(dummy, false)
tbl.DeleteOnSubmit(dummy)
db.SubmitChanges()
Имеет ли это смысл?
Редактировать
Когда вы только удаляете объект, вам не обязательно получать запись из базы данных. Если вы установите значение идентификатора объекта и затем присоедините его к контексту (как показано выше), LINQ to SQL будет обрабатывать его так, как если бы оно было получено из базы данных. На этом этапе вызов DeleteOnSubmit должен сообщить контексту, что необходимо создать оператор DELETE
в SQL на основе значения первичного ключа этого объекта.
Однако, если вам нужно получить объект для какой-либо цели, кроме удаления, вам нужно будет создать выражение для представления запроса для этого объекта. Так, например, если вы пишете запрос вручную, вы бы сказали что-то вроде:
Dim obj = tbl.First(Function(e) e.Id = ID)
Таким образом, чтобы динамически построить лямбда-выражение в скобках, вы можете сделать что-то вроде этого:
Dim eParam = Expression.Parameter(rowType, "e")
Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idMember), Expression.Constant(ID)), eParam)
Тогда вам нужно будет использовать отражение, чтобы вызвать универсальный метод First:
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})