# Evos API

Nuget-пакет `Evos.Api.Repository` — публичное API Evos для внешних приложений. В пакете **два API**,
и оба поставляются вместе: низкоуровневое (репозиторий Evos напрямую) и высокоуровневое
(обменная модель, которую собирают у себя и публикуют в Evos).

## Что внутри

| Сборка | API | Зачем |
|---|---|---|
| `Evos.Api.Repository` | низкоуровневое | Открыть репозиторий, писать в транзакциях, версии (VCS), повторитель |
| `Evos.Api.Model` | высокоуровневое | Обменная модель `ExchangeModel`, семейства, сериализация |
| `Evos.Api.Common.Families` | высокоуровневое | Готовые каталожные семейства (производитель, материал, размеры…) |
| `Evos.Api.CollaborationRepository` | высокоуровневое | Публикация модели в Evos и работа с проектом на сервере |

Пакет самодостаточный: все нужные сборки Evos лежат внутри, отдельных зависимостей ставить не надо.

## Какое API брать

Отталкивайтесь от того, откуда приходят данные.

**Данные приходят из внешней системы** (свой каталог, импорт из другого CAD, генератор) —
берите **высокоуровневое**. Вы описываете, что должно оказаться в проекте, а Evos сам решает,
что создать, а что обновить. Публикация идемпотентна: повторная отправка той же модели не плодит дубли.

**Нужен полный контроль над моделью** (пройти по продуктам, поправить свойство, посмотреть историю,
собрать воздуховод повторителем) — берите **низкоуровневое**. Вы работаете с репозиторием Evos
как он есть: продукты, экземпляры, семейства, транзакции.

Смешивать можно и нужно: отдельного «репозитория обменной модели» не существует. Репозиторий
открывает низкоуровневая фабрика, и **тот же самый** объект принимает высокоуровневый экспортёр.

```csharp
using var repository = new ApiConcurrentRepositoryFactory().OpenNewRepository(location);

ExchangeModelToEvosExporterFactory.Create().Export(repository, model);
```

## Документация

- [Низкоуровневое API](docs/LowLevelApi.md) — репозиторий, транзакции, продукты и семейства, VCS, повторитель.
- [Высокоуровневое API](docs/HighLevelApi.md) — обменная модель, свойства и семейства, сериализация,
  публикация в репозиторий и на Collaboration-сервер.

## Быстрый старт

Низкоуровневое — создать репозиторий и записать в него продукт:

```csharp
using var repository = new ApiConcurrentRepositoryFactory()
    .OpenNewRepository(new ProjectLocation(directory, "MyProject"));

repository.TryExecuteTransaction(
    writeAccess => writeAccess.NewNamedProduct("Насос", ProductKind.Designed),
    new TransactionInfo(TransactionDescription.AddingProduct, TransactionMode.Default));
```

Высокоуровневое — собрать модель и опубликовать её в репозиторий:

```csharp
var builder = ExchangeModelBuilderFactory.Create(projectId);

var pump = builder.NewProduct();
pump.KeyProperties.SetValue(CommonFamilies.КаталогПроизводитель.Производитель, "Grundfos");
pump.KeyProperties.SetValue(CommonFamilies.КаталогПроизводитель.АртикулПроизводителя, "UPS-25");
pump.Properties.SetValue(EvosFamilies.ProductName.Name, "Насос циркуляционный");

var model = builder.Build().ValueOrThrow();

ExchangeModelToEvosExporterFactory.Create().Export(repository, model);
```

## Сэмплы

Рабочие примеры поставляются отдельным архивом `EvosApiSamples-<версия>.zip` — с тем же номером версии,
что и этот пакет. Внутри готовый к сборке проект, эта документация и сам пакет, так что архив
собирается сразу после распаковки:

```
dotnet run
```

Каждый сэмпл — самостоятельный сценарий, который можно скопировать к себе. Они же служат smoke-тестами
API, поэтому не расходятся с кодом: сломается API — сломаются сэмплы, и версия не выйдет.

## Что стоит знать заранее

**Писать можно только в транзакции.** `TryExecuteTransaction` сам открывает write-соединение
и коммитит его на выходе.

**Запись и чтение не совмещаются.** Репозиторий не даёт взять write-блокировку поверх открытого
read-соединения: прочитали нужное, закрыли соединение — потом пишите.

**Ключевые свойства задают тождество.** В обменной модели два продукта с одинаковым набором
ключевых свойств — это один и тот же продукт. Отсюда и идемпотентность публикации, и требование
проставлять экземплярам собственный идентификатор.

**Продукт — это тип, а не деталь в проекте.** Четыре лампы в люстре — один продукт «Лампа»
и четыре его экземпляра. Свойство, заданное продукту, действует на все его экземпляры;
индивидуально экземпляр настраивают переопределением, и только если свойство открыто.

**Продукту нужны свои ключевые свойства.** Обычно это производитель и артикул. Без них Evos
не может отличить один продукт от другого, и `Build()` объявит их дубликатами — даже если имена
у них разные: имя лежит в обычных свойствах и в тождество не входит.

**Адресные идентификаторы выдаёт только сервер.** `EvosModelId` и `EvosInstanceRef` (обновить
конкретный продукт, поставить оборудование на конкретный уровень) приходят из чтения проекта
с Collaboration-сервера. Из локального репозитория их получить нечем — там те же задачи решают
низкоуровневым API.
