Есть база SQLite, с таблицами - Messages
и Users
. Содержит примерно 100 000 пользователей.
Нужно добавлять / обновлять сообщения, и пользователей, которые сделали репосты. На каждые 100 сообщений приходится ~6000 репостнувших пользователей. Сейчас на добавление 1 сообщения (в котором ~300 репостов), если всех репостнувших пользователей еще нет в базе, уходит ~14 секунд (это нормально?).
Делаю так:
using (AppDbContext db = new AppDbContext())
{
// Получаем всех пользователей, чтобы сравнивать с репостнувшими пользователями
usersFromDb = db.Users.ToList();
/*****
Т.к. пользователей в базе много, получение всех пользователей не оптимально.
Но лучше ли будет делать много запросов (для каждого пользователя), вместо этого одного?
*****/
}
using (AppDbContext db = new AppDbContext())
{
foreach (var message in messages)
{
if (message.RepostUsers != null)
{
// Проходим по списку репостнувших пользователей
/*****
Эта часть занимает много времени
Можно ли оптимизировать?
*****/
foreach (var user in message.RepostUsers)
{
// Ищем по пользователям из базы
var dbUser = usersFromDb.Find(u => u.Id == user.Id);
if (dbUser == null)
{
// Если не нашли, помечаем новым
db.Entry(user).State = EntityState.Added;
}
else if (dbUser.Name != user.Name)
{
// Если нашли и есть изменения, помечаем измененным
db.Entry(user).State = EntityState.Modified;
}
else
{
// Если нашли и изменений нет, помечаем не измененным
db.Entry(user).State = EntityState.Unchanged;
}
}
}
// Получаем Message из базы
var dbMessage = db.Messages.AsNoTracking().FirstOrDefault(p => p.Id == message.Id);
// Message всегда либо новое, либо измененное. Помечаем
db.Entry(message).State = dbMessage != null ? EntityState.Modified : EntityState.Added;
}
db.Messages.AddRange(messages);
db.SaveChanges();
}
Вопрос 1.
Т.к. пользователей в базе много, получение всех пользователей не оптимально. Но лучше ли будет делать много запросов (отдельно для каждого репостнувшего пользователя), вместо одного?
Вопрос 2.
Когда меняю у пользователей состояния через db.Entry(user).State
, объекты помещаются в кэш для отслеживания изменений? Т.е. AsNoTracking
не учитывается? Если так, нужно ли это изменить и как?
Отвечаю только на вопрос по оптимизации. Вы каждый раз перебираете usersFromDb в поисках Id. Для таких целей надо использовать словарь. Вот код:
Dictionary<int,User> usersFromDb;
...
usersFromDb = db.Users.ToDictionary(x=>x.Id, x=>x);
...
// Ищем по пользователям из базы
if (usersFromDb.ContainsKey(userId))
{
var dbUser = usersFromDb[userId];
...
Словарь позволяет совершать поиск за постоянное время O(1). В то время как поиск по листу происходит за линейное время O(n).
Рассмотри вариант с PostgreSQL, потому что SQLite - реляционная БД. Не вдаюсь в подробности. С одной стороны просто, но чем больше записей в БД, тем тяжелее запросы. Увеличь число записей в два раза в своей БД и посмотришь, стоит ли работать дальше с ней.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Как сделать так, чтобы перемещение формы осуществлялось не только за верхнюю границу, а за любую часть данной формы?
Форма и код который я пишу находиться в разных папках Код(в папке нет той формы который указываю):
Можно ли при нажатии на "Esc" переместить плавно форму в верхний левый угол рабочего экрана? Это как перетащить мышьюСпасибо
Не могу загрузить изображение в БДВыдает ошибку "Необходимо загрузить изображение", то есть он уже выдает ошибку в первом условии следующего...