【问题标题】:Can I update LINQ-to-SQL records retrieved with db.ExecuteQuery()?我可以更新使用 db.ExecuteQuery() 检索到的 LINQ-to-SQL 记录吗?
【发布时间】:2013-03-09 11:30:50
【问题描述】:

我的查询是从 app.config 动态检索的。我知道某些列将被包括在内。我想更新处理后返回的每条记录中的一列。我可以使用.SubmitChanges() 或类似方法来执行此操作吗?还是我必须用更新 sql 写另一个 db.ExecuteQuery()

DataClasses1DataContext db = new DataClasses1DataContext();
IEnumerable<invoice> invoices = db.ExecuteQuery<invoice>(ConfigurationManager.AppSettings["query_sql"].ToString());
foreach (invoice i in invoices)
{
    // do something with the invoice
    // flag the invoice as processed
    i.doc_processed = "Y";
    db.SubmitChanges();
}

更新

感谢 madd0 的回答,我重新设计了我的应用程序允许动态 SQL 的方式。应用程序不是在 app.config 中输入查询,而是查找具有特定名称的 SQL 视图。这样可以添加视图,LINQ 将自动生成类型/类并允许使用.SubmiteChanges()进行跟踪/更新

【问题讨论】:

    标签: c# .net linq linq-to-sql


    【解决方案1】:

    为了使用SubmitChanges 更新您的实体,Linq to Sql 必须能够跟踪它们。最简单的方法是让 Linq 生成你的类型(或者,你也可以用一堆属性装饰 POCO。)

    如果您的invoice 类型未生成以便Linq to Sql 可以跟踪它,则DataContext 将无法确定哪些对象已更改并在SubmitChanges 为时生成正确的UPDATE 语句调用。

    如果您正在使用跟踪的实体并且 ObjectTrackingEnabled 设置为 true,但想要使用 ExecuteQuery&lt;T&gt; 而不是让 Linq to Sql 生成您的查询,您仍然必须进行确保您的 SELECT 命令返回所有跟踪的字段并且您的表有一个主键(这在 documentation of ExecuteQuery&lt;T&gt; 中有说明。)

    最后,正如我在原始答案中解释的那样,您始终可以使用ExecuteCommand 手动执行UPDATE 查询。这是我进行大部分更新的方式,因为它在大多数情况下更有效,尤其是在更新大量实体时,因为 Linq to SQL 将在服务器上为每个更新的记录执行单独的 UPDATE 命令使用SubmitChanges,而如果您手动执行,您很可能能够将其编写为单个命令。

    如果您决定创建自己的 UPDATE 语句并使用 ExecuteCommand 执行它们,请记住在为了限制 SQL 注入攻击。 documentation for ExecuteCommand 中提供了参数化查询的示例。

    【讨论】:

    • 我想在处理它们时更新它们(一次一个)。我怎样才能做到这一点?我上面的代码不起作用。
    • 您的invoice 类型是被跟踪的实体(即由Linq2Sql 生成的类型)吗?如果是,您的查询是否返回实体的 all 列? Linq2Sql 需要这两个条件(以及更多条件)才能自动更新SubmitChanges 上的表。否则,您必须使用ExecuteCommand 执行您的UPDATES,当然,如果您需要单独更新,您可以在循环中执行此操作。
    • 不,发票是我创建的一个类。我预计“否”是答案,但发现很难确认 - 你能引用任何参考资料吗?无论如何,如果您想将此作为答案发布,我会接受。
    • 我昨天更新了答案,添加了我在 cmets 中讨论的内容以及一些您可能会感兴趣的链接。
    • brill- 谢谢。我还将更新我的问题以记录我最终使用的解决方案
    【解决方案2】:

    一如既往,视情况而定。

    在您的情况下,它取决于 // 对发票进行处理。 如果您在该部分中触​​摸每张发票的许多字段,则此代码很好。除了您可以将 submitchanges 移到循环之外:

      foreach (invoice i in invoices)
        {
            // do something with the invoice
            // flag the invoice as processed
            i.doc_processed = "Y";
        }
     db.SubmitChanges();
    

    因此您将受益于单笔交易(尽管仍然是多次更新,因此在大量发票的情况下,它不会是最好的)。

    如果 // 做某事相对简单明了,我会在查询中编写整个 // 做某事逻辑并在 sql 中执行,从而有效地将您的代码减少到

    db.ExecuteQuery<invoice>(ConfigurationManager.AppSettings["do_something_update_query_sql"].ToString());
    

    这种方式性能最高,但您不使用 Linq2sql 的任何 ORM 部分。

    【讨论】:

    • // do something 不是基于 sql 的,所以我无法将它移到查询中 :) db.SubmitChanges(); 命令不起作用...知道为什么吗?
    • 没有错误,但是表格没有更新。运行 sql 跟踪我看到 select 语句,但从来没有任何更新
    • 如果您使用本机 sql 检索实体,我怀疑这些实体不在您的数据库上下文中,它们只是对象。也许你必须先附上它们。
    • 我的上下文没有.attach.savechanges 方法:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 2013-04-04
    相关资源
    最近更新 更多