2008-12-03 4 views
17

Je travaille avec LINQ To SQL depuis un petit moment maintenant et quand il s'agit de supprimer une entité de la BD, j'ai toujours appelé la table. DeleteOnSubmit et transmis dans l'entité. Parfois je me suis trouvé écrire quelque chose comme:LINQ To SQL: Supprimer une entité (par ID) avec une requête

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

Ceci bien sûr provoque deux requêtes. Un pour obtenir l'entité correspondant aux critères et un autre pour l'effacer. J'ai souvent l'identifiant de l'enregistrement à retirer et je me demande s'il existe un moyen plus direct de retirer une ligne d'une table via l'identifiant uniquement?

Répondre

0

Je ne crois pas à Sql peut Linq faire nativement, bien que l'écriture d'une procédure stockée vous donnera ce que vous voulez, avec la syntaxe comme:

db.spDeleteUserById(id); 

Ceci requre écrit une procédure stockée pour chaque table , mais c'est une quantité assez triviale de SQL.


Découvrez this blog post, dans lequel l'auteur a créé une méthode d'extension qui génère sa propre déclaration de suppression. Vous pourriez être en mesure de prendre ce concept et de le lancer pour créer une routine de suppression qui ne nécessite pas de sélection. L'inconvénient est que vous pourriez vous retrouver avec une méthode d'extension spécifique à votre propre schéma. Je comprends que vous voulez garder votre logique hors de la couche de base de données, mais dans ce cas, je pense qu'il serait beaucoup plus simple d'aller sur la route proc. Il ne serait pas soumis aux problèmes liés à la logique d'accès aux données étroitement couplée, puisque la suppression d'une ligne par identifiant ne nécessitera probablement jamais de refactorisation.

6

Voici une solution ...

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

Ce n'est pas mon code! Voir pour l'explication - http://msmvps.com/blogs/omar/archive/2008/10/30/linq-to-sql-delete-an-entity-using-primary-key-only.aspx

Espérons que cela aide.

+0

Vous pouvez également faire de DeleteByPK une méthode d'extension sur DataContext et la chaîne elle-même devrait probablement être une requête paramétrée (exec sp_executesql ...). –

+7

dans la ligne SQL sur une déclaration Linq2Sql semble vaincre le but –

+3

@Bobby: pas vraiment.J'utilise en ligne SQL pour la performance et en cas de besoin (SQL complexe). Reste sur la génération SQL pour les opérations communes. –

0

J'utilise les méthodes d'extension suivantes, l'être d'utilisation:

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

Je sais que cette question est vieux, mais voici une meilleure nouvelle et (OMI) solution.
J'essayais d'accomplir la même chose quand j'ai couru à travers PLINQO. Très bel ensemble d'extensions à LINQ. This page décrit comment effectuer des suppressions avec les méthodes d'extension de PLINQO qui nécessitent seulement un aller-retour vers le serveur db. L'inconvénient est qu'il faut Codesmith pour fonctionner, ce qui est un peu cher.

4

faire sans main outillage SQL en attachant un objet partiel et supprimer:

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

facile. Vous pouvez même l'écrire comme une méthode d'extension et utiliser un type d'objet dynamique pour représenter la clé, et utiliser la réflexion pour comprendre les propriétés clés, que je vais laisser comme un exercice amusant pour le lecteur. Par exemple. implémenter Context.Delete (new {MyEntityId = xxx});

Questions connexes