У меня странная проблема.когда я вставляю запись в таблицу с первичным ключом в качестве идентификатора, уже определенного, новая запись вставляется с идентификатором 1 всегда.Я заблудился относительно того, почему это происходит.Целостность теряется, если в таблице есть повторяющиеся первичные ключи.
это структура таблицы
Это проблема, возникающая из-за различных контекстов внутри транзакции.Я вставляю точки в разные таблицы по разным действиям пользователя.Таким образом, за одно действие несколько пользователей могут получить очки, которые будут вставлены в несколько таблиц, а для сохранения очков я создал несколько задач.
это один из методов, который называется
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