Проблема, с которой я сталкиваюсь, заключается в том, что когда пользователь нажимает на рейтинг в первый раз, он выдает мне ошибку:
Не знаю, как обрабатывать конфликты параллелизма для NoSleepers.Core.Rating
в NoSleepers.Data.StoryRepository.WriteRatingForStory (Int32 storyId, Int32 userId, Int32 Score) в C: \ Users \ dough \ Desktop \ Разработка веб-сайтов \ Nosleepers \ Site \ NoSleepers.Data \ StoryRepository.cs: строка 91 в NoSleepers.Controllers.RatingsController.WriteRating (рейтинг Int32 storyId, Int32) в C: \ Users \ dough \ Desktop \ Разработка сайтов \ Nosleepers \ Site \ NoSleepers \ Controllers \ RatingsController.cs: строка 29 в Microsoft.AspNetCore. Mvc .Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute (преобразователь IActionResultTypeMapper, аргумент ObjectMethodExecutor, объектный контроллер, аргументы Object []) в Microsoft.AspNetCore. * 10ctionAgna. , ValueTask`1 actionResultValueTask) в Microsoft.Asp NetCore. Mvc .Infrastructure.ControllerActionInvoker.g__Awaited | 10_0 (вызывающий ControllerActionInvoker, задача lastTask, следующее состояние, область действия области, состояние объекта, логическое значение isCompleted) в Microsoft.AspNetCore. Mvc .Infrastructure.ControllerArowInteced.Exception.Context.ContextSuneInteSec. в Microsoft.AspNetCore. Mvc .Infrastructure.ControllerActionInvoker.Next (State & next, Scope & scope, Object & state, Boolean & isCompleted) в Microsoft.AspNetCore. Mvc .Infrastructure.ControllerActionInvoker.g__Awaited | 13_0 invakAler (для управления вызовом) Состояние следующее, область действия, состояние объекта, логическое значение isCompleted) в Microsoft.AspNetCore. Mvc .Infrastructure.ResourceInvoker.g__Awaited | 24_0 (вызов ресурса ResourceInvoker, задача lastTask, следующее состояние, область действия области, состояние объекта, логическое значение isCompleted) в корпорации Майкрософт. AspNetCore. Mvc .Infrastructure.ResourceInvoker.Rethrow (контекст ResourceExecutedContextSealed) в Microsoft.AspNetCore. Mvc .Infrastructure.ResourceInvoker.Next (состояние и следующее, область действия & scope, Object & state, Boolean & isCompleted) в Microsoft.AspNetCore. Mvc .Infrastructure.ResourceInvoker.g__Awaited | 19_0 (вызов ресурса ResourceInvoker, Task lastTask, следующее состояние, область действия Scope, состояние объекта, логическое значение isCompleted) в Microsoft.AspNetCore. Mvc .Infrastructure.ResourceInvoker.g__Awaited | 17_0 (ResourceInvoker invoker, задача Task, IDisposable scope) в Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask | 6_0 (конечная точка, конечная точка запроса, учетная запись обратного вызова. Invoke (контекст HttpContext) в Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke (контекст HttpContext) в Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke (контекст HttpContext)
* 1008 Ранее добавлен рейтинг для пользователя в базе данных вручную. Я не могу понять, что я делаю неправильно. Буду признателен за любую помощь.
EntityConfig и методы
public void Configure(EntityTypeBuilder<Story> builder)
{
builder.ToTable("Stories");
builder.HasKey(x => x.Id);
builder.HasOne(s => s.Author)
.WithMany(a => a.Stories)
.HasForeignKey(s => s.AuthorId);
builder.OwnsMany(x => x.Ratings, x =>
{
x.WithOwner().HasForeignKey(x => x.StoryId);
x.Property(x => x.Score);
x.HasKey(y => new { y.StoryId, y.UserId });
x.ToTable("Ratings");
});
builder.OwnsMany(x => x.Favorites, x =>
{
x.WithOwner().HasForeignKey(x => x.StoryId);
x.HasKey(y => new { y.StoryId, y.UserId });
x.ToTable("Favorites");
});
}
public void WriteRating(int userId, double newRating)
{
if (HasUserWrittenRating(userId))
{
Ratings.FirstOrDefault(c => c.UserId == userId && c.StoryId == this.Id).Score = newRating;
AverageRating = Ratings.Average(r => r.Score);
}
else
{
Ratings.Add(new Rating() { StoryId = this.Id, Score = newRating, UserId = userId });
AverageRating = ((AverageRating * NumberOfRatings - 1) + newRating) / NumberOfRatings;
}
}
private bool HasUserWrittenRating(int userId)
{
return Ratings.Any(rat => rat.UserId == userId);
}
public async Task WriteRatingForStory(int storyId, int userId, int score)
{
// Get the story that was rated
var story = await _dbContext.Stories.FirstOrDefaultAsync(story => story.Id == storyId);
// Updating thestory with the new rating
story.WriteRating(userId, score);
//_dbContext.Stories.Update(story);
// Save the updated story to the database
var saved = false;
while (!saved)
{
try
{
// Attempt to save changes to the database
_dbContext.SaveChanges();
saved = true;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is Story)
{
var proposedValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();
foreach (var property in proposedValues.Properties)
{
var proposedValue = proposedValues[property];
var databaseValue = databaseValues[property];
// TODO: decide which value should be written to database
// proposedValues[property] = <value to be saved>;
}
// Refresh original values to bypass next concurrency check
entry.OriginalValues.SetValues(databaseValues);
}
else
{
throw new NotSupportedException(
"Don't know how to handle concurrency conflicts for "
+ entry.Metadata.Name);
}
}
}
}
}
Рейтинговая структура базы данных (UserId, StoryId являются первичными, счет в виде числа с плавающей запятой)
Истории БД структура (Id как Primary, AuthorId, название, дата, оценка, средняя оценка, URL)