Дублирование первичных ключей генерируется при вставке записи с использованием EF - PullRequest
0 голосов
/ 13 июня 2018

У меня странная проблема.когда я вставляю запись в таблицу с первичным ключом в качестве идентификатора, уже определенного, новая запись вставляется с идентификатором 1 всегда.Я заблудился относительно того, почему это происходит.Целостность теряется, если в таблице есть повторяющиеся первичные ключи.

enter image description here

это структура таблицы

enter image description here

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

это один из методов, который называется

   public async Task<MethodResult> AddPointsForPollVote(int UserId, int PollOptionId)
    {

       using (var transaction = _entities.Database.BeginTransaction())
       {
           try
           {
               var PostId = await GetPostMasterIdFromOption((int)GamificationItemType.Poll, PollOptionId);
               var PostOwner = await GetOwnerOfThePost((int)GamificationItemType.Poll, PostId);
               var OptionOwner = await GetOwnerOfThePostOptions((int)GamificationItemType.Poll, PollOptionId);
               List<int> tagIds = _entities.PollTags.Where(x => x.Id == PostId).Select(x => x.TagId).ToList();

                List<Task> lst = new List<Task>();

               if (await CheckIfDailyPointLimitExceded((int)GamificationUserActions.Poll_Vote_Points_To_User, UserId) == false) // User limit not exceeded
               {
                   // Add Daily Activity Point For User
                   var DailyActivityResultForUser = AddDailyActivityPointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_User, (int)GamificationItemType.Poll, UserId);
                   lst.Add(DailyActivityResultForUser);

                   // Add Total Redeemable Point For User
                   var TotalRedeemablePointsForUser = AddOrUpdateTotalRedeemablePointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_User, UserId);
                   lst.Add(TotalRedeemablePointsForUser);


                   // Add Total Point For User
                   var TotalPointsForUser = AddOrUpdateTotalPointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_User, UserId);
                   lst.Add(TotalPointsForUser);

                    // Add Topic Points For User
                    var TopicPointsForUser = AddOrUpdatePointsForTags((int)GamificationUserActions.Poll_Vote_Points_To_User, tagIds, UserId);
                    lst.Add(TopicPointsForUser);

                    // Add Topic points For maintaining User Level 
                    var TopicPointLevelForUser = AddOrUpdatePointsLevelForTags((int)GamificationUserActions.Poll_Vote_Points_To_User, tagIds, UserId);
                    lst.Add(TopicPointLevelForUser);

                    // Add Daily Topic points For user 
                    var DailyTopicPointLevelForUser = AddDailyTopicWisePoints((int)GamificationUserActions.Poll_Vote_Points_To_User, tagIds, UserId);
                    lst.Add(DailyTopicPointLevelForUser);
                }

               if (await CheckIfDailyPointLimitExceded((int)GamificationUserActions.Poll_Vote_Points_To_Option_Owner, OptionOwner) == false) // Option Owners limit not exceeded
               {
                   // Add Daily Activity Point to  Option Owner
                   var DailyActivityResultForOptionOwner = AddDailyActivityPointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_Option_Owner,(int)GamificationItemType.Poll,OptionOwner);
                   lst.Add(DailyActivityResultForOptionOwner);


                   // Add Total Redeemable Point to Option Owner
                   var TotalRedeemablePointsForOptionOwner = AddOrUpdateTotalRedeemablePointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_Option_Owner, OptionOwner);
                   lst.Add(TotalRedeemablePointsForOptionOwner);

                   // Add Total Point to Option Owner
                   var TotalPointsForOptionOwner = AddOrUpdateTotalPointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_Option_Owner, OptionOwner);
                   lst.Add(TotalPointsForOptionOwner);

                    // Add Topic Points For Option owner
                    var TopicPointsForOptionOwner = AddOrUpdatePointsForTags((int)GamificationUserActions.Poll_Vote_Points_To_Option_Owner, tagIds, OptionOwner);
                    lst.Add(TopicPointsForOptionOwner);

                    // Add Topic points For maintaining Option Owner Level 
                    var TopicPointLevelForOptionOwner = AddOrUpdatePointsLevelForTags((int)GamificationUserActions.Poll_Vote_Points_To_Option_Owner, tagIds, OptionOwner);
                    lst.Add(TopicPointLevelForOptionOwner);

                    // Add Daily Topic points For Option Owner 
                    var DailyTopicPointLevelForOptionOwner = AddDailyTopicWisePoints((int)GamificationUserActions.Poll_Vote_Points_To_Option_Owner, tagIds, OptionOwner);
                    lst.Add(DailyTopicPointLevelForOptionOwner);
                }


               if (await CheckIfDailyPointLimitExceded((int)GamificationUserActions.Poll_Vote_Points_To_Poll_Owner, PostOwner) == false) // Post Owners limit not exceeded
               {
                   // Add Daily Activity Point to Post Owner
                   var DailyActivityResultForPollOwner = AddDailyActivityPointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_Poll_Owner, (int)GamificationItemType.Poll,PostOwner);
                   lst.Add(DailyActivityResultForPollOwner);


                   // Add Total Redeemable Point to Post Owner
                   var TotalRedeemablePointsForPostOwner = AddOrUpdateTotalRedeemablePointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_Poll_Owner, PostOwner);
                   lst.Add(TotalRedeemablePointsForPostOwner);


                   // Add Total Point to Post Owner
                   var TotalPointsForPollOwner = AddOrUpdateTotalPointsForUser((int)GamificationUserActions.Poll_Vote_Points_To_Poll_Owner, PostOwner);
                   lst.Add(TotalPointsForPollOwner);


                    // Add Topic Points For Post owner
                    var TopicPointsForPostOwner = AddOrUpdatePointsForTags((int)GamificationUserActions.Poll_Vote_Points_To_Poll_Owner, tagIds, PostOwner);
                    lst.Add(TopicPointsForPostOwner);


                    // Add Topic points For maintaining Post Owner Level 
                    var TopicPointLevelForPostOwner = AddOrUpdatePointsLevelForTags((int)GamificationUserActions.Poll_Vote_Points_To_Poll_Owner, tagIds, PostOwner);
                    lst.Add(TopicPointLevelForPostOwner);


                    // Add Daily Topic points For Post Owner 
                    var DailyTopicPointLevelForPostOwner = AddDailyTopicWisePoints((int)GamificationUserActions.Poll_Vote_Points_To_Poll_Owner, tagIds, PostOwner);
                    lst.Add(DailyTopicPointLevelForPostOwner);
                }


               await Task.WhenAll(lst);


               transaction.Commit();

               return new MethodResult() { Success = true, Message = "Points Added !!" };
           }
           catch (Exception ex)
           {
               transaction.Rollback();
               return new MethodResult() { Success = false, Message = "There was some error !!" };
           }
       }


    }

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

 public async Task AddDailyActivityPointsForUser(int ActionId, int ItemId, int UserId)
    {

        using (var context = new Entities())
        {

            try
            {
                DailyActivityPoint dailyActivityPoint = new DailyActivityPoint()
                {
                    ActionId = ActionId,
                    CreatedDate = DateTime.Now,
                    ItemId = ItemId,
                    UserId = UserId,
                    PointsAccumulated = await GetPointsAwardedForAction(ActionId)
                };

                context.DailyActivityPoints.Add(dailyActivityPoint);
                await context.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                ErrorLog errorLog = new ErrorLog()
                {
                    CreatedDate = DateTime.Now,
                    ErrorMessage = ex.Message,
                    ModuleName = "GamificationPointsService",
                    CustomMessage = " Error while Adding Daily Activity Points For user : AddDailyActivityPointsForUser ActionId : " + ActionId + " , ItemId : " + ItemId + " , UserId : " + UserId,
                    stackTrace = ex.StackTrace
                };

                context.ErrorLogs.Add(errorLog);
                await context.SaveChangesAsync();
            }

        }


    }

Как вы можете видеть, 6 методов вызывается 3 раза внутри транзакции, и транзакция фиксируется, когда у меня естьждали их всех.Дублированный первичный ключ вставляется только для некоторых таблиц.Остальные работают нормально.Но вопрос в том, каким образом SQL позволяет дублировать первичный ключ.

Пожалуйста, ведите меня.В чем может быть проблема.Я так закодировал это [Плохая практика или что-то в этом роде, я впервые использую задачи и асинхронное программирование [newbee: p]] ??

Настольный скрипт:

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [Gamification].[DailyActivityPoints](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ActionId] [int] NOT NULL,
    [ItemId] [int] NOT NULL,
    [UserId] [int] NOT NULL,
    [PointsAccumulated] [int] NOT NULL,
    [CreatedDate] [datetime] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [Gamification].[DailyActivityPoints] ADD  DEFAULT (getdate())        FOR [CreatedDate]
GO

ALTER TABLE [Gamification].[DailyActivityPoints]  WITH CHECK ADD FOREIGN KEY([ActionId]) REFERENCES [Gamification].[ActionMaster] ([Id])
GO

ALTER TABLE [Gamification].[DailyActivityPoints]  WITH CHECK ADD FOREIGN KEY([ItemId]) REFERENCES [Gamification].[ItemType] ([Id])
GO

ALTER TABLE [Gamification].[DailyActivityPoints]  WITH CHECK ADD FOREIGN KEY([UserId]) REFERENCES [dbo].[Users] ([UserID])
GO
...