[Canonical page](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/assignment-data/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# AssignmentData

Books one resource on one task at a utilization rate. `Offset` and `Duration` can narrow the booking to a slice of the task's work. Assignments go in [`ProjectData.Assignments`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/project-data.md>) or in a [`SchedulingChanges.Assignments`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/scheduling-changes.md>)`.Add` list. Build one with an object initializer; `Task`, `Resource` and `Value` are `required`. To change an assignment that a project already holds, send an [`AssignmentUpdate`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/assignment-update.md>).

## Declaration

```csharp
namespace Plen;

public sealed class AssignmentData : IDeepCloneable<AssignmentData>
```

`AssignmentData` has no constructor that sets the required properties, so `new AssignmentData()` without `Task`, `Resource` and `Value` doesn't compile.

## Properties

| Property | Type | Default | Description |
|---|---|---|---|
| `Id` | [`Id?`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>) | `null` | Assignment id, unique among the project's assignments. `null` generates one on import. |
| `Task` | [`Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>) | required | Id of the task. |
| `Resource` | [`Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>) | required | Id of the resource. |
| `Value` | `double` | required | Units booked, in the scale of the resource's capacity. `1` is 100 %. |
| `Offset` | `double?` | `null` | Start of the slice: worked time from the task start, in the task's duration unit. `null` means `0`. |
| `Duration` | `double?` | `null` | Length of the slice in worked time. `null` books up to the task end. |

### Id

```csharp
public Id? Id { get; set; }
```

The key that results and change sets use to refer to this assignment, for example in [`Note.DroppedAssignment`](<https://docs.dhtmlx.com/planning-engine/net/api/core/results/note.md>) and in [`AssignmentUpdate.Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/assignment-update.md#properties>). A `null` id gets a generated string id on import that never collides with an explicit id in the same snapshot. Give each assignment an explicit id when later edits must address it.

### Task, Resource

```csharp
public required Id Task { get; set; }
public required Id Resource { get; set; }
```

The booked task and resource. Both must name a record in the same snapshot. An assignment on an unscheduled task stays in the project but books no load, and the result reports it as a [`Note.DroppedAssignment`](<https://docs.dhtmlx.com/planning-engine/net/api/core/results/note.md>). One resource can have several assignments on one task; each books its own slice at its own `Value`, and overlapping slices add up.

### Value

```csharp
public required double Value { get; set; }
```

The share of the resource the assignment books while it works, in the same units as [`ResourceData.Capacity`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/resource-data.md>). `0.5` is half-time. Must be finite and greater than `0`.

### Offset, Duration

```csharp
public double? Offset { get; set; }
public double? Duration { get; set; }
```

Narrow the booking to a slice of the task's work. The slice runs from worked time `Offset` to `Offset + Duration`, clipped to the task's work. Both `null` books the whole task, and an `Offset` at or past the task's work books nothing.

Both values are worked time in the task's [`DurationUnit`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/task-data.md>): non-working time and pause time don't count, so the slice moves with the work when leveling delays or splits the task. Clipping happens when load is booked, so a slice follows a task that later gets shorter.

A slice changes resource load only. Task dates never depend on `Offset` or `Duration`, and editing them never moves a task. See [Assignment slices](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/resources-and-assignments.md#assignment-slices>) for how slices are measured and booked.

`Offset` must be finite and `0` or greater. `Duration` must be finite and greater than `0`.

## Methods

### DeepClone

```csharp
public AssignmentData DeepClone()
```

Returns a copy with the same property values.

### ToString

```csharp
public override string ToString()
```

Returns a readable rendering of every property, for logging.

`AssignmentData` doesn't override `Equals`; two instances compare by reference.

## Errors

The snapshot is validated when it's passed to [`Engine.Schedule`](<https://docs.dhtmlx.com/planning-engine/net/api/engine-schedule.md>) or [`Project.Solve(data, …)`](<https://docs.dhtmlx.com/planning-engine/net/api/project-solve.md>). An assignment makes the call throw [`InputException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/input-exception.md>) with `Kind = `[`InputErrorKind.Validation`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/input-exception.md#inputerrorkind>) when:

- its `Id` repeats the id of an earlier assignment: `Path = "assignments[i].id"`
- its `Value` isn't finite or is `0` or less: `Path = "assignments[i].value"`
- its `Offset` isn't finite or is less than `0`: `Path = "assignments[i].offset"`
- its `Duration` isn't finite or is `0` or less: `Path = "assignments[i].duration"`
- its `Resource` names no resource: `Path = "assignments[i].resource"`
- its `Task` names no task: `Path = "assignments[i].task"`
- in [`CalendarMode.Resource`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/calendar-mode.md>), the task's calendar and the resource's calendar share no weekly working time: `Path = "assignments[i]"`

These checks apply to assignments on unscheduled tasks too. [`Validation.Repair`](<https://docs.dhtmlx.com/planning-engine/net/api/core/project/validation.md>) fixes two of these cases instead of throwing. A repeated id replaces the earlier assignment at the earlier position. An invalid `Offset` or `Duration` is cleared to `null`. Each repair adds a [`Note.Repaired`](<https://docs.dhtmlx.com/planning-engine/net/api/core/results/note.md#repaired>) to the result.

Assignments added or edited after the first solve go through [`SchedulingChanges.Assignments`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/scheduling-changes.md>). An invalid one there is a rejected operation in the [`ApplyReport`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/apply-report.md>), not an exception.

## Example

Ann works full-time on task 1. Ben reviews it half-time, on the last of its five days only:

```csharp
using Plen;

var start = Moment.FromYmdHm(2026, 4, 6, 8, 0)
    ?? throw new InvalidOperationException("invalid date");

var data = new ProjectData
{
    Tasks =
    [
        new TaskData(1) { StartDate = start, Duration = 5.0 },
    ],
    Resources =
    [
        new ResourceData { Id = "ann" },
        new ResourceData { Id = "ben" },
    ],
    Assignments =
    [
        new AssignmentData { Id = "a1", Task = 1, Resource = "ann", Value = 1.0 },
        new AssignmentData
        {
            Id = "a2",
            Task = 1,
            Resource = "ben",
            Value = 0.5,
            Offset = 4.0,
            Duration = 1.0,
        },
    ],
};

var result = Engine.Schedule(data, new SolveOptions());
Console.WriteLine(result.Overallocations?.Count ?? 0);
```

## Related

- [`ResourceData`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/resource-data.md>) - the booked resource
- [`AssignmentUpdate`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/assignment-update.md>) - edits an existing assignment
- [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/project-data.md>) - the snapshot that holds assignments
- [Resources and assignments](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/resources-and-assignments.md>) - capacity, assignments and slices
- [Split assignment work](<https://docs.dhtmlx.com/planning-engine/net/how-to/split-assignment-work.md>) - booking part of a task
