Entiteit functiesEntity functions

Met entiteits functies worden bewerkingen gedefinieerd voor het lezen en bijwerken van kleine stukjes status, ook wel duurzame entiteitengenoemd.Entity functions define operations for reading and updating small pieces of state, known as durable entities. Net als Orchestrator functions zijn entiteits functies functies met een speciaal trigger type, de entiteit trigger.Like orchestrator functions, entity functions are functions with a special trigger type, the entity trigger. In tegens telling tot Orchestrator-functies, beheren entiteits functies de status van een entiteit expliciet, in plaats van impliciet de status te bepalen via de controle stroom.Unlike orchestrator functions, entity functions manage the state of an entity explicitly, rather than implicitly representing state via control flow. Entiteiten bieden een manier om toepassingen te schalen door het werk over een groot aantal entiteiten te verdelen, elk met een zeer grote status.Entities provide a means for scaling out applications by distributing the work across many entities, each with a modestly sized state.

Notitie

Entiteits functies en gerelateerde functionaliteit zijn alleen beschikbaar in Durable Functions 2,0 en hoger.Entity functions and related functionality is only available in Durable Functions 2.0 and above.

Algemene conceptenGeneral concepts

Entiteiten gedragen zich op dezelfde manier als kleine services die communiceren via berichten.Entities behave a bit like tiny services that communicate via messages. Elke entiteit heeft een unieke identiteit en een interne status (indien aanwezig).Each entity has a unique identity and an internal state (if it exists). Net als bij Services of objecten voeren entiteiten bewerkingen uit wanneer daarom wordt gevraagd.Like services or objects, entities perform operations when prompted to do so. Wanneer een bewerking wordt uitgevoerd, kan de interne status van de entiteit worden bijgewerkt.When an operation executes, it might update the internal state of the entity. Het kan ook externe services aanroepen en wachten op een reactie.It might also call external services and wait for a response. Entiteiten communiceren met andere entiteiten, Orchestrations en clients door gebruik te maken van berichten die impliciet worden verzonden via betrouw bare wacht rijen.Entities communicate with other entities, orchestrations, and clients by using messages that are implicitly sent via reliable queues.

Om conflicten te voor komen, is het mogelijk dat alle bewerkingen op één entiteit een serieel, dat wil zeggen, een voor een worden uitgevoerd.To prevent conflicts, all operations on a single entity are guaranteed to execute serially, that is, one after another.

Entiteit-IDEntity ID

Entiteiten worden geopend via een unieke id, de entiteit-id.Entities are accessed via a unique identifier, the entity ID. Een Entiteits-ID is gewoon een paar teken reeksen waarmee een entiteits exemplaar uniek wordt geïdentificeerd.An entity ID is simply a pair of strings that uniquely identifies an entity instance. Het bestaat uit een:It consists of an:

  • De naam van de entiteit. Dit is een naam die het type van de entiteit aanduidt.Entity name, which is a name that identifies the type of the entity. Een voor beeld is Counter.An example is "Counter." Deze naam moet overeenkomen met de naam van de entiteit functie die de entiteit implementeert.This name must match the name of the entity function that implements the entity. Het is niet hoofdletter gevoelig.It isn't sensitive to case.
  • Entiteits sleutel: dit is een teken reeks die een unieke identificatie vormt van de entiteit tussen alle andere entiteiten met dezelfde naam.Entity key, which is a string that uniquely identifies the entity among all other entities of the same name. Een voor beeld is een GUID.An example is a GUID.

Bijvoorbeeld, een functie voor het Counter entiteit kan worden gebruikt om de score in een online spel te bewaren.For example, a Counter entity function might be used for keeping score in an online game. Elk exemplaar van het spel heeft een unieke entiteit-ID, zoals @Counter@Game1 en @Counter@Game2.Each instance of the game has a unique entity ID, such as @Counter@Game1 and @Counter@Game2. Alle bewerkingen die gericht zijn op een bepaalde entiteit, moeten een entiteit-ID opgeven als para meter.All operations that target a particular entity require specifying an entity ID as a parameter.

Entiteits bewerkingenEntity operations

Als u een bewerking wilt aanroepen voor een entiteit, geeft u het volgende op:To invoke an operation on an entity, specify the:

  • Entiteit-id van de doel entiteit.Entity ID of the target entity.
  • Bewerkings naam: een teken reeks die de bewerking specificeert die moet worden uitgevoerd.Operation name, which is a string that specifies the operation to perform. De Counter entiteit kan bijvoorbeeld bewerkingen voor add, getof reset ondersteunen.For example, the Counter entity could support add, get, or reset operations.
  • Invoervan de bewerking. Dit is een optionele invoer parameter voor de bewerking.Operation input, which is an optional input parameter for the operation. De toevoeg bewerking kan bijvoorbeeld een geheel getal als invoer hebben.For example, the add operation can take an integer amount as the input.

Bewerkingen kunnen resulteren in een resultaat waarde of een fout resultaat, zoals een Java script-fout of een .NET-uitzonde ring.Operations can return a result value or an error result, such as a JavaScript error or a .NET exception. Dit resultaat of deze fout kan worden waargenomen door integraties die de bewerking worden genoemd.This result or error can be observed by orchestrations that called the operation.

Een entiteits bewerking kan ook de status van de entiteit maken, lezen, bijwerken en verwijderen.An entity operation can also create, read, update, and delete the state of the entity. De status van de entiteit is altijd blijvend behouden in de opslag.The state of the entity is always durably persisted in storage.

Entiteiten definiërenDefine entities

Momenteel zijn de twee afzonderlijke Api's voor het definiëren van entiteiten een:Currently, the two distinct APIs for defining entities are a:

Syntaxis op basis vanfuncties, waarbij entiteiten worden weer gegeven als functies en bewerkingen expliciet worden verzonden door de toepassing.Function-based syntax, where entities are represented as functions and operations are explicitly dispatched by the application. Deze syntaxis werkt goed voor entiteiten met eenvoudige status, weinig bewerkingen of een dynamische set bewerkingen, zoals in Application Frameworks.This syntax works well for entities with simple state, few operations, or a dynamic set of operations like in application frameworks. Deze syntaxis kan lastig zijn om te onderhouden omdat het geen type fouten tijdens het compileren ophaalt.This syntax can be tedious to maintain because it doesn't catch type errors at compile time.

Op klassen gebaseerde syntaxis, waarbij entiteiten en bewerkingen worden vertegenwoordigd door klassen en methoden.Class-based syntax, where entities and operations are represented by classes and methods. Deze syntaxis produceert eenvoudiger lees bare code en maakt het mogelijk om bewerkingen op een type veilige manier te activeren.This syntax produces more easily readable code and allows operations to be invoked in a type-safe way. De op klassen gebaseerde syntaxis is een smalle laag boven op de functie gebaseerde syntaxis, zodat beide varianten door elkaar kunnen worden gebruikt in dezelfde toepassing.The class-based syntax is a thin layer on top of the function-based syntax, so both variants can be used interchangeably in the same application.

Voor beeld: syntaxis op basis van een functie-C#Example: Function-based syntax - C#

De volgende code is een voor beeld van een eenvoudige Counter entiteit die als een duurzame functie is geïmplementeerd.The following code is an example of a simple Counter entity implemented as a durable function. Deze functie definieert drie bewerkingen, add, reseten get, die elk een gehele status hebben.This function defines three operations, add, reset, and get, each of which operates on an integer state.

[FunctionName("Counter")]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
    switch (ctx.OperationName.ToLowerInvariant())
    {
        case "add":
            ctx.SetState(ctx.GetState<int>() + ctx.GetInput<int>());
            break;
        case "reset":
            ctx.SetState(0);
            break;
        case "get":
            ctx.Return(ctx.GetState<int>());
            break;
    }
}

Zie syntaxis op basis van functiesvoor meer informatie over de syntaxis van de functie en hoe u deze kunt gebruiken.For more information on the function-based syntax and how to use it, see Function-based syntax.

Voor beeld: op klasse gebaseerde syntaxis-C#Example: Class-based syntax - C#

Het volgende voor beeld is een equivalente implementatie van de Counter entiteit met klassen en methoden.The following example is an equivalent implementation of the Counter entity using classes and methods.

[JsonObject(MemberSerialization.OptIn)]
public class Counter
{
    [JsonProperty("value")]
    public int CurrentValue { get; set; }

    public void Add(int amount) => this.CurrentValue += amount;

    public void Reset() => this.CurrentValue = 0;

    public int Get() => this.CurrentValue;

    [FunctionName(nameof(Counter))]
    public static Task Run([EntityTrigger] IDurableEntityContext ctx)
        => ctx.DispatchAsync<Counter>();
}

De status van deze entiteit is een object van het type Counter, dat een veld bevat waarin de huidige waarde van de teller wordt opgeslagen.The state of this entity is an object of type Counter, which contains a field that stores the current value of the counter. Als u dit object in de opslag ruimte wilt behouden, wordt het geserialiseerd en gedeserialiseerd door de JSON.net -bibliotheek.To persist this object in storage, it's serialized and deserialized by the Json.NET library.

Zie entity branches definiërenvoor meer informatie over de op klassen gebaseerde syntaxis en hoe u deze kunt gebruiken.For more information on the class-based syntax and how to use it, see Defining entity classes.

Voor beeld: Java script-entiteitExample: JavaScript entity

Duurzame entiteiten zijn beschikbaar in Java script vanaf versie 1.3.0 van het NPM-pakket van durable-functions.Durable entities are available in JavaScript starting with version 1.3.0 of the durable-functions npm package. De volgende code is de Counter entiteit die is geïmplementeerd als een duurzame functie die is geschreven in Java script.The following code is the Counter entity implemented as a durable function written in JavaScript.

function. jsonfunction.json

{
  "bindings": [
    {
      "name": "context",
      "type": "entityTrigger",
      "direction": "in"
    }
  ],
  "disabled": false
}

index. jsindex.js

const df = require("durable-functions");

module.exports = df.entity(function(context) {
    const currentValue = context.df.getState(() => 0);
    switch (context.df.operationName) {
        case "add":
            const amount = context.df.getInput();
            context.df.setState(currentValue + amount);
            break;
        case "reset":
            context.df.setState(0);
            break;
        case "get":
            context.df.return(currentValue);
            break;
    }
});

Toegangs entiteitenAccess entities

U kunt toegang krijgen tot entiteiten via eenrichtings-of twee richtings communicatie.Entities can be accessed using one-way or two-way communication. De volgende terminologie maakt onderscheid tussen de twee communicatie vormen:The following terminology distinguishes the two forms of communication:

  • Bij het aanroepen van een entiteit wordt gebruikgemaakt van twee richtings communicatie (round-trip).Calling an entity uses two-way (round-trip) communication. U stuurt een bewerkings bericht naar de entiteit en wacht vervolgens op het antwoord bericht voordat u doorgaat.You send an operation message to the entity, and then wait for the response message before you continue. Het antwoord bericht kan een resultaat waarde of een fout resultaat bevatten, zoals een Java script-fout of een .NET-uitzonde ring.The response message can provide a result value or an error result, such as a JavaScript error or a .NET exception. Dit resultaat of deze fout wordt vervolgens waargenomen door de oproepende functie.This result or error is then observed by the caller.
  • Wanneer een entiteit wordt gesignaleerd , wordt communicatie met één richting (vuur en verg eten) gebruikt.Signaling an entity uses one-way (fire and forget) communication. U verzendt een bewerkings bericht, maar u hoeft niet te wachten op een reactie.You send an operation message but don't wait for a response. Wanneer het bericht wordt gegarandeerd uiteindelijk wordt bezorgd, weet de afzender niet wanneer er geen resultaat waarde of fouten kunnen worden gevonden.While the message is guaranteed to be delivered eventually, the sender doesn't know when and can't observe any result value or errors.

Entiteiten kunnen worden geopend vanuit client functies, vanuit Orchestrator-functies, of vanuit entiteits functies.Entities can be accessed from within client functions, from within orchestrator functions, or from within entity functions. Niet alle communicatie vormen worden door alle contexten ondersteund:Not all forms of communication are supported by all contexts:

  • Vanuit clients kunt u een signaal sturen naar entiteiten en kunt u de status van de entiteit lezen.From within clients, you can signal entities and you can read the entity state.
  • Vanuit Orchestrations kunt u een signaal sturen naar entiteiten en kunt u entiteiten aanroepen.From within orchestrations, you can signal entities and you can call entities.
  • Vanuit entiteiten kunt u aangeven dat entiteiten moeten worden gesignaleerd.From within entities, you can signal entities.

In de volgende voor beelden ziet u de verschillende manieren waarop entiteiten worden geopend.The following examples illustrate these various ways of accessing entities.

Notitie

In het volgende voor beeld wordt de syntaxis voor het openen van entiteiten weer gegeven.For simplicity, the following examples show the loosely typed syntax for accessing entities. Over het algemeen raden wij u aan om toegang te krijgen tot entiteiten via interfaces , omdat het meer type controle biedt.In general, we recommend that you access entities through interfaces because it provides more type checking.

Voor beeld: client geeft een entiteit aanExample: Client signals an entity

Als u toegang wilt krijgen tot entiteiten van een normale Azure-functie, ook wel bekend als een client functie, gebruikt u de entiteit client uitvoer binding.To access entities from an ordinary Azure Function, which is also known as a client function, use the entity client output binding. In het volgende voor beeld ziet u een door de wachtrij geactiveerde functie waarmee een entiteit wordt gesignaleerd met behulp van deze binding.The following example shows a queue-triggered function signaling an entity using this binding.

[FunctionName("AddFromQueue")]
public static Task Run(
    [QueueTrigger("durable-function-trigger")] string input,
    [DurableClient] IDurableEntityClient client)
{
    // Entity operation input comes from the queue message content.
    var entityId = new EntityId(nameof(Counter), "myCounter");
    int amount = int.Parse(input);
    return client.SignalEntityAsync(entityId, "Add", amount);
}
const df = require("durable-functions");

module.exports = async function (context) {
    const client = df.getClient(context);
    const entityId = new df.EntityId("Counter", "myCounter");
    await context.df.signalEntity(entityId, "add", 1);
};

De term Signal geeft aan dat de aanroep van de entiteits-API in één richting en asynchroon is.The term signal means that the entity API invocation is one-way and asynchronous. Het is niet mogelijk dat een client functie weet wanneer de entiteit de bewerking heeft verwerkt.It's not possible for a client function to know when the entity has processed the operation. De client functie kan ook geen resultaat waarden of uitzonde ringen observeren.Also, the client function can't observe any result values or exceptions.

Voor beeld: client leest de status van een entiteitExample: Client reads an entity state

Client functies kunnen ook een query uitvoeren op de status van een entiteit, zoals wordt weer gegeven in het volgende voor beeld:Client functions can also query the state of an entity, as shown in the following example:

[FunctionName("QueryCounter")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Function)] HttpRequestMessage req,
    [DurableClient] IDurableEntityClient client)
{
    var entityId = new EntityId(nameof(Counter), "myCounter");
    JObject state = await client.ReadEntityStateAsync<JObject>(entityId);
    return req.CreateResponse(HttpStatusCode.OK, state);
}
const df = require("durable-functions");

module.exports = async function (context) {
    const client = df.getClient(context);
    const entityId = new df.EntityId("Counter", "myCounter");
    return context.df.readEntityState(entityId);
};

Entiteits status query's worden verzonden naar het duurzame opslag archief en retour neren de laatst persistente status van de entiteit.Entity state queries are sent to the Durable tracking store and return the entity's most recently persisted state. Deze status is altijd een ' toegezegde ' status, dat wil zeggen dat er nooit een tijdelijke tussenliggende status wordt aangenomen in het midden van het uitvoeren van een bewerking.This state is always a "committed" state, that is, it's never a temporary intermediate state assumed in the middle of executing an operation. Het is echter mogelijk dat deze status is verlopen ten opzichte van de status in het geheugen van de entiteit.However, it's possible that this state is stale compared to the entity's in-memory state. Alleen indelingen kunnen de in-memory status van een entiteit lezen, zoals wordt beschreven in de volgende sectie.Only orchestrations can read an entity's in-memory state, as described in the following section.

Voor beeld: Orchestration signalen en aanroepen van een entiteitExample: Orchestration signals and calls an entity

Orchestrator-functies hebben toegang tot entiteiten met behulp van Api's in de Orchestration-trigger binding.Orchestrator functions can access entities by using APIs on the orchestration trigger binding. De volgende voorbeeld code toont een Orchestrator-functie waarmee een Counter entiteit wordt aangeroepen en gesignaleerd.The following example code shows an orchestrator function calling and signaling a Counter entity.

[FunctionName("CounterOrchestration")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var entityId = new EntityId(nameof(Counter), "myCounter");

    // Two-way call to the entity which returns a value - awaits the response
    int currentValue = await context.CallEntityAsync<int>(entityId, "Get");
    if (currentValue < 10)
    {
        // One-way signal to the entity which updates the value - does not await a response
        context.SignalEntity(entityId, "Add", 1);
    }
}
const df = require("durable-functions");

module.exports = df.orchestrator(function*(context){
    const entityId = new df.EntityId("Counter", "myCounter");

    // Two-way call to the entity which returns a value - awaits the response
    currentValue = yield context.df.callEntity(entityId, "get");
    if (currentValue < 10) {
        // One-way signal to the entity which updates the value - does not await a response
        yield context.df.signalEntity(entityId, "add", 1);
    }
});

Alleen indelingen kunnen het aanroepen van entiteiten en het verkrijgen van een reactie zijn, wat een retour waarde of een uitzonde ring kan zijn.Only orchestrations are capable of calling entities and getting a response, which could be either a return value or an exception. Client functies die gebruikmaken van de client binding kunnen alleen entiteiten Signa leren.Client functions that use the client binding can only signal entities.

Notitie

Het aanroepen van een entiteit vanuit een Orchestrator-functie is vergelijkbaar met het aanroepen van een activiteit functie vanuit een Orchestrator-functie.Calling an entity from an orchestrator function is similar to calling an activity function from an orchestrator function. Het belangrijkste verschil is dat entiteits functies duurzame objecten zijn met een adres, wat de entiteit-ID is.The main difference is that entity functions are durable objects with an address, which is the entity ID. Entiteit functies bieden ondersteuning voor het opgeven van een bewerkings naam.Entity functions support specifying an operation name. Activiteit functies zijn daarentegen stateless en hebben niet het concept van bewerkingen.Activity functions, on the other hand, are stateless and don't have the concept of operations.

Voor beeld: entiteit signaleert een entiteitExample: Entity signals an entity

Een functie entiteit kan signalen verzenden naar andere entiteiten of zelfs zelf, terwijl er een bewerking wordt uitgevoerd.An entity function can send signals to other entities, or even itself, while it executes an operation. We kunnen bijvoorbeeld het voor beeld van de vorige Counter entiteit aanpassen zodat er een ' mijl paal '-signaal wordt verzonden naar een bepaalde monitor-entiteit wanneer de teller de waarde 100 bereikt.For example, we can modify the previous Counter entity example so that it sends a "milestone-reached" signal to some monitor entity when the counter reaches the value 100.

   case "add":
        var currentValue = ctx.GetState<int>();
        var amount = ctx.GetInput<int>();
        if (currentValue < 100 && currentValue + amount >= 100)
        {
            ctx.SignalEntity(new EntityId("MonitorEntity", ""), "milestone-reached", ctx.EntityKey);
        }

        ctx.SetState(currentValue + amount);
        break;
    case "add":
        const amount = context.df.getInput();
        if (currentValue < 100 && currentValue + amount >= 100) {
            const entityId = new df.EntityId("MonitorEntity", "");
            context.df.signalEntity(entityId, "milestone-reached", context.df.instanceId);
        }
        context.df.setState(currentValue + amount);
        break;

Entiteits coördinatieEntity coordination

Het kan voor komen dat u bewerkingen tussen meerdere entiteiten moet coördineren.There might be times when you need to coordinate operations across multiple entities. In een bank toepassing kunt u bijvoorbeeld entiteiten hebben die individuele Bank rekeningen vertegenwoordigen.For example, in a banking application, you might have entities that represent individual bank accounts. Wanneer u fondsen van het ene naar het andere account overbrengt, moet u ervoor zorgen dat het bron account voldoende fondsen heeft.When you transfer funds from one account to another, you must ensure that the source account has sufficient funds. U moet er ook voor zorgen dat updates voor zowel de bron-als de doel accounts worden uitgevoerd op een transactionele consistente manier.You also must ensure that updates to both the source and destination accounts are done in a transactionally consistent way.

Voor beeld: overdracht fondsenC#()Example: Transfer funds (C#)

Met de volgende voorbeeld code worden fondsen tussen twee account entiteiten overgedragen met behulp van een Orchestrator-functie.The following example code transfers funds between two account entities by using an orchestrator function. Voor het coördineren van entiteits updates moet de methode LockAsync worden gebruikt voor het maken van een kritieke sectie in de indeling.Coordinating entity updates requires using the LockAsync method to create a critical section in the orchestration.

Notitie

Voor het gemak wordt in dit voor beeld de eerder gedefinieerde Counter entiteit opnieuw gebruikt.For simplicity, this example reuses the Counter entity defined previously. In een echte toepassing is het beter om een gedetailleerde BankAccount entiteit te definiëren.In a real application, it would be better to define a more detailed BankAccount entity.

// This is a method called by an orchestrator function
public static async Task<bool> TransferFundsAsync(
    string sourceId,
    string destinationId,
    int transferAmount,
    IDurableOrchestrationContext context)
{
    var sourceEntity = new EntityId(nameof(Counter), sourceId);
    var destinationEntity = new EntityId(nameof(Counter), destinationId);

    // Create a critical section to avoid race conditions.
    // No operations can be performed on either the source or
    // destination accounts until the locks are released.
    using (await context.LockAsync(sourceEntity, destinationEntity))
    {
        ICounter sourceProxy = 
            context.CreateEntityProxy<ICounter>(sourceEntity);
        ICounter destinationProxy =
            context.CreateEntityProxy<ICounter>(destinationEntity);

        int sourceBalance = await sourceProxy.Get();

        if (sourceBalance >= transferAmount)
        {
            await sourceProxy.Add(-transferAmount);
            await destinationProxy.Add(transferAmount);

            // the transfer succeeded
            return true;
        }
        else
        {
            // the transfer failed due to insufficient funds
            return false;
        }
    }
}

In .NET retourneert LockAsync IDisposable, waardoor de sectie kritiek wordt beëindigd wanneer deze wordt verwijderd.In .NET, LockAsync returns IDisposable, which ends the critical section when disposed. Dit IDisposable resultaat kan worden gebruikt in combi natie met een using blok om een syntactische weer gave van de sectie kritiek te krijgen.This IDisposable result can be used together with a using block to get a syntactic representation of the critical section.

In het vorige voor beeld heeft een Orchestrator-functie fondsen van een bron entiteit overgezet naar een doel entiteit.In the preceding example, an orchestrator function transferred funds from a source entity to a destination entity. De LockAsync methode heeft de bron-en doel account-entiteiten vergrendeld.The LockAsync method locked both the source and destination account entities. Deze vergren deling heeft gezorgd dat een andere client de status van een van de accounts niet kan opvragen of wijzigen, totdat de indelings logica het kritieke gedeelte aan het einde van de using-instructie heeft verlaten.This locking ensured that no other client could query or modify the state of either account until the orchestration logic exited the critical section at the end of the using statement. Dit gedrag voor komt dat de mogelijkheid van overkomsten van het bron account kan worden verwisseld.This behavior prevents the possibility of overdrafting from the source account.

Notitie

Wanneer een indeling wordt beëindigd, ofwel normaal of met een fout, worden alle kritieke secties die worden uitgevoerd impliciet beëindigd en worden alle vergren delingen vrijgegeven.When an orchestration terminates, either normally or with an error, any critical sections in progress are implicitly ended and all locks are released.

Gedrag van kritieke sectiesCritical section behavior

Met de methode LockAsync maakt u een kritieke sectie in een indeling.The LockAsync method creates a critical section in an orchestration. Deze essentiële secties kunnen voor komen dat andere indelingen overlappende wijzigingen aanbrengen in een opgegeven set entiteiten.These critical sections prevent other orchestrations from making overlapping changes to a specified set of entities. Intern verzendt de LockAsync-API ' Lock '-bewerkingen naar de entiteiten en worden geretourneerd wanneer het antwoord bericht ' lock verworven ' van elk van deze entiteiten wordt ontvangen.Internally, the LockAsync API sends "lock" operations to the entities and returns when it receives a "lock acquired" response message from each of these same entities. Zowel vergren delen als ontgrendelen zijn ingebouwde bewerkingen die door alle entiteiten worden ondersteund.Both lock and unlock are built-in operations supported by all entities.

Er zijn geen bewerkingen van andere clients toegestaan voor een entiteit die een vergrendelde status heeft.No operations from other clients are allowed on an entity while it's in a locked state. Dit gedrag zorgt ervoor dat er slechts één Orchestrator-exemplaar tegelijk een entiteit kan vergren delen.This behavior ensures that only one orchestration instance can lock an entity at a time. Als een aanroeper probeert een bewerking aan te roepen voor een entiteit terwijl deze is vergrendeld door een indeling, wordt die bewerking geplaatst in een wachtrij voor bewerkingen in behandeling.If a caller tries to invoke an operation on an entity while it's locked by an orchestration, that operation is placed in a pending operation queue. Er worden geen bewerkingen verwerkt totdat de vergren deling is vrijgegeven.No pending operations are processed until after the holding orchestration releases its lock.

Notitie

Dit gedrag wijkt enigszins af van synchronisatie primitieven die worden gebruikt in de meeste programmeer talen, zoals de lock C#-instructie in.This behavior is slightly different from synchronization primitives used in most programming languages, such as the lock statement in C#. In C#moet bijvoorbeeld de lock-instructie door alle threads worden gebruikt om de juiste synchronisatie tussen meerdere threads te garanderen.For example, in C#, the lock statement must be used by all threads to ensure proper synchronization across multiple threads. Voor entiteiten hoeven echter niet alle bellers expliciet een entiteit te vergren delen.Entities, however, don't require all callers to explicitly lock an entity. Als een beller een entiteit vergrendelt, worden alle andere bewerkingen op die entiteit geblokkeerd en achter die vergrendeling in de wachtrij geplaatst.If any caller locks an entity, all other operations on that entity are blocked and queued behind that lock.

Vergren delingen op entiteiten zijn duurzaam, zodat ze behouden blijven, zelfs als het uitvoeren van het proces wordt gerecycled.Locks on entities are durable, so they persist even if the executing process is recycled. Vergren delingen worden intern persistent gemaakt als onderdeel van de duurzame status van een entiteit.Locks are internally persisted as part of an entity's durable state.

In tegens telling tot trans acties worden in essentiële secties de wijzigingen in het geval van fouten niet automatisch hersteld.Unlike transactions, critical sections don't automatically roll back changes in the case of errors. In plaats daarvan moet elke fout afhandeling, zoals roll-back of nieuwe poging, expliciet worden gecodeerd, bijvoorbeeld door fouten of uitzonde ringen te ondervangen.Instead, any error handling, such as roll-back or retry, must be explicitly coded, for example by catching errors or exceptions. Deze ontwerp keuze is opzettelijk.This design choice is intentional. Automatisch terugdraaien van de effecten van een indeling is in het algemeen moeilijk of onmogelijk, omdat met indelingen mogelijk activiteiten worden uitgevoerd en aanroepen naar externe services die niet terug kunnen worden gedraaid.Automatically rolling back all the effects of an orchestration is difficult or impossible in general, because orchestrations might run activities and make calls to external services that can't be rolled back. Er kunnen ook pogingen worden gedaan om te worden teruggedraaid en verdere fout afhandeling vereist.Also, attempts to roll back might themselves fail and require further error handling.

Kritieke sectie regelsCritical section rules

In tegens telling tot vergrendelings primitieve op laag niveau in de meeste programmeer talen, zijn essentiële secties gegarandeerd geen deadlock.Unlike low-level locking primitives in most programming languages, critical sections are guaranteed not to deadlock. Om deadlocks te voor komen, moeten we de volgende beperkingen afdwingen:To prevent deadlocks, we enforce the following restrictions:

  • Kritieke secties kunnen niet worden genest.Critical sections can't be nested.
  • In essentiële secties kunnen geen subintegraties worden gemaakt.Critical sections can't create suborchestrations.
  • Kritieke secties kunnen alleen entiteiten aanroepen die ze hebben vergrendeld.Critical sections can call only entities they have locked.
  • Essentiële secties kunnen niet dezelfde entiteit aanroepen met meerdere parallelle aanroepen.Critical sections can't call the same entity using multiple parallel calls.
  • Met kritieke secties kunnen alleen instanties worden gesignaleerd die niet zijn vergrendeld.Critical sections can signal only entities they haven't locked.

Eventuele schendingen van deze regels veroorzaken een runtime-fout, zoals LockingRulesViolationException in .NET, die een bericht bevat waarin wordt uitgelegd welke regel is verbroken.Any violations of these rules cause a runtime error, such as LockingRulesViolationException in .NET, which includes a message that explains what rule was broken.

Vergelijking met virtuele ActorsComparison with virtual actors

Veel van de functies van duurzame entiteiten zijn geïnspireerd op het actor model.Many of the durable entities features are inspired by the actor model. Als u al bekend bent met actors, kunt u veel van de concepten herkennen die in dit artikel worden beschreven.If you're already familiar with actors, you might recognize many of the concepts described in this article. Duurzame entiteiten zijn met name vergelijkbaar met virtuele actoren, of korrels, die zijn gepopulaird door het Orleans-project.Durable entities are particularly similar to virtual actors, or grains, as popularized by the Orleans project. Bijvoorbeeld:For example:

  • Duurzame entiteiten zijn adresseerbaar via een entiteit-ID.Durable entities are addressable via an entity ID.
  • De bewerkingen van een duurzame entiteit worden op een later tijdstip uitgevoerd om race voorwaarden te voor komen.Durable entity operations execute serially, one at a time, to prevent race conditions.
  • Duurzame entiteiten worden impliciet gemaakt wanneer ze worden aangeroepen of gesignaleerd.Durable entities are created implicitly when they're called or signaled.
  • Wanneer er geen bewerkingen worden uitgevoerd, worden duurzame entiteiten op de achtergrond uit het geheugen verwijderd.When not executing operations, durable entities are silently unloaded from memory.

Er zijn enkele belang rijke verschillen die moeten worden opgemerkt:There are some important differences that are worth noting:

  • Duurzame entiteiten bepalen de duurzaamheid over de latentie en zijn dus mogelijk niet geschikt voor toepassingen met strikte latentie vereisten.Durable entities prioritize durability over latency, and so might not be appropriate for applications with strict latency requirements.
  • Duurzame entiteiten hebben geen ingebouwde time-outs voor berichten.Durable entities don't have built-in timeouts for messages. In Orleans time-out voor alle berichten na een Configureer bare tijd.In Orleans, all messages time out after a configurable time. De standaard waarde is 30 seconden.The default is 30 seconds.
  • Berichten die tussen entiteiten worden verzonden, worden betrouwbaar en in de juiste volg orde bezorgd.Messages sent between entities are delivered reliably and in order. In Orleans wordt een betrouw bare of bestelde levering ondersteund voor inhoud die via stromen wordt verzonden, maar niet wordt gegarandeerd voor alle berichten tussen korrels.In Orleans, reliable or ordered delivery is supported for content sent through streams, but isn't guaranteed for all messages between grains.
  • Aanvraag-antwoord patronen in entiteiten zijn beperkt tot de integratie.Request-response patterns in entities are limited to orchestrations. Vanuit entiteiten is alleen eenrichtings berichten (ook wel Signa lering genoemd) toegestaan, zoals in het oorspronkelijke actor model en in tegens telling tot korrels in Orleans.From within entities, only one-way messaging (also known as signaling) is permitted, as in the original actor model, and unlike grains in Orleans.
  • Duurzame entiteiten hebben geen deadlock.Durable entities don't deadlock. In Orleans kunnen deadlocks optreden en worden er pas een time-out van berichten opgelost.In Orleans, deadlocks can occur and don't resolve until messages time out.
  • Duurzame entiteiten kunnen worden gebruikt in combi natie met duurzame Orchestrations en bieden ondersteuning voor gedistribueerde vergrendelings mechanismen.Durable entities can be used in conjunction with durable orchestrations and support distributed locking mechanisms.

Volgende stappenNext steps