2008-12-03 18 views
17

He estado trabajando con LINQ To SQL por un tiempo y cuando se trata de eliminar una entidad de la base de datos, siempre he llamado a la tabla. DeleteOnSubmit y pasado en la entidad. A veces me he encontrado escribiendo algo así como:LINQ to SQL: Eliminar entidad (por ID) con una consulta

db.Users.DeleteOnSubmit(db.Users.Where(c => c.ID == xyz).Select(c => c).Single()); 

Esto, por supuesto, causa dos consultas. Uno para obtener la entidad que coincida con los criterios y luego otro para eliminarlo. A menudo tengo el ID del registro que necesito eliminar y me pregunto si hay una manera más directa de eliminar una fila de una tabla solo a través de la identificación.

Respuesta

0

no creo LINQ to SQL puede hacer esto de forma nativa, aunque escribir un procedimiento almacenado que daría lo que quiere, con una sintaxis como:

db.spDeleteUserById(id); 

Esto requre escribir un procedimiento almacenado para cada tabla , pero es una cantidad bastante trivial de SQL.


Salida this blog post, en la que el autor ha creado un método de extensión que genera su propia instrucción de eliminación. Es posible que pueda tomar este concepto y ejecutarlo para crear una rutina de eliminación que no requiera una selección. La desventaja es que podrías terminar con un método de extensión que es específico de tu propio esquema.

Entiendo que quiere mantener su lógica fuera de la capa de la base de datos, pero en este caso creo que sería mucho más simple ir a la ruta del proceso almacenado. No estaría sujeto a los problemas con una lógica de acceso a datos estrechamente unida, ya que es probable que nunca más necesite refactorizar eliminar una fila por id.

6

Aquí es una solución ...

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); 
} 

No es mi código! Ver para explicación - http://msmvps.com/blogs/omar/archive/2008/10/30/linq-to-sql-delete-an-entity-using-primary-key-only.aspx

Espero que esto ayude.

+0

También podría hacer que DeleteByPK sea un método de extensión en DataContext y la cadena misma probablemente sea una consulta parametrizada (exec sp_executesql ...). –

+7

en línea SQL en una instrucción Linq2Sql parece frustrar el propósito –

+3

@Bobby: en realidad no.Uso en línea SQL para el rendimiento y cuando sea necesario (SQL complejo). Descanse en la generación de SQL para operaciones comunes. –

0

estoy usando los siguientes métodos de extensión, al ser de uso:

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

Sé que esta pregunta es viejo, pero aquí hay un y (OMI) mejor solución nueva.
Estaba tratando de lograr lo mismo cuando me encontré con PLINQO. Muy buen conjunto de extensiones para LINQ. This page describe cómo realizar eliminaciones con los métodos de extensión de PLINQO que requieren solo 1 ida y vuelta al servidor de db. El inconveniente es que requiere Codesmith para funcionar, que es un poco caro.

4

hacer esto sin la mano de SQL herramientas adjuntando un objeto parcial y eliminarlo:

var myEntity = new MyEntityType { MyEntityId = xxx }; 
Context.MyEntityTypeTable.Attach(myEntity, false); 
Context.MyEntityTypeTable.DeleteOnSubmit(myEntity); 
Context.SubmitChanges(); 

fácil. Incluso puede escribirlo como un método de extensión y usar un tipo de objeto dinámico para representar la clave, y usar la reflexión para descubrir las propiedades clave, que dejaré como un ejercicio divertido para el lector. P.ej. implementar Context.Delete (new {MyEntityId = xxx});

Cuestiones relacionadas