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


# ProfileQuery

Describes what a load profile covers: a date range, the resources, the bucket size and which buckets list their tasks. Create one with `new ProfileQuery(from, to)` and pass it to [`Project.LoadProfile`](<https://docs.dhtmlx.com/planning-engine/net/api/project-load-profile.md>) or set it as [`PreviewOptions.Profile`](<https://docs.dhtmlx.com/planning-engine/net/api/core/project/preview-options.md>).

## Declaration

```csharp
namespace Plen;

public sealed class ProfileQuery : IDeepCloneable<ProfileQuery>
{
    public ProfileQuery(Moment from, Moment to);

    public Moment From { get; set; }
    public Moment To { get; set; }
    public List<Id>? Resources { get; set; }
    public Basis? Basis { get; set; }
    public ProfileTasks Tasks { get; set; } = ProfileTasks.None;

    public ProfileQuery DeepClone();
}
```

`ProfileQuery` converts implicitly to [`LoadProfileOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/load-profile-options.md>), so `project.LoadProfile(query)` compiles without wrapping the query. It doesn't implement `IEquatable<T>`, so two instances compare by reference.

## Constructors

### ProfileQuery(Moment, Moment)

```csharp
public ProfileQuery(Moment from, Moment to)
```

Creates a query over `[from, to)` for every resource, on the derived basis, with no task lists.

| Name | Type | Description |
|---|---|---|
| `from` | [`Moment`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/moment.md>) | Start of the range (inclusive). |
| `to` | `Moment` | End of the range (exclusive). |

The constructor doesn't validate the range. The call that reads the query checks it.

## Properties

| Property | Type | Default | Description |
|---|---|---|---|
| `From` | [`Moment`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/moment.md>) | constructor argument | Start of the range. The profile holds every bucket whose start lies in `[From, To)`. |
| `To` | `Moment` | constructor argument | End of the range (exclusive). |
| `Resources` | `List<`[`Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>)`>?` | `null` | Resources to profile, in this order. `null` profiles every resource. |
| `Basis` | [`Basis`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/basis.md>)`?` | `null` | Bucket size. `null` derives it from [`SchedulingConfig.DurationUnit`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/scheduling-config.md>). |
| `Tasks` | [`ProfileTasks`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/profile-tasks.md>) | `ProfileTasks.None` | Which buckets list their booked tasks in [`LoadBucket.Tasks`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/load-profile.md>). |

### Validation

[`Project.LoadProfile`](<https://docs.dhtmlx.com/planning-engine/net/api/project-load-profile.md>) and [`Project.Preview`](<https://docs.dhtmlx.com/planning-engine/net/api/project-preview.md>) throw an [`InputException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/input-exception.md>) for an invalid query:

| Path | When |
|---|---|
| `to` | `To <= From`, or the range holds more than 100 000 buckets per resource |
| `resources` | `Resources` names a resource that isn't in the project |

## Methods

### DeepClone

```csharp
public ProfileQuery DeepClone()
```

Returns a copy that shares no list with this one.

## Example

```csharp
using Plen;

var monday = Moment.FromYmdHm(2026, 1, 5, 0, 0) ?? throw new InvalidOperationException("invalid date");
var nextMonday = Moment.FromYmdHm(2026, 1, 12, 0, 0) ?? throw new InvalidOperationException("invalid date");

var data = new ProjectData
{
    Tasks =
    [
        new TaskData("design") { StartDate = monday, Duration = 3.0 },
        new TaskData("review") { StartDate = monday, Duration = 2.0 },
    ],
    Resources = [new ResourceData { Id = "dev1" }],
    Assignments =
    [
        new AssignmentData { Task = "design", Resource = "dev1", Value = 1.0 },
        new AssignmentData { Task = "review", Resource = "dev1", Value = 0.5 },
    ],
};

var project = new Project();
project.Solve(data, new SolveOptions());

var query = new ProfileQuery(monday, nextMonday)
{
    Resources = ["dev1"],
    Basis = Basis.Day,
    Tasks = ProfileTasks.Over,
};

var profile = project.LoadProfile(query);

foreach (var bucket in profile.Resources[0].Buckets)
    Console.WriteLine($"{bucket.Start}: {bucket.Load} / {bucket.Capacity}");
```

## Related

- [`Project.LoadProfile`](<https://docs.dhtmlx.com/planning-engine/net/api/project-load-profile.md>) - the call that takes the query
- [`LoadProfileOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/load-profile-options.md>) - the query plus a baseline check
- [`LoadProfile`](<https://docs.dhtmlx.com/planning-engine/net/api/core/resources/load-profile.md>) - the returned profile
- [`PreviewOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/project/preview-options.md>) - a load profile of previewed dates
- [Resource load](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/resource-load.md#narrowing-the-query>) - querying a profile and drawing a resource histogram
