ECore.Client
26.2.8
dotnet add package ECore.Client --version 26.2.8
NuGet\Install-Package ECore.Client -Version 26.2.8
<PackageReference Include="ECore.Client" Version="26.2.8" />
<PackageVersion Include="ECore.Client" Version="26.2.8" />
<PackageReference Include="ECore.Client" />
paket add ECore.Client --version 26.2.8
#r "nuget: ECore.Client, 26.2.8"
#:package ECore.Client@26.2.8
#addin nuget:?package=ECore.Client&version=26.2.8
#tool nuget:?package=ECore.Client&version=26.2.8
ECore.Client
Typovaný .NET klient GraphQL API Evolio ECore (net8.0/net10.0): multi-tenant transport,
přihlášení přes EIdentity, doménově dělené dotazy/mutace, volání procedur a chybový model.
Nemá závislost na serverových sestaveních ECore.*. Verze balíčku odpovídá verzi API
(26.2.8 = API 26.2.8), klient ji posílá v hlavičce evolio-x-version.
Instalace
dotnet add package ECore.Client
Přihlášení
API přijímá Bearer token z EIdentity (https://eidentity.evolio.cz) se scope ecore.api.
Třetí strany používají klienta ecore.public-api (ROPC + refresh token); client secret a účet
dostanete od AVE Soft. Implementace ITokenProvider (ECore.Client.Transport):
| Implementace | Kdy použít |
|---|---|
StaticTokenProvider(token) |
hotový token (z requestu/ticketu), bez obnovy |
DelegateTokenProvider |
vlastní zdroj nebo cache tokenu |
EIdentityPasswordTokenProvider |
servisní účet — ROPC + refresh_token, cache do expires_in − 60 s, souběžná volání čekají na jeden refresh |
services.AddSingleton<ITokenProvider>(sp => new EIdentityPasswordTokenProvider(
new HttpClient(),
new EIdentityPasswordOptions
{
ClientId = "ecore.public-api",
ClientSecret = "…",
Username = "uzivatel@firma.cz",
Password = "…",
}));
ITokenProvider registrujte jako Singleton a před AddECoreClient — jiný lifetime
shodí aplikaci hned při startu.
Konfigurace
services.AddECoreClient(options =>
{
options.Tenant = "acme"; // povinné
options.BaseUrlTemplate = "https://{tenant}.evolio.ws/api"; // výchozí
options.TenantMode = TenantMode.Subdomain; // nebo Header (X-Tenant-Id)
});
| Vlastnost | Výchozí | Poznámka |
|---|---|---|
BaseUrlTemplate |
https://{tenant}.evolio.ws/api |
jen https (výjimka localhost); v Subdomain musí obsahovat {tenant} |
Tenant |
— | ^[a-z0-9][a-z0-9-]{0,62}$ |
TenantMode |
Subdomain |
Header = sdílená URL, tenant v hlavičce X-Tenant-Id |
ApiVersion |
verze balíčku | hlavička evolio-x-version |
Timeout |
100 s | |
PageSize / MaxRowsPerQuery |
100 / 10 000 | stránkování a strop ToListAsync |
ClientCostLimit |
1000 | klientský odhad ceny dotazu před odesláním; null = vypnuto |
Language |
cs |
Accept-Language |
Kontext pro konkrétního tenanta (i víc tenantů v jednom procesu) dá IECoreContextFactory:
var ctx = contextFactory.Create("acme");
var jiny = contextFactory.Create("jina-firma", jinyTokenProvider);
Dotazy
Entity jsou rozdělené podle domén: ctx.<Domena>.<Entita> (ctx.Pripady, ctx.Subjekty,
ctx.Dokumenty, ctx.Udalosti, ctx.Ukoly, ctx.Posta, ctx.Lhuty, ctx.Vykazy, …),
typy leží v namespace ECore.Client.<Domena>.
var page = await ctx.Pripady.Pripady
.Where(f => f.Stav.Eq("A") & f.CisloPripadu.StartsWith("2026")) // typovaný filtr (& = AND)
.Where(x => x.IdPripad > 100 && x.Stav != "Z") // nebo výraz nad kořenovou entitou
.OrderBy(s => s.DatumZahajeno.Desc())
.Include(x => x.VyrizujeZamestnanec) // navigace
.Select(x => new { x.IdPripad, x.Stav, Zamestnanec = x.VyrizujeZamestnanec!.Jmeno })
.ToPageAsync(first: 50);
var pripad = await ctx.Pripady.Pripady.ByIdAsync(42);
var vsechny = await ctx.Subjekty.Subjekty.Where(x => x.Prijmeni == "Novák").ToListAsync();
var pocet = await ctx.Pripady.Pripady.CountAsync();
- Terminály:
ToPageAsync,ToListAsync/AsAsyncEnumerable(stránkují samy),FirstOrDefaultAsync,SingleOrDefaultAsync,CountAsync,AnyAsync,ByIdAsync,ByKeyAsync,BySysRowIdAsync,SouhrnAsync(agregace),HodnotyAsync(distinct hodnoty). - Výraz s metodou řetězce (
StartsWith,Contains) je nejednoznačný vůči typovanému filtru — pište typ parametru explicitně:.Where((Pripady x) => x.CisloPripadu!.Contains("/")). - OR na úrovni entity schéma nemá (
|vyhodíNotSupportedException) — použijteIn(...)nebo dva dotazy. ToListAsyncnadMaxRowsPerQueryvyhodíECoreTooManyRowsException, nikdy tiše neořízne.Includenad kolekcí načte prvních 50 položek a vrátíTotalCount— useknutí poznáte.
Mutace
var result = await ctx.Pripady.Mutace.PripadPatchAsync(new PripadPatchInput
{
Id = 42,
RowVersion = pripad!.System!.RowVersion, // optimistický zámek
Stav = "B",
});
if (!result.IsSuccess) { /* result.UserErrors, result.IsRetryable */ }
var ulozeny = result.EnsureSuccess(); // při userErrors vyhodí ECoreUserErrorException
// PATCH jen změněných polí z načtené entity (klíč a verzi doplní sám):
var input = PatchBuilder.For(pripad).Set(x => x.Stav, "B").ToInput<PripadPatchInput>();
PATCH mění jen pole, která nastavíte (Optional<T>), ostatní na serveru zůstanou. Business chyby
chodí jako UserErrors v payloadu (field, code, message), ne jako výjimka. Mutace se po
timeoutu/5xx neopakují — před opakováním zápisu ověřte čtením, zda neproběhl.
Procedury
// MujRadek = vlastní DTO s vlastnostmi podle sloupců výsledku
var rows = await ctx.Procedures.QueryAsync<MujRadek>("dbo.NejakyDotaz",
new Dictionary<string, object?> { ["IdPripad"] = 42 }, maxRows: 500);
var exec = await ctx.Procedures.ExecuteAsync("dbo.NejakaProcedura",
new Dictionary<string, object?> { ["Id"] = 5 });
exec.EnsureSuccess();
Volat lze jen procedury, které server zpřístupňuje. Oříznutý výsledek (Truncated) vyhodí
ECoreTruncatedResultException, pokud nezavoláte s allowTruncated: true.
Chyby (ECore.Client.Exceptions)
| Výjimka | Kdy |
|---|---|
ECoreGraphQLException |
errors[] z GraphQL (NOT_FOUND, VALIDATION, AUTH_NOT_AUTHORIZED, …); nese Errors, PartialData, CorrelationId |
ECoreTenantAccessException |
uživatel nemá přístup k tenantovi |
ECoreVersionException |
server nepodporuje verzi klienta (Code, ServerVersion) |
ECoreCostException |
dotaz je příliš drahý (klientský odhad nebo server) |
ECoreAuthException |
selhalo přihlášení k EIdentity |
ECoreUserErrorException |
EnsureSuccess() nad výsledkem s userErrors |
ECoreUnexpectedResponseException |
odpověď není GraphQL (proxy, HTML chybová stránka) |
Transport sám zopakuje request po 401 (s novým tokenem) a dotazy po 5xx/timeoutu (2×).
CorrelationId je hodnota hlavičky X-Correlation-Id, kterou klient poslal — hodí se do
hlášení chyby.
Schéma a verze
GET https://{tenant}.evolio.ws/api/version— verze nasazeného API (anonymně).GET https://{tenant}.evolio.ws/api/schema— SDL schématu.- Balíček nepředbíhá nasazené API; novější verze balíčku než API server odmítne (
ECoreVersionException).
Licence
Apache-2.0 — https://licenses.nuget.org/Apache-2.0.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Http (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
-
net8.0
- Microsoft.Extensions.Http (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ECore.Client:
| Package | Downloads |
|---|---|
|
ECore.Client.EMapCompat
Vrstva pro mechanickou migraci z EMapProxyContext na ECore.Client — zachovává názvy a tvar API EMap.Proxy pro postupný přechod EFabric služeb z EMap na ecore (E005-Z, plán §5.3/§5.6). Neatomický UnitOfWork, IncludeEMap, mapa názvů v docs/ecore-client-mapa-emap.md. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 26.2.8 | 63 | 9/23/2026 |