Помогите с идеей решения проблемы, дано:
- EF Core Code first
- MS Sql Server
- ASP.Net server с асинзроннымиасинхронными запросами.
У меня есть база с данными пользователей, мне нужно поменять сразу несколько таблиц в базе для выбранного пользователя, пречемпричем данные гарантированно должны быть либо обновлены, либо не тронуты. В момент изменения данных, они могут быть запрошены пользователем в ином потоке (запросы асинзронныеасинхронные).
Проблема в следубющем :
Сейчас когда изменяются данные, для каждого конкретного пользователя используется lock(sync) lock(sync)- как способ синхронизации от двух паралельных запросов, к примеру первый запрос пишет в базу, второй читает.
Когда я обновляю базу, мне нужно обновлять ее под locklock объектом, соответственно я не могу использовать SaveChangesAsyncSaveChangesAsync(), так как его нельзя использовать под пконструкцией locklock. ТАк же я не могу обойтись без локирования, так как обновляю сразу ряд таблиц и по этому, должна быть гарантия, что пользователь не запросит случайно часть новых и часть старых данных. ВпринцепиВ принципе, все в порядке, однако процесс обновления достаточно долог, и для надежности обернут в транзакцию, из за-за чего получается что база недоступнянедоступна для всех иных пользователей данного сервиса, ведь обновление происзодитпроисходит в синхронном режиме. И если к примеру 1000 пользователей сделают запрос на обновление данных, то получается что сервис может висеть даже до часу обрабатывая эти запросы. БудублагодаренБуду благодарен, если подскажитеподскажете возможное нормальное решение проблемы.
Ниже приведен схематичный код, который элюстрируетиллюстрирует описанное:
object sync = new object()
async Task MyMethod(MyDBContext context)
{
// переключили поток но это не делает погоды так как далее идут синхронные операции и база виснет намертво для всех обращений к ней
using transaction = await context.Database.BeginTransactionAsync();
lock(sync)
{
UpdateTb1(context);
UpdateTb2(context);
UpdateTb3(context);
transaction.Commit();
}
}
void UpdateTb1(context)
{
context.Tb1.Add(VeryLongData);
context.SaveChanges();
}
void UpdateTb2(context)
{
context.Tb2.Add(VeryLongData);
context.SaveChanges();
}
void UpdateTb3(context)
{
context.Tb3.Add(VeryLongData);
context.SaveChanges();
}
Повторюсь еще раз, это лишь пример кода для эллюстрациииллюстрации проблемы, проблема в подзодеподходе к решениярешению, а не в коде, по этому не кидайтесь помидорами за то что приложенный пример не воспроизводим. Буду благодарен за предложенные решения.
Как тлько произзошлотолько произошло первое созранениесохранение данных, транзакция блокирует базу, и нени кто не может к ней достучаться.
В реальном коде, все щеееще обернуто в try - catchtry-catch, для того что бы если будет ошибка во время поерации созраненияоперации сохранения данных,она она прошла незаметно, а транзакция откатила бы изменениизменения в базе.
Помогите с идеей решения проблемы, дано:
- EF Core Code first
- MS Sql Server
- ASP.Net server с асинзронными запросами.
У меня есть база с данными пользователей, мне нужно поменять сразу несколько таблиц в базе для выбранного пользователя, пречем данные гарантированно должны быть либо обновлены либо не тронуты. В момент изменения данных, они могут быть запрошены пользователем в ином потоке (запросы асинзронные).
Проблема в следубющем : Сейчас когда изменяются данные, для каждого конкретного пользователя используется lock(sync) - как способ синхронизации от двух паралельных запросов, к примеру первый запрос пишет в базу, второй читает.
Когда я обновляю базу, мне нужно обновлять ее под lock объектом, соответственно я не могу использовать SaveChangesAsync, так как его нельзя использовать под пконструкцией lock. ТАк же я не могу обойтись без локирования, так как обновляю сразу ряд таблиц и по этому, должна быть гарантия, что пользователь не запросит случайно часть новых и часть старых данных. Впринцепи все в порядке, однако процесс обновления достаточно долог и для надежности обернут в транзакцию, из за чего получается что база недоступня для всех иных пользователей данного сервиса, ведь обновление происзодит в синхронном режиме. И если к примеру 1000 пользователей сделают запрос на обновление данных, то получается что сервис может висеть даже до часу обрабатывая эти запросы. Будублагодарен если подскажите возможное нормальное решение проблемы.
Ниже приведен схематичный код который элюстрирует описанное:
object sync = new object()
async Task MyMethod(MyDBContext context)
{
// переключили поток но это не делает погоды так как далее идут синхронные операции и база виснет намертво для всех обращений к ней
using transaction = await context.Database.BeginTransactionAsync();
lock(sync)
{
UpdateTb1(context);
UpdateTb2(context);
UpdateTb3(context);
transaction.Commit();
}
}
void UpdateTb1(context)
{
context.Tb1.Add(VeryLongData);
context.SaveChanges();
}
void UpdateTb2(context)
{
context.Tb2.Add(VeryLongData);
context.SaveChanges();
}
void UpdateTb3(context)
{
context.Tb3.Add(VeryLongData);
context.SaveChanges();
}
Повторюсь еще раз, это лишь пример кода для эллюстрации проблемы, проблема в подзоде к решения а не в коде, по этому не кидайтесь помидорами за то что приложенный пример не воспроизводим. Буду благодарен за предложенные решения.
Как тлько произзошло первое созранение данных, транзакция блокирует базу и не кто не может к ней достучаться.
В реальном коде, все щее обернуто в try - catch, для того что бы если будет ошибка во время поерации созранения данных,она прошла незаметно, а транзакция откатила бы изменени в базе.
Помогите с идеей решения проблемы, дано:
- EF Core Code first
- MS Sql Server
- ASP.Net server с асинхронными запросами.
У меня есть база с данными пользователей, мне нужно поменять сразу несколько таблиц в базе для выбранного пользователя, причем данные гарантированно должны быть либо обновлены, либо не тронуты. В момент изменения данных, они могут быть запрошены пользователем в ином потоке (запросы асинхронные).
Проблема в следубющем :
Сейчас когда изменяются данные, для каждого конкретного пользователя используется lock(sync)- как способ синхронизации от двух паралельных запросов, к примеру первый запрос пишет в базу, второй читает.
Когда я обновляю базу, мне нужно обновлять ее под lock объектом, соответственно я не могу использовать SaveChangesAsync(), так как его нельзя использовать под пконструкцией lock. ТАк же я не могу обойтись без локирования, так как обновляю сразу ряд таблиц и по этому, должна быть гарантия, что пользователь не запросит случайно часть новых и часть старых данных. В принципе, все в порядке, однако процесс обновления достаточно долог, и для надежности обернут в транзакцию, из-за чего получается что база недоступна для всех иных пользователей данного сервиса, ведь обновление происходит в синхронном режиме. И если к примеру 1000 пользователей сделают запрос на обновление данных, то получается что сервис может висеть даже до часу обрабатывая эти запросы. Буду благодарен, если подскажете возможное нормальное решение проблемы.
Ниже приведен схематичный код, который иллюстрирует описанное:
object sync = new object()
async Task MyMethod(MyDBContext context)
{
// переключили поток но это не делает погоды так как далее идут синхронные операции и база виснет намертво для всех обращений к ней
using transaction = await context.Database.BeginTransactionAsync();
lock(sync)
{
UpdateTb1(context);
UpdateTb2(context);
UpdateTb3(context);
transaction.Commit();
}
}
void UpdateTb1(context)
{
context.Tb1.Add(VeryLongData);
context.SaveChanges();
}
void UpdateTb2(context)
{
context.Tb2.Add(VeryLongData);
context.SaveChanges();
}
void UpdateTb3(context)
{
context.Tb3.Add(VeryLongData);
context.SaveChanges();
}
Повторюсь еще раз, это лишь пример кода для иллюстрации проблемы, проблема в подходе к решению, а не в коде, по этому не кидайтесь помидорами за то что приложенный пример не воспроизводим. Буду благодарен за предложенные решения.
Как только произошло первое сохранение данных, транзакция блокирует базу, и ни кто не может к ней достучаться.
В реальном коде, все еще обернуто в try-catch, для того что бы если будет ошибка во время операции сохранения данных, она прошла незаметно, а транзакция откатила бы изменения в базе.
SaveChangesAsync() + lock
Помогите с идеей решения проблемы, дано:
- EF Core Code first
- MS Sql Server
- ASP.Net server с асинзронными запросами.
У меня есть база с данными пользователей, мне нужно поменять сразу несколько таблиц в базе для выбранного пользователя, пречем данные гарантированно должны быть либо обновлены либо не тронуты. В момент изменения данных, они могут быть запрошены пользователем в ином потоке (запросы асинзронные).
Проблема в следубющем : Сейчас когда изменяются данные, для каждого конкретного пользователя используется lock(sync) - как способ синхронизации от двух паралельных запросов, к примеру первый запрос пишет в базу, второй читает.
Когда я обновляю базу, мне нужно обновлять ее под lock объектом, соответственно я не могу использовать SaveChangesAsync, так как его нельзя использовать под пконструкцией lock. ТАк же я не могу обойтись без локирования, так как обновляю сразу ряд таблиц и по этому, должна быть гарантия, что пользователь не запросит случайно часть новых и часть старых данных. Впринцепи все в порядке, однако процесс обновления достаточно долог и для надежности обернут в транзакцию, из за чего получается что база недоступня для всех иных пользователей данного сервиса, ведь обновление происзодит в синхронном режиме. И если к примеру 1000 пользователей сделают запрос на обновление данных, то получается что сервис может висеть даже до часу обрабатывая эти запросы. Будублагодарен если подскажите возможное нормальное решение проблемы.
Ниже приведен схематичный код который элюстрирует описанное:
object sync = new object()
async Task MyMethod(MyDBContext context)
{
// переключили поток но это не делает погоды так как далее идут синхронные операции и база виснет намертво для всех обращений к ней
using transaction = await context.Database.BeginTransactionAsync();
lock(sync)
{
UpdateTb1(context);
UpdateTb2(context);
UpdateTb3(context);
transaction.Commit();
}
}
void UpdateTb1(context)
{
context.Tb1.Add(VeryLongData);
context.SaveChanges();
}
void UpdateTb2(context)
{
context.Tb2.Add(VeryLongData);
context.SaveChanges();
}
void UpdateTb3(context)
{
context.Tb3.Add(VeryLongData);
context.SaveChanges();
}
Повторюсь еще раз, это лишь пример кода для эллюстрации проблемы, проблема в подзоде к решения а не в коде, по этому не кидайтесь помидорами за то что приложенный пример не воспроизводим. Буду благодарен за предложенные решения.
Как тлько произзошло первое созранение данных, транзакция блокирует базу и не кто не может к ней достучаться.
В реальном коде, все щее обернуто в try - catch, для того что бы если будет ошибка во время поерации созранения данных ,она прошла незаметно, а транзакция откатила бы изменени в базе.