【问题标题】:LINQ To SQL: Delete entity (by ID) with one queryLINQ To SQL:使用一个查询删除实体(按 ID)
【发布时间】:2008-12-03 22:52:54
【问题描述】:

我使用 LINQ To SQL 已经有一段时间了,在从数据库中删除实体时,我总是调用表的 .DeleteOnSubmit 并传入实体。有时我发现自己会写这样的东西:

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

这当然会导致两个查询。一个获取符合条件的实体,然后另一个删除它。通常我有我需要删除的记录的 ID,我想知道是否有更直接的方法可以仅通过 ID 从表中删除一行?

【问题讨论】:

    标签: c# sql linq


    【解决方案1】:

    通过附加部分对象并删除它,无需手动工具 SQL 即可做到这一点:

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

    简单。您甚至可以将其编写为扩展方法并使用动态对象类型来表示键,并使用反射来计算键属性,我将把它作为一个有趣的练习留给读者。例如。实现 Context.Delete(new { MyEntityId = xxx });

    【讨论】:

      【解决方案2】:

      这里有一个解决方案...

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

      这不是我的代码!请参阅解释 - http://msmvps.com/blogs/omar/archive/2008/10/30/linq-to-sql-delete-an-entity-using-primary-key-only.aspx

      希望这会有所帮助。

      【讨论】:

      • 您也可以让 DeleteByPK 成为 DataContext 上的扩展方法,并且字符串本身应该是参数化查询(exec sp_executesql ...)。
      • 在 Linq2Sql 语句上的行 SQL 似乎无法达到目的
      • @Bobby:不是真的。我使用在线 SQL 来提高性能和在需要时使用(复杂的 SQL)。依靠 SQL 生成来进行常见操作。
      • @Eduardo:哈,我现在也在做同样的事情。
      【解决方案3】:

      我不相信 Linq to Sql 可以原生地做到这一点,尽管编写存储过程会给你想要的东西,语法如下:

      db.spDeleteUserById(id);
      

      这将需要为每个表编写一个存储过程,但它的 SQL 数量非常少。


      查看this blog post,作者在其中创建了一个扩展方法,可以生成自己的删除语句。您可能可以采用此概念并使用它运行以创建不需要选择的删除例程。不利的一面是,您最终可能会得到一个特定于您自己架构的扩展方法。

      我知道您希望将您的逻辑排除在数据库层之外,但在这种情况下,我认为采用存储过程路径会简单得多。它不会受到紧密耦合的数据访问逻辑的问题的影响,因为通过 id 删除一行不太可能需要重构。

      【讨论】:

        【解决方案4】:

        我知道这个问题很老,但这里有一个更新和(IMO)更好的解决方案。
        当我遇到PLINQO 时,我正试图完成同样的事情。非常好的一组 LINQ 扩展。 This page 描述了如何使用 PLINQO 的扩展方法执行删除操作,只需 1 次往返数据库服务器。
        缺点是需要Codesmith才能运行,有点贵。

        【讨论】:

          【解决方案5】:

          我正在使用以下扩展方法,用法是:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多