【问题标题】:How to get the primary key from a table without making a second trip?如何在不进行第二次访问的情况下从表中获取主键?
【发布时间】:2010-01-18 03:32:54
【问题描述】:

我如何从表中获取主键 ID 号而不第二次访问 LINQ To SQL 中的数据库?

现在,我将数据提交到表中,然后再进行一次检查,以找出分配给新字段的 id(在自动增量 id 字段中)。我想在 LINQ To SQL 中而不是在 Raw SQL 中执行此操作(我不再使用 Raw SQL)。

另外,我的问题的第二部分是:我总是很小心地知道在线用户的 ID,因为我宁愿使用他们的 ID 在各种表中调用他们的信息,而不是使用 GUID 或用户名,这都是长字符串。我这样做是因为我认为 SQL Server 进行数字比较比进行用户名(字符串)甚至 guid(非常长的字符串)比较更有效(?)。我的问题是,我是否比我应该更担心?差异是否值得始终将用户 ID (int32) 保持在会话状态?


@RedFilter 为第一个问题提供了一些有趣/有希望的线索,因为我现阶段无法尝试它们,如果有人知道或可以确认他在答案的 cmets 部分中推荐的这些更改吗?

【问题讨论】:

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


    【解决方案1】:

    如果您有对该对象的引用,则可以在调用db.SubmitChanges() 后使用该引用并调用主键。 LINQ 对象将自动更新其(标识符)主键字段以反映通过 SQL Server 分配给它的新主键字段。

    示例(vb.net):

      Dim db As New NorthwindDataContext
      Dim prod As New Product
      prod.ProductName = "cheese!"
      db.Products.InsertOnSubmit(prod)
      db.SubmitChanges()
      MessageBox.Show(prod.ProductID)
    

    您可以将上述代码包含在一个函数中并返回 ProductID(或等效的主键)并在其他地方使用它。

    编辑:如果您不进行原子更新,则可以将每个新产品添加到单独的集合中,并在调用 SubmitChanges 后对其进行迭代。我希望 LINQ 能够像数据集一样提供“数据库先睹为快”。

    【讨论】:

    • @calico:谢谢队友,解释得很好,偶尔在这里看到一些 vb 代码也很令人耳目一新,给了你投票并接受答案,所以现在你可以开始投票了 :)
    • 只是为了让您知道,我在提交后尝试调用引用对象的 PorductID,但它根本不起作用。虽然我没有“按原样”尝试上面的代码,但原则上是一样的,知道为什么它可能很挑剔吗?
    • 你确定提交成功了吗?你确定你还在引用同一个对象吗?我不知道你的代码,所以我不能确定。
    • 我不认为它开箱即用,我认为如果我们实现 RedFilter 在他的答案的 cmets 部分中引用的更改,那么它应该可以工作吗? (但要试试这个)。
    【解决方案2】:

    除非您正在做一些不寻常的事情,否则您不需要做任何额外的事情来检索生成的主键。

    当您在 Linq-to-SQL 数据上下文中调用 SubmitChanges 时,它会自动更新对象的主键值。

    关于您的第二个问题 - 通过对数字字段进行扫描而不是像 varchar() 之类的东西,可能会稍微提高性能,但通过确保您的列中有正确的列,您会看到更好的性能数据库索引。而且,对于 SQL Server,如果您使用标识列创建主键,则默认情况下它会在其上具有聚集索引。

    【讨论】:

    • 您好,谢谢,您的权利在 SubmitChange 期间自动递增,这不是问题 - 我需要保留此号码/ID 才能真正使用它来调用其他记录,这就是我想要它的唯一原因处于会话状态。
    【解决方案3】:

    Linq to SQL 使用插入新记录时生成的 ID 自动设置类的标识值。只需访问该属性。我不知道它是否为此使用了单独的查询,从未使用过它,但 ORM 要求另一个查询来取回最后插入的 ID 并不罕见。

    您可以通过两种方式独立于 Linq To SQL(可能适用):

    1) 如果您使用的是 SQL Server 2005 或更高版本,则可以使用 OUTPUT 子句:

    从或返回信息 基于每行的表达式 受 INSERT、UPDATE 或 删除语句。这些结果可以 返回处理申请 用于确认等用途 消息、归档和其他此类 申请要求。 或者,可以插入结果 到表或表变量中。

    2) 或者,您可以像这样构造一个批处理 INSERT 语句:

    insert into MyTable
    (field1)
    values
    ('xxx');
    select scope_identity();
    

    至少可以追溯到 SQL Server 2000。

    【讨论】:

    • 嗨 orbMan,如果 linq to sql 在 SubmitChanges 之后自动更新了类的 id 列,那就太好了,有人可以确认吗?
    • @Erx_VB.NExT.Coder:如果您告诉它,它将更新插入的 id 列。默认情况下,如果您的 id 列是 int 类型,它将自动设置为“在插入时生成”,如果它是 guid 类型,那么您必须将默认值更改为“在插入时生成”。您可以从 Linq 2 SQL 设计器中执行此操作。
    • @EgilHansen 啊,太棒了,因为当我尝试这个时,它没有开箱即用,我将实施这些更改并再试一次,让你知道它是怎么回事(一旦我回来在这个特定项目或另一个使用 LINQ To SQL 的项目上)。
    【解决方案4】:

    在 T-SQL 中,您可以使用 OUTPUT 子句,表示:

    INSERT table (columns...)
    OUTPUT inserted.ID
    SELECT columns...
    

    因此,如果您可以将 LINQ 配置为使用该构造进行插入,那么您可能很容易将其取回。但是 LINQ 是否可以从插入中返回值,我会让其他人回答这个问题。

    【讨论】:

    • 我不知道如何用 sql lang 编写 sql 过程。但是如果我可以很确定 linq 可以映射到它的 .dbml 文件设计器中的 sql 存储过程,那么它应该能够获取返回值,可能只有当你使用 t-sql 执行整个 INSERT 时...否则我不确定也是。
    • 我不认为 InsertOnSubmit 或 Submit 作为与我们的需求相关的返回值。
    【解决方案5】:

    从返回 ID 作为输出参数的 LINQ 调用存储过程可能是最简单的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 1970-01-01
      相关资源
      最近更新 更多