Mds.Libraries.CSharp.Updates 6.0.0-beta.99971

Mds.Libraries.CSharp.Updates - пакет для работы с изменениями и их отслеживанием

Задачи пакета

  • Средства для обновления в апи, PartialUpdater
  • Применение и отcлеживание изменений, Updater
  • Синхронизация и импорт, IUpdatesIndex, CollectionsSynchronizer и GroupsSynchronizer

Синхронизация

Для синхронизации необходимо реализовать адаптер.

Есть несколько типов адаптера:

Синхронизация коллекций

  • ICollectionAtomicSynchronizeAdapter
  • ICollectionBindingSynchronizeAdapter
  • ICollectionSynchronizeAdapter

При таком типе синхронизации происходит синхронизация по указанному ключу обновляемой сущности.

При использовании интерфейса адаптера ICollectionSynchronizeAdapter происходит обновление всех полей сущностей, которые указаны в bindings, вне зависимости от того, какие изменялись.

file class ImportAdapter : ICollectionSynchronizeAdapter<TestGood, long>
{
    private static readonly UpdateBindings<TestGood> _bindings;

    static ImportAdapter()
    {
        _bindings = new UpdateBindings<TestGood>()
        {
            {e => e.ExternalId },
            {e => e.Name },
            {e => e.Manufacturer },
        };
    }


    #region ICollectionSynchronizeAdapter

    Expression<Func<TestGood, long>> ICollectionSynchronizeAdapter<TestGood, long>.KeySelector => e => e.Id;

    bool ICollectionSynchronizeAdapter<TestGood, long>.UpdateEntity(TestGood entity, TestGood update)
    {
        return UpdateAdapter.Apply(entity, update, _bindings);
    }

    #endregion ICollectionSynchronizeAdapter
}

При использовании интерфейса адаптера ICollectionBindingSynchronizeAdapter происходит обновление полей сущности, которые были изменены и указаны в bindings. Остальные поля в итоговый запрос к бд не попадают. Данный адаптер нужно применять когда bindings строятся динамически.

file class ImportAdapter : ICollectionBindingSynchronizeAdapter<TestGood, long>
{ 
    #region ICollectionBindingSynchronizeAdapter

    Expression<Func<TestGood, long>> ICollectionBindingSynchronizeAdapter<TestGood, long>.KeySelector => e => e.Id;

    UpdateBindings<TestGood> ICollectionBindingSynchronizeAdapter<TestGood, long>.GetBindings(TestGood entity, TestGood update)
    {
       var bindings = new UpdateBindings<TestGood>()
        {
            {e => e.ExternalId },
            {e => e.Name },
            {e => e.Manufacturer },
        };

       if (entity.ExternalHash != update.ExternalHash)
       {
           bindings.Add(e => e.Quantity);
       }

        return bindings;
    }

    #endregion ICollectionBindingSynchronizeAdapter
}

При использовании интерфейса адаптера ICollectionAtomicSynchronizeAdapter происходит обновление полей сущности, которые были изменены и указаны в bindings. Остальные поля в итоговый запрос к бд не попадают. В отличие от ICollectionBindingSynchronizeAdapter, здесь мы используем статические bindings, которые не будут изменяться во время выполнения UpdateEntity.

file class ImportAdapter : ICollectionAtomicSynchronizeAdapter<TestGood, long>
{
    private static readonly UpdateBindings<TestGood> _bindings;

    static ImportAdapter()
    {
        _bindings = new UpdateBindings<TestGood>()
        {
            {e => e.ExternalId },
            {e => e.Name },
            {e => e.Manufacturer },
        };
    }


    #region ICollectionAtomicSynchronizeAdapter

    Expression<Func<TestGood, long>> ICollectionAtomicSynchronizeAdapter<TestGood, long>.KeySelector => e => e.Id;

    EntityChanges<TestGood> ICollectionAtomicSynchronizeAdapter<TestGood, long>.UpdateEntity(TestGood entity, TestGood update)
    {
        return UpdateAdapter.Apply(entity, update, _bindings);
    }

    #endregion ICollectionAtomicSynchronizeAdapter
}

Групповая синхронизация

  • IGroupsAtomicSynchronizeAdapter
  • IGroupsBindingSynchronizeAdapter
  • IGroupsSynchronizeAdapter

При таком типе синхронизации происходит синхронизация по указанному ключу обновляемой сущности с группировкой по ключу группы.

При использовании интерфейса адаптера IGroupsSynchronizeAdapter происходит обновление всех полей сущностей, которые указаны в bindings, вне зависимости от того, какие изменялись.

file class ImportAdapter : IGroupsSynchronizeAdapter<TestGood, string, long>
{
    private static readonly UpdateBindings<TestGood> _bindings;

    static ImportAdapter()
    {
        _bindings = new UpdateBindings<TestGood>()
        {
            {e => e.ExternalId },
            {e => e.Name },
            {e => e.Manufacturer },
        };
    }


    #region IGroupsSynchronizeAdapter

    Expression<Func<TestGood, string>> IGroupsSynchronizeAdapter<TestGood, string, long>.GroupKeySelector => e => e.ExternalId;

    Expression<Func<TestGood, long>> ICollectionSynchronizeAdapter<TestGood, long>.KeySelector => e => e.Id;

    bool ICollectionSynchronizeAdapter<TestGood, long>.UpdateEntity(TestGood entity, TestGood update)
    {
        return UpdateAdapter.Apply(entity, update, _bindings);
    }

    #endregion IGroupsSynchronizeAdapter
}

При использовании интерфейса адаптера IGroupsBindingSynchronizeAdapter происходит обновление полей сущности, которые были изменены и указаны в bindings. Остальные поля в итоговый запрос к бд не попадают. Данный адаптер нужно применять когда bindings строятся динамически.

file class ImportAdapter : IGroupsBindingSynchronizeAdapter<TestGood, string, long>
{
   #region IGroupsBindingSynchronizeAdapter

    Expression<Func<TestGood, string>> IGroupsBindingSynchronizeAdapter<TestGood, string, long>.GroupKeySelector => e => e.ExternalId;

    Expression<Func<TestGood, long>> ICollectionBindingSynchronizeAdapter<TestGood, long>.KeySelector => e => e.Id;

    UpdateBindings<TestGood> ICollectionBindingSynchronizeAdapter<TestGood, long>.GetBindings(TestGood entity, TestGood update)
    {
       var bindings = new UpdateBindings<TestGood>()
       {
           {e => e.ExternalId },
           {e => e.Name },
           {e => e.Manufacturer },
       };

       if (entity.ExternalHash != update.ExternalHash)
       {
           bindings.Add(e => e.Quantity);
       }

       return bindings;
    }

   #endregion IGroupsBindingSynchronizeAdapter
}

При использовании интерфейса адаптера IGroupsAtomicSynchronizeAdapter происходит обновление полей сущности, которые были изменены и указаны в bindings. Остальные поля в итоговый запрос к бд не попадают. В отличие от IGroupsBindingSynchronizeAdapter, здесь мы используем статические bindings, которые не будут изменяться во время выполнения UpdateEntity.

file class ImportAdapter : IGroupsAtomicSynchronizeAdapter<TestGood, string, long>
{
    private static readonly UpdateBindings<TestGood> _bindings;

    static ImportAdapter()
    {
        _bindings = new UpdateBindings<TestGood>()
        {
            {e => e.ExternalId },
            {e => e.Name },
            {e => e.Manufacturer },
        };
    }


    #region IGroupsAtomicSynchronizeAdapter

    Expression<Func<TestGood, string>> IGroupsAtomicSynchronizeAdapter<TestGood, string, long>.GroupKeySelector => e => e.ExternalId;

    Expression<Func<TestGood, long>> ICollectionAtomicSynchronizeAdapter<TestGood, long>.KeySelector => e => e.Id;

    EntityChanges<TestGood> ICollectionAtomicSynchronizeAdapter<TestGood, long>.UpdateEntity(TestGood entity, TestGood update)
    {
        return UpdateAdapter.Apply(entity, update, _bindings);
    }

    #endregion IGroupsAtomicSynchronizeAdapter
}

Обьявление адаптера и его применение

Пример синхнизации коллекции

В месте, где нам нужна синхронизация коллекции создаем синхронизатор.

var synchronizer = CollectionsSynchronizerBuilder.Build<TestGood, long>(new ImportAdapter());

// При желании можно указать настроки синхронизации
adapter.Settings = new CollectionsSynchronizerSettings
{
    ImportMode = ImportMode.Partial
};

Используем синхронизатор для синхронизации

// Когда синхронизируем все элементы в базе
var index = await synchronizer.SyncAsync(import, context);

// Когда синхронизируем только определенные элементы
var stored = new List<TestGood> { ... };
var index = synchronizer.Sync(converted, stored);

Переменная index содержит данные для синхронизации: какие элементы надо добавить, какие обновить, какие удалить и поля которые были обновлены, если используется соотвествующий адаптер.

После этого фиксируем изменения в БД.

await index.SaveAsync(context);

Пример группой синхронизации.

В метод Custom можно передать настройки вашего синхронизатора


var synchronizer = GroupsSynchronizerBuilder.Custom(new ImportAdapter(), s =>
                   {
                       s.ImportMode = ImportMode.Full;
                       s.AllowAdd = false;
                       s.AllowUpdate = true;
                       s.AllowRemove = true;   
                       if (container.IsPatch)
                       {
                           s.ImportMode = ImportMode.Partial;
                           s.AllowRemove = false;
                       }
                   });

 // Вызываем метод синхронизации и передаем туда коллекцию сущностей с изменениями и коллекцию которая будет изменятся, в исходном состоянии(пока не обновленную).
 // Переменная index содержит данные для синхронизации: какие элементы надо добавить, какие обновить, какие удалить и поля которые были обновлены, если используется соотвествующий адаптер.
 var index = synchronizer.Sync(import, stored);

 // После этого фиксируем изменения в БД.
 await index.SaveAsync(context);

Showing the top 20 packages that depend on Mds.Libraries.CSharp.Updates.

Packages Downloads
Mds.Libraries.CSharp.ChangesBus
Пакет для интеграции шины для обновления сущностей.
1
Mds.Libraries.CSharp.ChangesBus
Пакет для интеграции шины для обновления сущностей.
2
Mds.Libraries.CSharp.Db.Mongo
Пакет для удобной работы с mongoDb.
1
Mds.Libraries.CSharp.Db.Mongo
Пакет для удобной работы с mongoDb.
2
Mds.Libraries.CSharp.Server
Package with tools for server from MedvedStudio.
4

Version Downloads Last updated
7.0.1 3 02/28/2026
6.2.1 1 02/28/2026
6.2.0 1 02/28/2026
6.2.0-beta.120674 1 02/28/2026
6.2.0-beta.107775 1 02/28/2026
6.1.1 1 02/28/2026
6.1.0 1 02/28/2026
6.1.0-beta.106612 1 02/28/2026
6.1.0-beta.106605 1 02/28/2026
6.1.0-beta.106595 1 02/28/2026
6.1.0-beta.106589 1 02/28/2026
6.0.1 1 02/28/2026
6.0.0 1 02/28/2026
6.0.0-beta.99971 1 02/28/2026
6.0.0-beta.57258 1 02/28/2026
5.4.0 1 02/28/2026
5.4.0-beta.103919 1 02/28/2026
5.3.0 1 02/28/2026
5.3.0-beta.104867 1 02/28/2026
5.3.0-beta.71649 1 02/28/2026
5.3.0-beta.61482 1 02/28/2026
5.3.0-beta.58276 1 02/28/2026
5.2.1 1 02/28/2026
5.2.0 1 02/28/2026
5.2.0-beta.29757 1 02/28/2026
5.2.0-beta.29727 1 02/28/2026
5.2.0-beta.29724 1 02/28/2026
5.2.0-beta.29722 1 02/28/2026
5.2.0-beta.29719 1 02/28/2026
5.1.0 1 02/28/2026
5.1.0-beta.104532 1 02/28/2026
5.1.0-beta.18822 1 02/28/2026
5.0.3 1 02/28/2026
5.0.3-beta.11921 1 02/28/2026
5.0.2 1 02/28/2026
5.0.2-beta.11265 1 02/28/2026
5.0.1 1 02/28/2026
5.0.1-beta.105682 1 02/28/2026
5.0.0 1 02/28/2026
4.5.4-beta.11277 1 02/28/2026
4.5.3 1 02/28/2026
4.5.2 1 02/28/2026
4.5.1 1 02/28/2026
4.5.0 1 02/28/2026
4.0.3 1 02/28/2026
4.0.1 1 02/28/2026
4.0.0 1 02/28/2026
3.1.3 1 02/28/2026
3.1.1.9498 1 02/28/2026