Entity Framework и копирование 100 строк одновременно - PullRequest
0 голосов
/ 08 октября 2019

Я пишу своему первому работнику сервиса, который обрабатывает копирование всех записей из одной таблицы в другую каждые 60 секунд. На данный момент все работает как чудо, но после развертывания я не хочу быть уверенным, что все будущие данные будут скопированы за 100 записей за один раз, пока не останется больше записей для копирования - и перерыв 60 секунд.

Код проверки будет копировать каждую запись с заданной даты сразу, а затем ждать 60 секунд.

 public void CopyLatestData(DateTime from)
    {
        using (var context = new EdDbContext())
        {
            var dataToCopy = context.ELMAH_Errors.Where(x => x.TimeUtc > from).ToList();

            var result = dataToCopy.Select(x => new parsed_errors(x)).ToList();

            context.parsed_errors.AddRange(result);
            context.SaveChanges();
        }
    }

Вот как я обрабатываю таймер

  private static void startTimer()
    {
        if (timer == null)
        {
            timer = new Timer();
            timer.Interval = 60 * 1000;
            timer.Elapsed += timer_ElapsedActions;
            timer.Start();
        }
    }

    private static void timer_ElapsedActions(object sender, ElapsedEventArgs e)
    {
        if (isTaskAlreadyRunning)
        {
            return;
        }
        lock (locker)
        {
            if (!isTaskAlreadyRunning)
            {
                isTaskAlreadyRunning = true;
                try
                {
                    copyDataFromRemoteDatabaseToLocalDatabase();
                    parseCopiedData();                      
                }
                finally
                {
                    isTaskAlreadyRunning = false;
                }
            }
        }

, что является самым простым способомдобиться того, что мне нужно?

Ответы [ 3 ]

1 голос
/ 08 октября 2019

мое предложение было бы добавить логическое значение в вашей сущности, например AlreadyCopied или IsCopied. Затем используйте это в качестве маркера.

public bool CopyLatestData()
{
    using (var context = new EdDbContext())
    {
        var query = context.ELMAH_Errors.Where(x => !x.IsCopied).AsQueryable();
        //if (query.Any())
        if (query.Count() != 0) //this will check if some are left not copied
        {
            var dataToCopy = query.Take(100).ToList(); //this will only take the first 100
            var result = dataToCopy.Select(x => new parsed_errors(x)).ToList();

            context.parsed_errors.AddRange(result);
            dataToCopy.ForEach(x => x.IsCopied = true); //this will update the records to IsCopied = true
            context.SaveChanges();
            if (query.Any())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
}

, затем в таймере остановки таймера, если значение bool if (Copylatestdata() == false)

private static void timer_ElapsedActions(object sender, ElapsedEventArgs e)
{
    var stillHasRecords = CopyLatestData();
    if (!stillHasRecords)
    {
        Timer timer = (Timer)sender; //get the sender object
        timer.Stop(); // stop the sender
    }
}
0 голосов
/ 08 октября 2019

Альтернативой «IsProcessed» было бы сохранение «latestProcessed» и последующее извлечение записей, которые имеют временные метки после этого, партиями по 100.

(Что-то вроде приведенного ниже кода, извините за плохое форматирование, янабираю на телефоне)

while( keepGoing) {
var dataToCopy = context.ELMAH_Errors
       .Where(x => x.TimeUtc > from)
       .Where(x => x.TimeUTc > lastProcessedUtc)
       .Take(100)
       .OrderBy( x => x.TimeUtc)
       .ToList();

(...)
if( dataToCopy.Any() ) lastProcessedUtc = data.Last().TimeUtc;
keepGoing = dataToCopy.Any(); //Or .Count()  == 100
0 голосов
/ 08 октября 2019

Вы можете попробовать использовать .Take (), чтобы ограничить количество строк, возвращаемых запросом, таким образом каждые 60 секунд он будет возвращать максимум 100 записей. Если присутствует менее 100 записей, он вернет только то, что есть.

var dataToCopy = context.ELMAH_Errors.Where(x => x.TimeUtc > from).Take(100).ToList();
...