views:

669

answers:

6

What is the best way to delete a database record using LINQ when I have the primary key?

A: 

You can map a stored procedure to a method on the DataContext that deletes a record with a given value for the primary key.

Mark Cidade
A: 

I've always used the select-delete approach as it's very straight-forward. As marxidad said, you can map a stored proc if you really want to. I believe there are plans for ESQL to support insert, update and delete operations in the future.

Ty
+2  A: 

That approach is acceptable and typical.

It is a little wasteful because you're requesting the whole record. This cannot be avoided given the DeleteOnSubmit method signature.

Why does LINQ to SQL work this way? The answers obvious if you think about tables that do not have primary keys, or use composite keys. LINQ to SQL needs the whole record for the worst case where it needs to match every object property against the table fields.

But as should be asked for all concerns of performance - are you absolutely sure this is a performance issue for you?? Where's your profiling proof?

I haven't tried this yet but there might be a way to achieve the same thing with DataContext.ExecuteCommand.

CVertex
L2S can't delete a record from a table that doesn't have a primary key.
Adam Lassek
+1  A: 

I ended up doing a select, but improved my syntax which I think was really my concern:

Old:

var products = from p in db.Products select p;
db.Products.DeleteOnSubmit(products.Take(1).Single()); <--seemed nasty
db.SubmitChanges();

New:

Service service = db.Services.Where(s => s.id == serviceID).FirstOrDefault(); <--nicer
db.Services.DeleteOnSubmit(service);
db.SubmitChanges();
stimms
Oh, you meant syntactically inefficient (i.e. ugly), not actually inefficient....
CVertex
+1  A: 
  public static Delete(this ITable table, object key)
   { var t = table.GetType();
     var tableName  = t.GetCustomAttributes
                                    (typeof(TableAttribute),false)[0].Name;
     var primaryKey = (from p in t.GetProperties()
                       from c in p.GetCustomAttributes
                                            (typeof(ColumnAttribute),false)
                       where c.IsPrimaryKey
                       select c.Name).Single();
     using (var cmd = table.Context.Connection.CreateCommand())
      { cmd.CommandText = string.Format( "DELETE FROM {0} WHERE {1} = @key"
                                        ,tableName, primaryKey);
        cmd.Parameters.Add(new SqlParameter("@key", key));
        cmd.ExecuteNonQuery();        
      }            
   }

/* ... */
dataContext.Table1.Delete(id);
Mark Cidade
Nice approach but won't work for composite keys.
DamienG
It's just an example. If you accept multiple keys and values as parameters and use the ColumnAttributes to validate, you should be okay.
Mark Cidade
+1  A: 

If you set update checks on all your columns to never or when changed, you can simply attach an instance with the primary key and delete the row without a load.

public void DeleteCustomer(int CustomerID)
{
    NorthwindContext c = new NorthwindContext c;
    Customer target = new Customer(){CustomerID = CustomerID};
    c.Customers.Attach(target);
    c.Customers.DeleteOnSubmit(target);
    c.SubmitChanges();                       
}
David B