【问题标题】:Nhibernate won't delete rows while table has trigger当表有触发器时,Nhibernate 不会删除行
【发布时间】:2013-08-01 10:19:41
【问题描述】:

我有以下 SQL Server 表:

CREATE TABLE [dbo].[Logins](
    [LoginID] [int] IDENTITY(1,1) NOT NULL,
    [AbonnementID] [int] NOT NULL,
    [Zeitpunkt] [datetime] NULL,
    [IPAdresse] [nvarchar](255) NULL,
    [IstLogout] [bit] NULL,
 CONSTRAINT [PK_Logins] PRIMARY KEY CLUSTERED 
(
[LoginID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,     
ALLOW_ROW_LOCKS      =     ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Logins]  WITH CHECK ADD  CONSTRAINT [FK_Logins_Abonnements] FOREIGN([AbonnementID])
REFERENCES [dbo].[Abonnements] ([AbonnementID])
GO

ALTER TABLE [dbo].[Logins] CHECK CONSTRAINT [FK_Logins_Abonnements]
GO

因此我创建了一个触发器来写入 ChangeLog:

CREATE TRIGGER [dbo].[LoginsChangeLog]
ON [dbo].[Logins]
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    DECLARE @LoginID INT
    DECLARE @TypID INT

    SET @TypID = (SELECT ChangeLogTables.ChangeLogTableID FROM ChangeLogTables WHERE ChangeLogTable = 'Logins')
    IF EXISTS(SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted)
    BEGIN
        SET @LoginID = (SELECT inserted.LoginID FROM inserted)
        INSERT INTO ChangeLog(ChangeLogTableID,ChangeLogTypeID,PrimaryKey) VALUES(@TypID,1, @LoginID)
    END

    IF EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted)
    BEGIN
        SET @LoginID = (SELECT inserted.LoginID FROM inserted)
        INSERT INTO ChangeLog(ChangeLogTableID,ChangeLogTypeID,PrimaryKey) VALUES(@TypID,2, @LoginID)
    END

    IF NOT EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted)
    BEGIN
        SET @LoginID = (SELECT deleted.LoginID FROM deleted)
        INSERT INTO ChangeLog(ChangeLogTableID,ChangeLogTypeID,PrimaryKey) VALUES(@TypID,3, @LoginID)
    END
END

向表中添加行没问题,触发器成功完成,但是当我尝试使用 Nhibernate-Framework 删除表时出现异常:

无法执行更新查询[SQL:从登录中删除 AbonnementID=?和时代朋克

这是我的 C# 代码:

    public void Cleanup(long Id, DateTime time)
    {
        var hqlBuilder = new StringBuilder();

        hqlBuilder.Append("DELETE Login AS login");
        hqlBuilder.Append(" WHERE login.Abonnement.AbonnementId = :Id");
        hqlBuilder.Append(" AND login.Zeitpunkt < :time ");


        CurrentSession.CreateQuery(hqlBuilder.ToString())
            .SetParameter("Id", Id)
            .SetParameter("time", time)
            .ExecuteUpdate();

    }

如果我删除我的触发器一切正常,但触发器必须完成他的工作并写入我的变更日志表

【问题讨论】:

    标签: c# sql sql-server nhibernate triggers


    【解决方案1】:

    您的触发器已损坏,因为它假定 inserteddeleted 仅包含一行。实际上,它们可能包含 0、1 或多行。您需要编写一个触发器来处理所有这些可能性。比如:

    INSERT INTO ChangeLog(ChangeLogTableID,ChangeLogTypeID,PrimaryKey)
    SELECT clt.ChangeLogTableID,
       CASE WHEN i.LoginID is not null and d.LoginID is not null THEN 2
            WHEN i.LoginID is not null THEN 1
            ELSE 3 END,
       COALESCE(i.LoginID,d.LoginID)
    FROM
       ChangeLogTables clt
          cross join
       (inserted i
          full outer join
       deleted d
          on
             i.LoginID = d.LoginID)
    WHERE
       clt.ChangeLogTable = 'Logins'
    

    应该更换整个触发器体。

    【讨论】:

    • 非常好,非常感谢,但它可以很好地插入和更新,但如果我删除行,它不会用 TypeID 3 和 TableID 填充 ChangeLogTable。
    • @gangfish - 小错误 - 我需要将 () 外连接括起来,以便 cross join 将其作为一个整体。我现在添加了括号(第 9 行和第 13 行)
    猜你喜欢
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多