c# - 使用 LINQ 将数据插入到使用序列作为主键生成器的表中

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

我有一个表,它根据序列生成主键(从 0 开始计数):

CREATE TABLE [dbo].[testTable](
    [id] [int] NOT NULL,
    [a] [int] NOT NULL,
 CONSTRAINT [PK_testTable] PRIMARY KEY CLUSTERED ([id] ASC))

ALTER TABLE [dbo].[tblTestTable] ADD  CONSTRAINT [DF_tblTestTable_id]  DEFAULT (NEXT VALUE FOR [seq_PK_tblTestTable]) FOR [id]

我使用 Visual Studio 的 O/R Designer 为表创建映射文件; id 字段定义为:

[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_id", DbType="Int NOT NULL", IsPrimaryKey=true)]
public int id {…}

现在我尝试通过 LINQ 插入数据。

var testTableRecord = new testTable()
{
    a = 1,
};
db.Connection.Open();
db.testTables.InsertOnSubmit(testTableRecord);
db.SubmitChanges();
Console.WriteLine($"id: {testTableRecord.id}");

我遇到的问题是,LINQ 似乎无法通过序列处理 id 生成,因为它在插入时将 id 隐式设置为 0。

  • 当我将 id 设置为 CanBeNull 时,插入失败,因为它尝试将 NULL 插入不可为 null 的字段。
  • 当我将 id 设置为 IsDbGenerate 时,插入可以工作,但它需要一个 IDENTITY 字段,并尝试使用 加载生成的 id code>SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]',N'@p0 int',@p0=1 并将对象中的 id 设置为 null,因为SCOPE_IDENTITY() 返回null...
  • 我一直在考虑仅使用 IsDbGenerate、销毁 LINQ 对象并在数据库中查询 id,但我没有任何独特的内容可供搜索.

不幸的是,无法将 id 创建机制更改为 IDENTITY。

我必须 explicitly query the DB for the next sequence value并手动设置id?

通过 LINQ 处理这些插入的最佳方法是什么?

PS:我需要 id,因为我必须插入更多使用 id 作为 FK 的数据。

最佳答案

从原始 sql 角度查看解决方案:

1.

INSERT INTO [dbo].[testTable] VALUES (NEXT VALUE FOR [dbo].[seq_PK_tblTestTable], 1)

据我所知,根本无法在 LINQ to SQL 中完成

2.

INSERT INTO [dbo].[testTable] (a) VALUES (1)

这可以在 LINQ to SQL 中通过从 testTable 实体中排除 id 属性来实现。

如果您需要从表中检索 id,您可以创建单独的实体用于插入和查询:

public class testTableInsert {
    [ColumnAttribute(...)]
    public int a
}

public class testTableResult {
    [ColumnAttribute(...)]
    public int id

    [ColumnAttribute(...)]
    public int a
}

3.

DECLARE @nextId INT;
SELECT @nextId = NEXT VALUE FOR [dbo].[seq_PK_tblTestTable];  
INSERT INTO [dbo].[testTable] VALUES (@nextId, 1)

正如您所提到的,这基本上可以通过在每次插入之前手动请求下一个 id 来实现。如果您选择这条路线,有多种方法可以在代码中实现它,您可以考虑存储过程或使用 LINQ 数据上下文手动执行 sql 以检索下一个序列值。

以下代码示例演示了如何使用部分方法扩展生成的 DataContext。

public partial class MyDataContext : System.Data.Linq.DataContext
{
    partial void InsertTestTable(TestTable instance)
    {

        using (var cmd = Connection.CreateCommand()) 
        {
            cmd.CommandText = "SELECT NEXT VALUE FOR [dbo].[seq_PK_TestTable] as NextId";
            cmd.Transaction = Transaction;
            int nextId = (int) cmd.ExecuteScalar();
            instance.id = nextId;

            ExecuteDynamicInsert(instance);
        }         
    }
}

一旦实现了上述操作,您就可以安全地插入这样的实体,它们将生成正确的序列id。

TestTable entity = new TestTable { a = 2 };
dataContext.TestTables.InsertOnSubmit(entity);
dataContext.SubmitChanges();

关于c# - 使用 LINQ 将数据插入到使用序列作为主键生成器的表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54463242/

相关文章:

sql - 具有 uniqueidentifier 的递归 CTE 必须在 anchor 中具有值

sql - 获取时间间隔的计数

c# - 实例方法的 'this' 参数可以是无类型的(即 System.Object)吗?

c# - .NET 代码行计数器

使用 Oauth2 和 Google Drive API 的 c# 异常(使用 4.0 .Net)

.net - 您可以舍入 .NET TimeSpan 对象吗?

sql - 需要将前一天的日期类型与整数值进行比较

c# - Azure 移动应用程序 - 自定义身份验证 - 无法登录

c# - Rtf to Html 删除 html 表

c# - 无法弄清楚如何检查生物识别是否存在