[英]how to insert data in sql table using Linq without seting any primary key in table
[英]Using LINQ to insert data into a table that uses a sequence as primary key generator
我有一个表,该表从一个序列(仅从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设计器来创建表的映射文件。 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插入非空字段。 id
设置为IsDbGenerated
,插入可以工作,但是它需要一个IDENTITY
字段,并尝试使用SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]',N'@p0 int',@p0=1
然后将对象中的id
设置为null,因为SCOPE_IDENTITY()
返回null
。 IsDbGenerated
,销毁LINQ对象并向数据库查询id
,但是我没有什么可以搜索的。 不幸的是,不能将ID创建机制更改为IDENTITY。
我是否必须明确查询数据库以获取下一个序列值并手动设置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)
通过从testTable
实体中排除id属性,可以在LINQ to SQL中实现这一点。
如果需要从表中检索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();
您唯一的希望是进行深刻的重构,并使用存储过程插入记录 。 可以将存储过程映射到数据上下文设计器中类的Insert
方法。
使用表定义,存储的内容只不过是这样:
CREATE PROCEDURE InsertTestTable
(
@id int OUTPUT,
@a AS int
)
AS
BEGIN
INSERT dbo.testTable (a) VALUES (@a);
SET @id = (SELECT CONVERT(int, current_value)
FROM sys.sequences WHERE name = 'seq_PK_tblTestTable')
END
通过将其从Sql Object Explorer拖到设计器图面上,可以将其存储到上下文中,然后将其如下所示:
下一步是单击testTable
类,然后单击Insert方法的省略号按钮(通过将存储过程添加到上下文中来启用该按钮):
并如下对其进行自定义:
就这样。 现在,LINQ-to-SQL将生成一个存储过程调用以插入一条记录,例如:
declare @p3 int
set @p3=8
declare @p5 int
set @p5=0
exec sp_executesql N'EXEC @RETURN_VALUE = [dbo].[InsertTestTable] @id = @p0 OUTPUT,
@a = @p1',N'@p0 int output,@p1 int,@RETURN_VALUE int output',
@p0=@p3 output,@p1=123,@RETURN_VALUE=@p5 output
select @p3, @p5
当然,您可能不得不怀疑要挂多久才能使用LINQ-to-SQL。 实体框架核心具有开箱即用的序列支持。 以及更多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.