SQL Trigger пытается вставить нулевое значение, но мой код C # передает int 300? - PullRequest
4 голосов
/ 22 июля 2011

Мне нужно немного вспомнить ошибку, которую я совершил с этим триггером. Я использую слой данных LINQ to SQL в своем приложении asp.net/c#, которое вставляет данные в базу данных до того, как я добавил этот триггер.

Я знаю, что значения, передаваемые на уровень данных, совершенно корректны, так как я проверял их также в отладчике.

Я пытаюсь оценить, превышает ли расход по пробегу годовой лимит (налоговый год в Великобритании), равный 10 000, и разделить его соответственно для разных ставок претензии.

Вот мой триггер

    USE [Horizon]
GO
/****** Object:  Trigger [dbo].[trER_InsteadOf_Insert]    Script Date: 07/22/2011 12:21:44 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      Matthew Arnold
-- Create date: 19/07/2011
-- Description: Validate Expense Row for Allowed Mileage
-- =============================================
ALTER TRIGGER [dbo].[trER_InsteadOf_Insert] 
   ON  [dbo].[ExpenseRow] 
   INSTEAD OF INSERT
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @WorkerID varchar(20);
    DECLARE @ExpenseID int;
    DECLARE @Mileage int;
    DECLARE @Miles int;
    DECLARE @TotalMiles int;
    DECLARE @MilesOver10k int;
    DECLARE @MilesUnder10k int;
    DECLARE @Amount decimal (7, 2);
    DECLARE @AmountOver decimal(7, 2);
    DECLARE @ClaimedDate datetime;
    DECLARE @HighRateMileage decimal (7, 2);
    DECLARE @LowRateMileage decimal (7, 2);

    --Get current mileage and additional miles to work out threshold for worker expense
    SET @ExpenseID = (SELECT Expense_ID FROM inserted)
    SET @WorkerID = (SELECT Worker_ID FROM Expense WHERE Expense_ID = @ExpenseID)
    SET @Mileage = (SELECT Mileage FROM WorkerSettings WHERE Worker_ID = @WorkerID)
    SET @Miles = (SELECT Mileage FROM inserted)
    SET @ClaimedDate = (SELECT ExpenseDate From inserted)

    SET @HighRateMileage = (SELECT Value FROM dbo.SystemSettings WHERE ConfigType_ID = 1 
                            AND @ClaimedDate >=  StartDate
                            AND @ClaimedDate <= EndDate)
    SET @LowRateMileage =  (SELECT Value FROM dbo.SystemSettings WHERE ConfigType_ID = 2
                            AND @ClaimedDate >=  StartDate
                            AND @ClaimedDate <= EndDate)

    SET @TotalMiles = @Mileage + @Miles
    SET @MilesOver10k = @TotalMiles - 10000
    SET @MilesUnder10k = @Miles - @MilesOver10k

            IF (@Mileage < 10000)
                BEGIN
                    IF (@TotalMiles > 10000)
                        BEGIN
                            SET @AmountOver = @MilesOver10k * @LowRateMileage
                            SET @Amount = @MilesUnder10k * @HighRateMileage

                            --Split higher rate and lower rate mileage and insert two expense rows
                            INSERT INTO dbo.ExpenseRow (Expense_ID, JobNumber, ExpenseType_ID, Mileage,
                                                        ExpenseDate, Description, Amount, Notes, ClientChargeable,
                                                        VAT_Receipt, ItemAuthorised, AuthBy, 
                                                        CreatedBy, CreatedOn, ModifiedBy, ModifiedOn)

                            SELECT Expense_ID, JobNumber, ExpenseType_ID, @MilesOver10k, ExpenseDate,
                                                        Description, @AmountOver, 'Calculated at' + ' ' + @LowRateMileage + ' ' + 'pence per mile', 
                                                        ClientChargeable,
                                                        VAT_Receipt, 0, AuthBy, 
                                                        CreatedBy, CreatedOn, ModifiedBy, ModifiedOn FROM inserted



                            INSERT INTO dbo.ExpenseRow (Expense_ID, JobNumber, ExpenseType_ID, Mileage,
                                                        ExpenseDate, Description, Amount, Notes, ClientChargeable,
                                                        VAT_Receipt, ItemAuthorised, AuthBy, 
                                                        CreatedBy, CreatedOn, ModifiedBy, ModifiedOn)

                            SELECT Expense_ID, JobNumber, ExpenseType_ID, @MilesUnder10k, ExpenseDate,
                                                        Description, @Amount, 'Calculated at' + ' ' + @HighRateMileage + ' ' + 'pence per mile', 
                                                        ClientChargeable,
                                                        VAT_Receipt, 0, AuthBy, 
                                                        CreatedBy, CreatedOn, ModifiedBy, ModifiedOn FROM inserted


                        END
                    ELSE
                        BEGIN
                            --Insert higher rate into the expense row
                            INSERT INTO dbo.ExpenseRow (Expense_ID, JobNumber, ExpenseType_ID, Mileage,
                                                        ExpenseDate, Description, Amount, Notes, ClientChargeable,
                                                        VAT_Receipt, ItemAuthorised, AuthBy, 
                                                        CreatedBy, CreatedOn, ModifiedBy, ModifiedOn)

                            SELECT Expense_ID, JobNumber, ExpenseType_ID, Mileage,ExpenseDate, 
                                                        Description, Amount, 'Calculated at' + ' ' + @HighRateMileage + ' ' + 'pence per mile', 
                                                        ClientChargeable,
                                                        VAT_Receipt, 0, AuthBy, 
                                                        CreatedBy, CreatedOn, ModifiedBy, ModifiedOn FROM inserted


                        END

                END


            ELSE 

                    BEGIN
                        SET @AmountOver = @MilesOver10k * @LowRateMileage

                            --Insert lower rate mleage into the expense row
                            INSERT INTO dbo.ExpenseRow (Expense_ID, JobNumber, ExpenseType_ID, Mileage,
                                                        ExpenseDate, Description, Amount, Notes, ClientChargeable,
                                                        VAT_Receipt, ItemAuthorised, AuthBy, 
                                                        CreatedBy, CreatedOn, ModifiedBy, ModifiedOn)

                            SELECT Expense_ID, JobNumber, ExpenseType_ID, @Mileage,ExpenseDate, 
                                                        Description, @AmountOver, 'Calculated at' + ' ' + @LowRateMileage + ' ' + 'pence per mile', 
                                                        ClientChargeable,
                                                        VAT_Receipt, 0, AuthBy, 
                                                        CreatedBy, CreatedOn, ModifiedBy, ModifiedOn FROM inserted


                    END




END

Извините за вставку такого большого количества кода, но я здесь озадачен, но мой недостаток опыта явно создал эту ошибку.

Можете ли вы заметить мою проблему, как я не могу?

Спасибо

Ответы [ 3 ]

7 голосов
/ 22 июля 2011

У вас есть эта строка в вашем триггере:

SET @Mileage = (SELECT Mileage FROM WorkerSettings WHERE Worker_ID = @WorkerID)

Так что, если @WorkerID равен null или не существует, то @Mileage в конечном итоге станет null, даже есливы дали правильное значение для этого.Вот почему INSERT работает без триггера.

2 голосов
/ 22 июля 2011

Позвольте мне рассказать вам, как лучше всего разработать и отладить триггеры.

Сначала создайте шаблоны для #inserted и / или # delete '

Затем вставьте несколько записей в временные таблицы, которые будутданные, которые триггер вставил и удалил бы.Убедитесь, что вы охватили все необходимые тесты.Очень важно, чтобы у вас было несколько записей.

Затем напишите свой код, используя #inserted вместо вставленного.

Теперь вы можете выполнять шаги и проверять данные перед последним действием.Вы также можете поместить всю транзакцию в транзакцию, которую вы можете автоматически откатить, пока не получите правильный код.

Наконец, я сказал это в комментарии, но никогда не записывал триггер, предполагая, что будет обрабатываться только одна запись за раз.

Как только все будет правильно, измените имена временных таблиц на вставленные или удаленныеи добавьте код триггера создания.

1 голос
/ 22 июля 2011

Убедитесь, что значение Milage в WorkerSettings для WorkerID, связанного с вставляемым ExpenseID, не равно нулю.

...