Прежде всего, позвольте мне сказать, что я новичок в развивающемся мире.Я начинал как стажер около месяца назад, поэтому есть большая вероятность, что я не смогу правильно объяснить себя.За это я прошу прощения.
Теперь вот проблема: я пишу набор конечных точек для API с использованием C # и Entity Framework Core.В принципе, фильтрация должна быть установлена на уровне базы данных, поэтому мы используем RLS для этого.Для этого я написал следующий предикат и политику:
USE [DBO]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [sec].[RestrictApplicationsByUser](@ApplicationId int)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS RestrictApplicationsByUserResult
WHERE
@ApplicationId IN (SELECT
ApplicationId
FROM
[usr].[UserApplications]
WHERE
UserId = CAST(SESSION_CONTEXT(N'UserId') AS uniqueidentifier))
OR SESSION_CONTEXT(N'UserId') IS NULL;
GO
И
USE [DBO]
GO
CREATE SECURITY POLICY [sec].[FilterApplicationByUser]
ADD FILTER PREDICATE [sec].[RestrictApplicationsByUser]([ApplicationId]) ON [app].[Applications]
WITH (STATE = ON, SCHEMABINDING = ON)
GO
Таблицы установлены следующим образом:
[app].[Applications]
имеет ApplicationId
и Name
в качестве столбцов, а [usr].[UserApplications]
имеет UserId
и ApplicationId
в качестве столбцов.
Идея заключается в том, что всякий раз, когда пользователь запрашивает таблицу [app].[Applications]
, он будет видеть только эти приложения.он управляет (это соотношение установлено в таблице [usr].[UserApplications]
).Насколько я могу сказать, это работает.
Теперь проблема в том, что вставка новой записи в [app].[Applications]
вместе с ее связью в таблице [usr].[UserApplications]
приводит к ошибке сервера 500.
При использовании SQL Profiler я замечал, что всякий раз, когда SQL Server ProfilerЯ пытаюсь сделать POST-запрос, эти два запроса выполняются в следующем порядке:
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [app].[Applications] ([Name])
VALUES (@p0);
SELECT [ApplicationId]
FROM [app].[Applications]
WHERE @@ROWCOUNT = 1 AND [ApplicationId] = scope_identity();
',N'@p0 nvarchar(2000)',@p0=N'test''
go
И
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [usr].[UserApplications] ([UserId], [ApplicationId])
VALUES (@p1, @p2);
',N'@p1 uniqueidentifier,@p2 int',@p1='<user_guid>',@p2=<PK_value>
go
Мой недостаток опыта требует, чтобы первый запрос был атомарной операцией,таким образом, когда он пытается выбрать ApplicationId
, если происходит сбой, поскольку между ним и запрашивающим пользователем нет существующей связи, поскольку он еще не был создан (это будет второй запрос).После прочтения немного кажется, что этот конкретный SELECT выполняется Entity Framework для получения следующего доступного идентификатора на столе.
Если вы все еще со мной, и то, что я понял, правильно, я считаю,что у меня проблемы с курицей или яйцом.
Это что-то, что можно исправить?Если так, где я должен искать корень проблемы?Политика RLS?Мой код API?
Большое спасибо за любые подсказки или советы, которые вы можете мне дать.