Использование DbContext.SaveChanges () с «После вставки триггера» - PullRequest
0 голосов
/ 12 января 2020

После триггера вставки вызывает исключение при вызове dbContext.SaveChanges() Entity Framework !!

Сообщение об ошибке:

Член с идентификатором '' делает не существует в коллекции метаданных

Это мой триггерный код:

ALTER trigger [dbo].[AddAccountForCustomer] on [dbo].[Customer] after insert
as
begin

IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND  TABLE_NAME = 'Acc_Accounts'))
BEGIN
    declare @customerName nvarchar(256) = (select NameAr from inserted) 
    declare @customerID bigint = (select customerID from inserted)

    declare @serial  NCHAR(10) = (SELECT '11' + RIGHT('00000000'+ CAST(MAX(CAST(REPLACE(AccountID, '11', '') AS bigint)) + 1 AS VARCHAR(10)), 8)

    FROM [Acc_Accounts] WHERE '11' = LEFT(AccountID,2));
    select @serial

    insert into Acc_Accounts (AccountID, [Name], AccountTypeID, ParentAccountID) values ((case when @serial is null then ('1100000001') else @serial end), 
                                                                                                    @customerName, '1000000000', '1100000000');
    update [Customer] set AccountID = (case when @serial is null then ('1100000001') else @serial end) where CustomerID = @customerID;
END
end

, и это операция вставки в C# код:

private static void Add(CustomerDTO Customer)
        {
            try
            {
                using (Entities context = new Entities())
                {
                    var data = Mapper.Map<CustomerDTO, Customer>(Customer);
                    context.Customers.Add(data);
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }       

Было решение той же проблемы в stackoverflow, но с удалением триггера, есть ли решение без удаления триггера ??

1 Ответ

1 голос
/ 13 января 2020

Первое, что нужно понять при написании (после) триггеров, это то, что вам почти всегда нужно включать SET NOCOUNT ON в начале. В противном случае действие триггера может обновить, вставить или удалить строки, и это будет возвращено как часть количества строк, что заставит код вашего приложения думать, что что-то не так. Во-вторых, вы написали однострочный триггер. Вы предполагаете, что при срабатывании триггера будет затронута только одна строка. Это не тот случай. Вы должны предположить, что вы пишете триггеры, где вставленные и / или удаленные содержат несколько строк. В-третьих, вам больше не разрешается ВЫБРАТЬ данные в триггере, если вы не включите опцию, которую не должны делать. В-четвертых, больше не используйте представления информационной схемы. Используйте соответствующие системные представления, например, sys.tables.

Я переработал скелет кода, который вам нужен. Вы немного потеряли меня в сериале. Я предполагаю, что есть выражение или поиск, необходимый, где я положил ?? часть. Но этого должно быть достаточно, чтобы начать.

CREATE OR ALTER TRIGGER TR_dbo_Customer_AddAccountForCustomer
ON dbo.Customer 
AFTER INSERT
AS
BEGIN
    IF EXISTS (SELECT 1 FROM sys.tables AS t 
                        INNER JOIN sys.schemas AS s
                        ON s.schema_id = t.schema_id 
                        WHERE s.[name] = N'dbo'
                        AND t.[name] = N'Acc_Accounts')
    BEGIN
        SET NOCOUNT ON;

        INSERT INTO dbo.Acc_Accounts (AccountID, [Name], AccountTypeID, ParentAccountID)
        SELECT ??, i.NameAr, 1000000000, 1100000000
---    (SELECT '11' + RIGHT('00000000'+ CAST(MAX(CAST(REPLACE(AccountID, '11', '') AS bigint)) + 1 AS VARCHAR(10)), 8)
---    FROM [Acc_Accounts] WHERE '11' = LEFT(AccountID,2));
---    ((case when @serial is null then ('1100000001') else @serial end), 
        FROM inserted AS i;

        UPDATE c 
        SET c.AccountID = CASE WHEN ??? IS NULL 
                               THEN '1100000001'
                               ELSE ??? 
                          END 
        FROM dbo.Customers AS c
        INNER JOIN inserted AS i 
        ON i.customerID = c.CustomerID;
    END;
END;
GO
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...