Механизмы EF Core в .NET Core для решения проблем конкурентоспособности.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Механизмы EF Core в .NET Core для решения проблем конкурентоспособности.

Сообщение Anonymous »

Я только начинаю изучать конкурентоспособную обработку в EF Core для создания согласованных приложений, и у меня есть несколько вопросов. В документации Microsoft указано следующее:

Код: Выделить всё

using var context = new PersonContext();

// Fetch a person from database and change phone number
var person = context.People.Single(p => p.PersonId == 1);
person.PhoneNumber = "555-555-5555";

// Change the person's name in the database to simulate a concurrency conflict
context.Database.ExecuteSqlRaw(
"UPDATE dbo.People SET FirstName = 'Jane' WHERE PersonId = 1");

var saved = false;

while (!saved)
{
try
{
// Attempt to save changes to the database
context.SaveChanges();
saved = true;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is Person)
{
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] = ;
}

// 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);
}
}
}
}
У меня есть этот код WeatherService:

Код: Выделить всё

public WeatherForecast UpdateMeasurementsForToday()
{
var saved = false;
var date = DateTime.Today;
var specified = DateTime.SpecifyKind(date, DateTimeKind.Utc);

while (!saved)
{
try
{
var entityFromDb = _source.GetWeatherByDate(specified);
entityFromDb.TemperatureC = Random.Shared.Next(30);

_source.UpdateEntity(entityFromDb);
saved = true;
return entityFromDb;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is WeatherForecast)
{
var proposedValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();

if (databaseValues is null)
throw new ArgumentException("Сущность была удалена");
entry.OriginalValues.SetValues(databaseValues);
entry.CurrentValues.SetValues(databaseValues);
}
else
{
throw new NotSupportedException(
"Don't know how to handle concurrency conflicts for "
+ entry.Metadata.Name);
}
}
}
}

throw new ArgumentException();
}
Код из репозитория _source:

Код: Выделить всё

public void UpdateEntity(WeatherForecast newEntity)
{
var entityFromDb = _ctx.Forecasts.First(c =>  c.Id.Equals(newEntity.Id));
entityFromDb.TemperatureC = newEntity.TemperatureC;
entityFromDb.SummaryUpdates++;
entityFromDb.Version = Guid.NewGuid();
_ctx.SaveChanges();
}
И у меня вопрос: почему при получении DbConcurrencyException мы делаем какие-то дополнительные действия, как в документации Miscrosoft?
Не могу мы просто возвращаемся и запрашиваем НОВЫЕ данные (я пробовал этот способ, и он действительно не работал должным образом, цикл бесконечно выбрасывал DbConcurrencyUpdateEx, я думаю, это связано с тем, что EF Core кэширует данные).
Другая проблема заключается в том, что нам может понадобиться ситуация, когда нам нужны предлагаемые нами значения и НОВЫЕ значения из базы данных для разрешения конфликта, поскольку наши предлагаемые значения основаны на старых, логически это выглядит так: если нам просто нужно написать

Код: Выделить всё

entry.OriginalValues.SetValues(databaseValues);
entry.CurrentValues.SetValues(databaseValues);
и вроде подсказывают новые значения.
Но в документации мы опять подробно разбираем свойства
Тоже наверное глупый вопрос со стороны, но я искренне не понимаю, почему мой тест на конкурентоспособность нестабилен:

Код: Выделить всё

public async void UpdateWeather_Updatingsimultaneously_SummaryShouldConsiderUpdateCounters()
{
var rep1 = new EfWeatherRepository(_ctx1);
var rep2 = new EfWeatherRepository(efDbInitializer.Ctx);
var weatherService1 = new WeatherService(rep1, _fakeService.Object);
var weatherService2 = new WeatherService(rep2, _fakeService.Object);
var createdEntity = weatherService1.MeasureTodayWeather();
var task1 = Task.Run(() => weatherService1.UpdateMeasurementsForToday());
var task2 = Task.Run(() => weatherService2.UpdateMeasurementsForToday());
await Task.WhenAll(task1, task2);
var result = rep1.GetEntityById(createdEntity.Id);
result.SummaryUpdates.Should().Be(2);
}
Я перехватываю конфликт, обновляю данные и загружаю объект погоды в базу данных с НОВЫМИ данными, но иногда тест не проходит, потому что количество обновлений 1 вместо 2.
Спасибо, что уделили время!
Я использовал код из документации MS

Подробнее здесь: https://stackoverflow.com/questions/785 ... ess-issues
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Ошибка Bad Gateway (502) при вызове API Core Core .NET .NET из другого API Core .NET .NET .NET .NET
    Anonymous » » в форуме C#
    0 Ответы
    4 Просмотры
    Последнее сообщение Anonymous
  • Ошибка Bad Gateway (502) при вызове API Core Core .NET .NET из другого API Core .NET .NET .NET .NET
    Anonymous » » в форуме C#
    0 Ответы
    5 Просмотры
    Последнее сообщение Anonymous
  • Механизмы обхода загрузки файлов в PHP
    Anonymous » » в форуме Php
    0 Ответы
    22 Просмотры
    Последнее сообщение Anonymous
  • Механизмы обхода загрузки файлов в PHP
    Anonymous » » в форуме Php
    0 Ответы
    33 Просмотры
    Последнее сообщение Anonymous
  • Механизмы обхода загрузки файлов в PHP
    Anonymous » » в форуме Php
    0 Ответы
    16 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»