LINQ To SQL: удалить объект (по идентификатору) с помощью одного запроса
Я уже давно работаю с LINQ To SQL, и когда дело доходит до удаления сущности из БД, я всегда вызывал таблицу .DeleteOnSubmit и передавал в сущности. Иногда я обнаружил, что пишу что-то вроде:
db.Users.DeleteOnSubmit(db.Users.Where(c => c.ID == xyz).Select(c => c).Single());
Это, конечно, вызывает два запроса. Один, чтобы получить объект, соответствующий критериям, а затем другой, чтобы удалить его. Часто у меня есть идентификатор записи, которую мне нужно удалить, и мне интересно, есть ли более прямой способ удалить строку из таблицы только с помощью идентификатора?
Ответы
Ответ 1
Вот решение...
public static void DeleteByPK<TSource, TPK>(TPK pk, DataContext dc)
where TSource : class
{
Table<TSource> table = dc.GetTable<TSource>();
TableDef tableDef = GetTableDef<TSource>();
dc.ExecuteCommand("DELETE FROM [" + tableDef.TableName
+ "] WHERE [" = tableDef.PKFieldName + "] = {0}", pk);
}
Это не мой код! См. Объяснение - http://msmvps.com/blogs/omar/archive/2008/10/30/linq-to-sql-delete-an-entity-using-primary-key-only.aspx
Надеюсь, что это поможет.
Ответ 2
Сделайте это без ручного инструментария SQL, добавив частичный объект и удалив его:
var myEntity = new MyEntityType { MyEntityId = xxx };
Context.MyEntityTypeTable.Attach(myEntity, false);
Context.MyEntityTypeTable.DeleteOnSubmit(myEntity);
Context.SubmitChanges();
Легко. Вы даже можете записать его как метод расширения и использовать динамический тип объекта для представления ключа, а также использовать отражение для определения ключевых свойств, которое я оставлю в качестве веселого упражнения для читателя. Например. реализовать Context.Delete(новый {MyEntityId = xxx});
Ответ 3
Я не верю, что Linq to Sql может сделать это изначально, хотя запись хранимой процедуры даст вам то, что вы хотите, с синтаксисом вроде:
db.spDeleteUserById(id);
Это потребовало бы записи хранимой процедуры для каждой таблицы, но это довольно тривиальное количество SQL.
Отметьте это сообщение в блоге, в котором автор создал метод расширения, который генерирует свою собственную инструкцию delete. Вы могли бы принять эту концепцию и запустить ее, чтобы создать процедуру удаления, которая не требует выбора. Недостатком является то, что у вас может быть метод расширения, специфичный для вашей собственной схемы.
Я понимаю, что вы хотите сохранить свою логику из уровня базы данных, но в этом случае я думаю, что гораздо проще перейти к сохраненному маршруту proc. Это не будет связано с проблемами с жестко связанной логикой доступа к данным, поскольку удаление строки по идентификатору вряд ли когда-либо понадобится для рефакторинга.
Ответ 4
Я использую следующие методы расширения, использование:
context.Customers.DeleteEntity(c => c.CustomerId, 12);
public static class EntityExtensions
{
public static EntityKey CreateEntityKey<T, TId>(this ObjectSet<T> entitySet, Expression<Func<T, TId>> entityKey, TId id)
where T : class
{
var qEntitySet = entitySet.Context.DefaultContainerName + "." + entitySet.EntitySet.Name;
var keyName = LinqHelper.PropertyName(entityKey);
return new EntityKey(qEntitySet, keyName, id);
}
public static void DeleteEntity<T, TId>(this ObjectSet<T> entitySet, Expression<Func<T, TId>> entityKey, TId id)
where T : EntityObject, new()
{
var key = CreateEntityKey(entitySet, entityKey, id);
var entityInstance = new T {EntityKey = key};
var propertyName = LinqHelper.PropertyName(entityKey);
var property = typeof (T).GetProperty(propertyName);
if (property == null)
throw new Exception("Property name " + propertyName + " does not exist on " + typeof(T).Name);
property.SetValue(entityInstance, id, null);
entitySet.Attach(entityInstance);
entitySet.DeleteObject(entityInstance);
}
Ответ 5
Я знаю, что этот вопрос старый, но здесь более новое и (ИМО) лучшее решение.
Я пытался сделать то же самое, когда я наткнулся на PLINQO. Очень хороший набор расширений для LINQ. Эта страница описывает, как выполнять удаленные действия с помощью методов расширения PLINQO, которые требуют только одного перехода туда-обратно к серверу db.
Недостатком является то, что для выполнения требуется Codesmith, что немного дорого.