YEAR()
- это функция mysql , вы должны использовать whereRaw()
для запроса этого. Например:
->whereRaw('YEAR(docdate) = 2019')
Обновление:
Для вашей части whereIn()
вы должны сделать два запроса, по одному для каждого столбца. Таким образом, вам нужно будет получить правильные значения из массива. Это можно сделать с помощью array_map
.
Например:
->whereIn('comp', array_map(function($cat) { return $cat['comp']; }, $categories))
->whereIn('cus', array_map(function($cat) { return $cat['cus']; }, $categories))
Боюсь, что это хорошо известная ошибка / особенность класса FileSystemWatcher
. Это из документации класса:
В определенных ситуациях вы можете заметить, что одно событие создания генерирует несколько событий Created, которые обрабатываются вашим компонентом. Например, если вы используете компонент FileSystemWatcher для отслеживания создания новых файлов в каталоге, а затем тестируете его с помощью Блокнота для создания файла, вы можете увидеть два события Created, сгенерированных, даже если был создан только один файл. Это связано с тем, что в процессе записи Блокнот выполняет несколько действий с файловой системой. Блокнот записывает на диск пакетами, которые создают содержимое файла, а затем атрибуты файла. Другие приложения могут работать таким же образом. Поскольку FileSystemWatcher отслеживает действия операционной системы, все события, запускаемые этими приложениями, будут захвачены.
Теперь этот фрагмент текста относится к событию Created
, но то же самое относится и к другим файловым событиям. . В некоторых приложениях вы можете обойти это, используя свойство NotifyFilter
, но мой опыт показывает, что иногда вам также нужно выполнить некоторую ручную дублирующую фильтрацию (хаки).
Некоторое время назад Я добавил в закладки страницу с несколькими советами FileSystemWatcher . Вы можете проверить это.
В некоторых приложениях вы можете обойти это, используя свойство NotifyFilter
, но мой опыт говорит, что иногда вам также необходимо вручную выполнить фильтрацию дубликатов (хаки).
Некоторое время назад Я добавил в закладки страницу с несколькими советами FileSystemWatcher . Вы можете проверить это.
В некоторых приложениях вы можете обойти это, используя свойство NotifyFilter
, но мой опыт показывает, что иногда вам также нужно выполнить некоторую ручную дублирующую фильтрацию (хаки).
Некоторое время назад Я добавил в закладки страницу с несколькими советами FileSystemWatcher . Вы можете проверить это.
Я изменил способ отслеживания файлов в каталогах. Вместо использования FileSystemWatcher я опрашиваю местоположения в другом потоке, а затем смотрю на LastWriteTime файла.
DateTime lastWriteTime = File.GetLastWriteTime(someFilePath);
Используя эту информацию и сохраняя индекс пути к файлу и его последнее время записи, я могу определить файлы, которые были изменены или которые имеют был создан в определенном месте. Это избавляет меня от странностей FileSystemWatcher. Основным недостатком является то, что вам нужна структура данных для хранения LastWriteTime и ссылки на файл, но она надежна и проста в реализации.
Вы можете попробовать открыть это для записи, и в случае успеха вы можете предположить, что другое приложение завершило работу с файлом.
private void OnChanged(object source, FileSystemEventArgs e)
{
try
{
using (var fs = File.OpenWrite(e.FullPath))
{
}
//do your stuff
}
catch (Exception)
{
//no write access, other app not done
}
}
Кажется, что простое открытие его для записи не вызывает измененное событие. Так что это должно быть безопасно.
Я "исправил" эту проблему, используя следующую стратегию в моем делегате:
// fsw_ is the FileSystemWatcher instance used by my application.
private void OnDirectoryChanged(...)
{
try
{
fsw_.EnableRaisingEvents = false;
/* do my stuff once asynchronously */
}
finally
{
fsw_.EnableRaisingEvents = true;
}
}
Любые дублирующиеся OnChanged
события от FileSystemWatcher
можно обнаружить и отбросить, проверив File.GetLastWriteTime
временную метку для данного файла. Например:
DateTime lastRead = DateTime.MinValue;
void OnChanged(object source, FileSystemEventArgs a)
{
DateTime lastWriteTime = File.GetLastWriteTime(uri);
if (lastWriteTime != lastRead)
{
doStuff();
lastRead = lastWriteTime;
}
// else discard the (duplicated) OnChanged event
}
Мой сценарий таков: у меня есть виртуальная машина с сервером Linux на ней. Я разрабатываю файлы на хосте Windows. Когда я изменяю что-то в папке на хосте, я хочу, чтобы все изменения загружались, синхронизировались на виртуальный сервер через Ftp. Вот как я устраняю дублирующее событие изменения при записи в файл (что отмечает папку, содержащую файл, как измененную) :
private Hashtable fileWriteTime = new Hashtable();
private void fsw_sync_Changed(object source, FileSystemEventArgs e)
{
string path = e.FullPath.ToString();
string currentLastWriteTime = File.GetLastWriteTime( e.FullPath ).ToString();
// if there is no path info stored yet
// or stored path has different time of write then the one now is inspected
if ( !fileWriteTime.ContainsKey(path) ||
fileWriteTime[path].ToString() != currentLastWriteTime
)
{
//then we do the main thing
log( "A CHANGE has occured with " + path );
//lastly we update the last write time in the hashtable
fileWriteTime[path] = currentLastWriteTime;
}
}
В основном я создаю хэш-таблицу для хранения информации о времени записи файла. Затем, если в хэш-таблице есть измененный путь файла, и его значение времени совпадает с текущим уведомленным изменением файла, я знаю, что это дубликат события и игнорирую его.
Вот другой подход. Вместо того, чтобы распространить первое событие быстрой последовательности событий и подавить все, что следует, теперь все подавлены кроме от последнего. Я думаю, что сценарии, которые могут извлечь выгоду из этого подхода, более распространены.
, Чтобы заставить это произойти мы должны использовать скользящую задержку. Каждое входящее событие отменяет таймер, который запустил бы предыдущее событие и перезапускает таймер. Это открывает возможность, что бесконечная серия событий задержит распространение навсегда. Для хранения вещей простыми нет никакого условия для этого аварийного случая в дополнительных методах ниже.
public static class FileSystemWatcherExtensions
{
public static IDisposable OnAnyEvent(this FileSystemWatcher source,
WatcherChangeTypes changeTypes, FileSystemEventHandler handler, int delay)
{
var cancellations = new Dictionary<string, CancellationTokenSource>(
StringComparer.OrdinalIgnoreCase);
var locker = new object();
if (changeTypes.HasFlag(WatcherChangeTypes.Created))
source.Created += FileSystemWatcher_Event;
if (changeTypes.HasFlag(WatcherChangeTypes.Deleted))
source.Deleted += FileSystemWatcher_Event;
if (changeTypes.HasFlag(WatcherChangeTypes.Changed))
source.Changed += FileSystemWatcher_Event;
if (changeTypes.HasFlag(WatcherChangeTypes.Renamed))
source.Renamed += FileSystemWatcher_Event;
return new Disposable(() =>
{
source.Created -= FileSystemWatcher_Event;
source.Deleted -= FileSystemWatcher_Event;
source.Changed -= FileSystemWatcher_Event;
source.Renamed -= FileSystemWatcher_Event;
});
async void FileSystemWatcher_Event(object sender, FileSystemEventArgs e)
{
var key = e.FullPath;
var cts = new CancellationTokenSource();
lock (locker)
{
if (cancellations.TryGetValue(key, out var existing))
{
existing.Cancel();
}
cancellations[key] = cts;
}
try
{
await Task.Delay(delay, cts.Token);
// Omitting ConfigureAwait(false) is intentional here.
// Continuing in the captured context is desirable.
}
catch (TaskCanceledException)
{
return;
}
lock (locker)
{
if (cancellations.TryGetValue(key, out var existing)
&& existing == cts)
{
cancellations.Remove(key);
}
}
cts.Dispose();
handler(sender, e);
}
}
public static IDisposable OnAllEvents(this FileSystemWatcher source,
FileSystemEventHandler handler, int delay)
=> OnAnyEvent(source, WatcherChangeTypes.All, handler, delay);
public static IDisposable OnCreated(this FileSystemWatcher source,
FileSystemEventHandler handler, int delay)
=> OnAnyEvent(source, WatcherChangeTypes.Created, handler, delay);
public static IDisposable OnDeleted(this FileSystemWatcher source,
FileSystemEventHandler handler, int delay)
=> OnAnyEvent(source, WatcherChangeTypes.Deleted, handler, delay);
public static IDisposable OnChanged(this FileSystemWatcher source,
FileSystemEventHandler handler, int delay)
=> OnAnyEvent(source, WatcherChangeTypes.Changed, handler, delay);
public static IDisposable OnRenamed(this FileSystemWatcher source,
FileSystemEventHandler handler, int delay)
=> OnAnyEvent(source, WatcherChangeTypes.Renamed, handler, delay);
private struct Disposable : IDisposable
{
private readonly Action _action;
internal Disposable(Action action) => _action = action;
public void Dispose() => _action?.Invoke();
}
}
пример Использования:
myWatcher.OnAnyEvent(WatcherChangeTypes.Created | WatcherChangeTypes.Changed,
MyFileSystemWatcher_Event, 100);
Эта строка комбинирует подписку к двум событиям, Created
и Changed
. Таким образом, это примерно эквивалентно им:
myWatcher.Created += MyFileSystemWatcher_Event;
myWatcher.Changed += MyFileSystemWatcher_Event;
различие - то, что эти два события рассматриваются как единственный тип события, и в случае быстрой последовательности этих событий только будет распространено последнее. Например, если Created
событие будет сопровождаться два Changed
события, и нет никакого разрыва времени, больше, чем 100 мс между этими тремя событиями, только второе Changed
, то событие будет распространено путем вызова MyFileSystemWatcher_Event
обработчик, и предыдущие будут отброшены.
Я думаю, что лучшее решение решить проблему состоит в том, чтобы использовать реактивные расширения при преобразовании события в заметный затем можно просто добавить Регулировку (..) (первоначально названный Debounce (..))
Пример кода здесь
var templatesWatcher = new FileSystemWatcher(settingsSnapshot.Value.TemplatesDirectory)
{
NotifyFilter = NotifyFilters.LastWrite,
IncludeSubdirectories = true
};
templatesWatcher.EnableRaisingEvents = true;
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
addHandler => templatesWatcher.Changed += addHandler,
removeHandler => templatesWatcher.Changed -= removeHandler)
.Throttle(TimeSpan.FromSeconds(5))
.Subscribe(args =>
{
_logger.LogInformation($"Template file {args.EventArgs.Name} has changed");
//TODO do something
});
Поиск отвечает, но я предложил грязное решение. Так как мое событие стреляет дважды, второе действие ничего не делает.
$count = 1
$action = {
if($count -eq 1){
#DO SOMETHING
$count = 2
}else{
$count = 1
}
}
если вы регистрируетесь на событие OnChanged, то удаление контролируемого файла перед его изменением может сработать, пока вам нужно отслеживать только событие OnChange. .