首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在单个事务中执行多个原始SQL命令?

如何在单个事务中执行多个原始SQL命令?
EN

Stack Overflow用户
提问于 2019-07-25 13:18:42
回答 3查看 1.7K关注 0票数 0

我需要使用.net core应用程序将几个值插入到几个表中。

第一个表 AI_Table包含键,第二个表AI_TableLanguage包含多个语言的名称。AI_Table具有标识主键,所以DB生成它。我需要从AI_Table获取该密钥并将其插入到AI_TableLanguage中。

首先,我不确定获取最大键是否是正确的方法,其次,如果两个或多个用户同时接近这个表,怎么办?会陷入僵局还是怎样?所以我的问题是,如果没有,这个http post操作结果如何能够充当一个事务,所以没有人可以中断这些插入?

一般想法:

  • 插入到表格中。
  • 获取该PK并将其插入AI_TableLanguage三次。

我读了很少的其他问题得到了答案,也阅读了微软的文档。我找不到任何使用原始SQL的答案。另外,我无法找到整个IActionResult是否充当单个事务。

代码语言:javascript
运行
复制
[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));
}

代码本身是有效的。它正确地插入到DB中,但当有许多用户同时访问这些表时,我不知道它是否会继续这样做。

EN

回答 3

Stack Overflow用户

发布于 2019-07-25 13:28:01

您认为这将导致并发问题是正确的。

使用存储过程并搜索如何使用SCOPE_IDENTITY

票数 1
EN

Stack Overflow用户

发布于 2019-07-25 13:30:07

数据库在提交日志上工作。在每次提交中,数据库都会检查记录(或序列)的最终版本(状态)和提交日志本身提供的版本号,如果这些信息之间存在不一致的情况,您可能会采取一个异常,例如“此记录自启动以来已被另一个用户更改”。因此,使用单个提交使这些操作(在一个事务中相互关联)插入/更新/删除操作非常重要。这样,您就可以使用数据库的一致性机制,并确保代码在任何加载情况下的行为。

票数 1
EN

Stack Overflow用户

发布于 2019-07-25 13:52:30

确保获得正确标识的一种方法是使用OUTPUT子句文档

在本例中,FieldID是表TableXYZ的标识键。

存储示例:

代码语言:javascript
运行
复制
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

您的代码如下所示:

代码语言:javascript
运行
复制
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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57202909

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档