Mds.Libraries.CSharp.Updates 6.0.0-beta.99971
Mds.Libraries.CSharp.Updates - пакет для работы с изменениями и их отслеживанием
Задачи пакета
- Средства для обновления в апи,
PartialUpdater - Применение и отcлеживание изменений,
Updater - Синхронизация и импорт,
IUpdatesIndex,CollectionsSynchronizerиGroupsSynchronizer
Синхронизация
Для синхронизации необходимо реализовать адаптер.
Есть несколько типов адаптера:
Синхронизация коллекций
ICollectionAtomicSynchronizeAdapterICollectionBindingSynchronizeAdapterICollectionSynchronizeAdapter
При таком типе синхронизации происходит синхронизация по указанному ключу обновляемой сущности.
При использовании интерфейса адаптера 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
}
Групповая синхронизация
IGroupsAtomicSynchronizeAdapterIGroupsBindingSynchronizeAdapterIGroupsSynchronizeAdapter
При таком типе синхронизации происходит синхронизация по указанному ключу обновляемой сущности с группировкой по ключу группы.
При использовании интерфейса адаптера 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 |
.NET 7.0
- EFCore.BulkExtensions (>= 7.0.4)
- Mds.Libraries.CSharp.Extensions (>= 2.1.0)
- Microsoft.EntityFrameworkCore (>= 7.0.5)
- Microsoft.EntityFrameworkCore.SqlServer (>= 7.0.5)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 7.0.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 |