我需要使用.net core
应用将几个值插入几个表中。
第一个表 [AI_Table]包含键,第二个表[AI_TableLanguage]包含多种语言的名称。 [AI_Table]具有IDENTITY主键,因此DB会生成它。我需要从[AI_Table]获取该密钥并将其插入[AI_TableLanguage]。
首先,我不确定获取最大密钥是正确的方法,其次,如果两个或更多用户同时访问该表怎么办?它会陷入僵局,还是什么?所以我的问题是,或者不是,这个http post操作结果如何充当一个事务,所以没有人可以中断这些插入?
总体思路:
我阅读了其他一些得到解答的问题,还阅读了Microsoft文档。我找不到使用RAW SQL的任何答案。另外,我找不到整个IActionResult是否充当单个事务。
[HttpPost, ActionName("Create")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(IzvorDropDown IzvorDropDown, InstitucijaDropDown InstitucijaDropDown, UpitTabeleCreate UpitTabeleCreate)
{
//insert
await context.Database.ExecuteSqlCommandAsync($"INSERT INTO AI_Table (IAICode, VOD, VDO, user_insert, user_update, date_insert, date_update) VALUES ({IzvorDropDown.IAIcode},{UpitTabeleCreate.VOD},{UpitTabeleCreate.VDO},{TrenutniKorisnik},{TrenutniKorisnik},{TrenutnoVreme},{TrenutnoVreme})");
//get max key
var item = await context.NextIAITableCodeGenerator.FromSql($"SELECT ISNULL(MAX(IAITableCode), 0) AS NextIAIcode FROM AI_Table").ToListAsync();
int IAITableCode = item[0].NextIAIcode;
//insert continue
await context.Database.ExecuteSqlCommandAsync($"INSERT INTO AI_TableLanguage (IAITableCode, LanguageID, TableName) VALUES ({IAITableCode},1,{UpitTabeleCreate.TableNameCyr})"); //cirilica - radi
await context.Database.ExecuteSqlCommandAsync($"INSERT INTO AI_TableLanguage (IAITableCode, LanguageID, TableName) VALUES ({IAITableCode},2,{UpitTabeleCreate.TableNameLat})"); //latinica
await context.Database.ExecuteSqlCommandAsync($"INSERT INTO AI_TableLanguage (IAITableCode, LanguageID, TableName) VALUES ({IAITableCode},3,{UpitTabeleCreate.TableNameEng})"); //engleski
return RedirectToAction(nameof(Index));
}
代码本身有效。它可以正确地插入数据库,但是当有许多用户试图同时访问这些表时,我不知道它是否会继续这样做。
答案 0 :(得分:1)
您正确地认为这将导致并发问题。
使用存储过程并搜索如何使用FormResponse
答案 1 :(得分:1)
数据库在提交日志上工作。并且在每次提交中,数据库都会检查记录(或序列)的最终版本(状态)以及提交日志本身提供的版本号,如果这些信息之间存在不一致,您可能会遇到类似“的异常自您启动以来,其他用户已更改记录”。因此,重要的是使用单次提交使这些(在一个事务中相互关联)插入/更新/删除操作。这样您就可以使用数据库的一致性机制,并可以确保在任何负载情况下代码的行为。
答案 2 :(得分:0)
一种100%确定获得正确身份的方法是使用OUTPUT子句documentation
在此示例中,FieldID
是表TableXYZ的IDENTITY
存储过程示例:
USE [DataBaseX]
GO
IF OBJECT_ID('spTableXYZAdd') IS NOT NULL
DROP PROC spTableXYZAdd
GO
CREATE PROCEDURE dbo.spTableXYZAdd
@FieldOne int,
@FieldTwo int,
@FieldThree DateTime,
@ReturnIdentityValue int OUTPUT
AS
BEGIN
DECLARE @TempTableXYZ table ( TempID int )
INSERT INTO TableXYZ (FieldOne,FieldTwo,FieldThree)
OUTPUT INSERTED.FieldID into @TempTableXYZ
VALUES (@FieldOne,@FieldTwo,@FieldThree)
SELECT @ReturnIdentityValue = (SELECT TempID FROM @TempTableXYZ)
END
GO
您的代码将如下所示:
public static int AddSomeRecord(RecordClass oRecordObj)
{
int iRetVal = 0;
using (SqlConnection conn = Connection.GetConnection())
{
using (SqlCommand cmd = new SqlCommand("spTableXYZAdd", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@FieldOne", oRecordObj.FieldOne);
cmd.Parameters.AddWithValue("@FieldTwo", oRecordObj.FieldTwo);
cmd.Parameters.AddWithValue("@FieldThree", oRecordObj.FieldThree);
cmd.Parameters.Add("@ReturnIdentityValue", SqlDbType.Int).Direction = ParameterDirection.Output;
conn.Open();
cmd.ExecuteNonQuery();
iRetVal = Convert.ToInt32(cmd.Parameters["@ReturnIdentityValue"].Value);
}
}
return iRetVal;
}