简体   繁体   English

LINQ To SQL:使用一个查询删除实体(按ID)

[英]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. 我一直在使用LINQ To SQL一段时间,当涉及从数据库中删除实体时,我总是调用表的.DeleteOnSubmit并传入实体。 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? 通常我有我需要删除的记录的ID,我想知道是否有更直接的方法通过ID从表中删除行?

Do this without hand tooling SQL by attaching a partial object and deleting it: 通过附加部分对象并删除它,无需手动工具SQL即可执行此操作:

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 }); 例如实现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 请参阅解释 - 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: 我不相信Linq to Sql可以原生这样做,虽然编写存储过程会给你你想要的,语法如下:

db.spDeleteUserById(id);

This would requre writing a stored procedure for each table, but it's a pretty trivial amount of SQL. 这将需要为每个表编写一个存储过程,但这是一个非常微不足道的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. 您可以采用此概念并使用它来创建不需要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. 它不会受到紧耦合数据访问逻辑的问题,因为按id删除行不太可能需要重构。

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. 我知道这个问题已经过时了,但这是一个更新的(IMO)更好的解决方案。
I was trying to accomplish the same thing when I ran across PLINQO . 当我遇到PLINQO时,我试图完成同样的事情。 Very nice set of extensions to LINQ. 对LINQ非常好的扩展。 This page describes how to perform deletes with PLINQO's extension methods that require only 1 roundtrip to the db server. 本页介绍如何使用PLINQO的扩展方法执行删除操作,这些方法只需要向数据包服务器进行1次往返。
The downside is that it requires Codesmith to run, which is a little pricey. 缺点是它需要Codesmith运行,这有点贵。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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