简体   繁体   中英

LINQ To SQL: Delete entity (by ID) with one query

I've been working with LINQ To SQL for a little while now and when it comes to removing an entity from the DB, I've always called the table's .DeleteOnSubmit and passed in the entity. Sometimes I've found myself writing something like:

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

This of course causes two queries. One to get the entity matching the criteria and then another to delete it. Often I have the ID of the record I need removing and I am wondering if there is a more direct way to remove a row from a table via the ID only?

Do this without hand tooling SQL by attaching a partial object and deleting it:

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

Easy. You can even write it as an extension method and use a dynamic object type to represent the key, and use reflection to figure out key properties, which I will leave as a fun exercise for the reader. Eg implement Context.Delete(new { MyEntityId = xxx });

Here is a 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);
}

It's not my code! See for explaination - http://msmvps.com/blogs/omar/archive/2008/10/30/linq-to-sql-delete-an-entity-using-primary-key-only.aspx

Hope this helps.

I don't believe Linq to Sql can do this natively, although writing a stored procedure would give you what you want, with syntax like:

db.spDeleteUserById(id);

This would requre writing a stored procedure for each table, but it's a pretty trivial amount of SQL.


Check out this blog post , in which the author has created an extension method that generates its own delete statement. You might be able to take this concept and run with it to create a delete routine that doesn't require a select. The downside is, you might end up with an extension method that is specific to your own schema.

I understand that you want to keep your logic out of the database layer, but in this case I think it would be far simpler to go the stored proc route. It wouldn't be subject to the problems with tightly coupled data access logic, since deleting a row by id isn't likely to ever need refactoring.

I am using the following extension methods, the usage being:

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

I know this question is old but here's a newer and (IMO) better solution.
I was trying to accomplish the same thing when I ran across PLINQO . Very nice set of extensions to LINQ. This page describes how to perform deletes with PLINQO's extension methods that require only 1 roundtrip to the db server.
The downside is that it requires Codesmith to run, which is a little pricey.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM