我有一个表,它根据序列生成主键(从 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/