2015-06-16 3 views
2

У меня есть веб-приложение ASP MVC, которое требуется для ежедневного загрузки пользователя из файла. Пользователи в базе данных должны быть соответствующим образом обновлены: удалены, если не в источнике, обновлены, если в исходном и целевом, и созданы, если только в источнике. При этом определенные права также должны автоматически предоставляться пользователям. Если есть какая-либо ошибка, ничего не должно произойти вообще.Загрузить выдержку пользователя с помощью хранимой процедуры

Сначала я попытался сделать это с помощью Entity Framework, но для вызова SaveChanges требуется около двух минут, что очень важно для относительно небольшого количества пользователей (~ 140 000).

Теперь я хочу написать хранимую процедуру, которая будет выполнять обновление. Я бы передал список новых пользователей в качестве параметра. Тип моей временной таблицы:

CREATE TYPE [dbo].[TempUserType] AS TABLE 
(
    [Uid] NVARCHAR(80) NOT NULL PRIMARY KEY, 
    [GivenName] NVARCHAR(80) NOT NULL, 
    [FamilyName] NVARCHAR(80) NOT NULL, 
    [Email] NVARCHAR(256) NOT NULL, 
    [GiveRight1] BIT NOT NULL, 
    [GiveRight2] BIT NOT NULL, 
    [GiveRight3] BIT NOT NULL 
) 

Пользователи:

CREATE TABLE [dbo].[User] (
    [Id]   INT   IDENTITY (1, 1) NOT NULL, 
    [Uid]   NVARCHAR (80) NOT NULL, 
    [GivenName] NVARCHAR (80) NOT NULL, 
    [FamilyName] NVARCHAR (80) NOT NULL, 
    [Email]  NVARCHAR (256) NOT NULL, 
    PRIMARY KEY CLUSTERED ([Id] ASC), 
    UNIQUE NONCLUSTERED ([Uid] ASC) 
); 

Роли пользователей:

CREATE TABLE [dbo].[UserRole] (
    [UserId]  INT NOT NULL, 
    [RoleId] INT NOT NULL, 
    CONSTRAINT [PK_UserRole] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC), 
    CONSTRAINT [FK_UserRole_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]), 
    CONSTRAINT [FK_UserRole_Role] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[Role] ([Id]) 
); 

процедура я застрял записывания:

CREATE PROCEDURE [dbo].[UpdateUsers] 
    @extractedUsers TempUserType READONLY 
AS 

BEGIN TRANSACTION 

MERGE 
    [dbo].[User] AS trg 
USING 
    @extractedUsers AS src 
ON 
    (trg.[Uid] = src.[Uid]) 
WHEN MATCHED THEN 
    UPDATE SET 
     trg.GivenName = src.GivenName, 
     trg.FamilyName = src.FamilyName, 
     trg.Email = src.Email 
WHEN NOT MATCHED BY TARGET THEN 
    INSERT 
     ([Uid], GivenName, FamilyName, Email) 
    VALUES 
     (src.[Uid], src.GivenName, src.FamilyName, src.Email) 
WHEN NOT MATCHED BY SOURCE THEN 
    DELETE; 


COMMIT TRANSACTION 

Мой вопрос: используется ли процедура с объединением, подходящая в этом случае для достижения улучшения производительности по сравнению с EF? Как я могу назначить роли в соответствии с 3 булевыми значениями, которые находятся в исходной таблице?

Роли могут быть закодированы, то есть я знаю, что Right1 соответствует RoleId 1, Right 2 to RoleId 2 и Right 3 to RoleId3.

+0

Cant вы используете, если еще если? –

+0

Вы имеете в виду использование if else, если внутри оператора слияния? Или вы хотите написать процедуру без слияния? – user3711864

+0

Написание storproc без слияния и просто использование if else, если –

ответ

1

После прочтения вопроса я хочу оставить идею для решения. Для меня имеет смысл иметь IF/ELSE для вызова обновления или вставки, не используя слияние, так как вам нужен UserId, который вы обновляете/вставляете, чтобы добавить его разрешения на роль.

Вы можете проверить, существует ли UId, и если это так обновить данные пользователя, если не существует, создайте и сохраните новое значение Identity.

В обоих случаях при наличии идентификатора пользователя добавить соответствующие разрешения в соответствии с булевыми значениями с помощью операторов IF.

Псевдо-код:

If UserId exists in UsersTable 
    Update 
    Store UserId 
Else 
    Insert 
    Store created UserId (using the @@IDENTITY) 

If bool1 add permission 1 
If bool3 add permission 2 
If bool3 add permission 3 
Смежные вопросы