.Net SqlDataAdapter 和 SQL Server 中的触发器

Posted

技术标签:

【中文标题】.Net SqlDataAdapter 和 SQL Server 中的触发器【英文标题】:.Net SqlDataAdapter and triggers in SQL Server 【发布时间】:2014-11-25 02:25:13 【问题描述】:

我在 SQL Server 中使用了一个触发器,该触发器在 SQL Server Management Studio 的查询窗口中执行查询时按要求工作。触发器的目标是从一个表中获取最新值(其中一个 id 对应于插入的 id)并将该值添加到插入的行中。

我还在 C# 中使用DataAdapter 与具有触发器的同一个数据库进行交互。当我使用MyAdapter.update(MyDataTable) 将新值插入到触发器分配到的表中时,触发器不会执行。

我做了很多谷歌搜索,但似乎没有其他人有这个问题,所以我想我错过了一些基本的东西。我对与.Net 的数据库交互也是新手。数据适配器正常工作(即根据需要插入和更新),但不触发触发器。

以下是我的 C# 代码和触发器的一些摘录。

CREATE TRIGGER getLatestCap 
ON  TestIDTable 
AFTER insert
AS 
BEGIN
    SET NOCOUNT ON;

    DECLARE @BID INT;
    DECLARE @Date Date;

    SET @BID = (SELECT BattID FROM inserted);
    SET @Date = (SELECT Test_Date FROM inserted);

    SELECT M_Cap, Cap_Date
    INTO #tempTable
    FROM CapDataTable
    WHERE BattID = @BID;

    -- Set the Test_Cap entry in TestIDTable to that capacity. 
    UPDATE TestIDTable 
    SET Test_Cap = (SELECT M_Cap
                    FROM #tempTable
                    WHERE Cap_Date = (SELECT max(Cap_Date)
                                      FROM #tempTable))
    WHERE BattID = @BID AND Test_Date = @Date;
END
GO

private void Setup()

        try
        
            string BattSelect = "SELECT * FROM " + tbl;
            dt = new DataTable();
            Adpt = new SqlDataAdapter(BattSelect, ConnectionStr);
            builder = new SqlCommandBuilder(Adpt);
            Adpt.Fill(dt);
        
        catch (Exception e)
        
            MessageBox.Show("While Connecting to "+tbl+": " + e.ToString());
        
    

    private void UpdateDB()
    
        try
        
            Adpt.InsertCommand = builder.GetInsertCommand();
            Adpt.UpdateCommand = builder.GetUpdateCommand();
            Adpt.Update(dt);
        
        catch (Exception e)
        
            MessageBox.Show("While Updating " + tbl + ": " + e.ToString());
        
    

问题摘要:触发器在 SQL Server 中有效,但在使用数据适配器时会触发(也不报错)。

感谢您的宝贵时间和帮助!

马文

【问题讨论】:

提示:inserteddeleted 是表,因此它们可以表示集合操作的结果。假设触发器总是包含一行,而设计触发器通常是一个糟糕的计划。如果您绝对确定不会超过一行,那么添加对行数的检查并使用RaIsError 明确告知后来出现的人他们已尝试执行不可接受的说法。 (if ( select Count(*) from inserted ) > 1 RaIsError( 'FooTable_Insert: No more than one row may be processed.', 25, 42 ) with log) 感谢您的回答。在对触发器的一对多插入问题进行一些研究之后,我非常确定重新编写触发器以处理多个插入将解决我的问题。累了我会再发一次。 【参考方案1】:

按照 HABO 的提示(在原始帖子下方),我修改了触发器以适用于多个插入的行。这解决了我的问题。新的触发代码如下:

 CREATE TRIGGER getLatestCap
    ON TestIDTable
    AFTER insert
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE TestIDTable 
    set Test_Cap = M_Cap
    FROM 
        (SELECT C.BattID, Test_Date, M_Cap
        FROM 
            (SELECT t.BattID, t.M_Cap, t.Cap_Date 
            FROM CapDataTable t
            INNER JOIN(
                SELECT BattID, max(Cap_Date) as Latest
                FROM CapDataTable
                GROUP BY BattID
            ) tm on t.BattID = tm.BattID and t.Cap_Date = tm.Latest)

         C INNER JOIN inserted I
            on C.BattID = I.BattID) as t1
        INNER JOIN TestIDTable as t2
        on  t1.BattID = t2.BattID AND t1.Test_Date = t2.Test_Date
END
GO

感谢您的帮助!

【讨论】:

【参考方案2】:

您在 INSERT 之后触发了触发器。使用 SQLDataAdapter,您正在执行 UPDATE。这是两种截然不同的交易类型。

尝试将触发器设置为 ON UPDATE。这应该可以解决问题。

【讨论】:

感谢您的回答。 1. 为了理解,adapter.update() 可以根据数据表中所做的更改执行任何 INSERT、DELETE 或 UPDATE。不是这样吗? 2.我确实尝试使用ON UPDATE而不是ON INSERT,这并没有解决问题。 是的,没错,我没有看到你也添加了插入命令。

以上是关于.Net SqlDataAdapter 和 SQL Server 中的触发器的主要内容,如果未能解决你的问题,请参考以下文章

SqlDataAdapter.Fill 方法不会给出任何错误,但也不会返回任何数据以用于长时间运行的查询 ado.net core SQL Server

SqlDataAdapter.Fill 运行 SQL 命令两次

如何从 VB.NET 的视图中获取 SQL 查询

SqlDataAdapter概述

C#中SqlDataAdapter的使用小结

ASP.NET + SqlDataAdapter 没有返回正确的查询结果