# DBDownloader

This class provides functionality for downloading data from a database and storing the result in a provided class. It supports multithreaded asynchronous calls, and allows for a queue of threaded download operations. It has automatic retry capability built in.

The type of DB Connection passed determines the database language it uses. You could for example provide a MySql connection instead.

{% hint style="info" %}
It's like saying, "Hey downloader, I have a class with several properties I want filled from my database, take care of the rest".
{% endhint %}

#### Quick implementation

```csharp
//Generate a connection string with custom properties set
string _CNS() => new SqlConnectionStringBuilder(c.GetConnectionString("main")) { Pooling = true, MaxPoolSize = 200, MultipleActiveResultSets = false, PacketSize = 32767 }.ToString();

//Create an instance of our data class with proeprties to hold results
var DataObject = new CircuitData();

//Allocate and assign with downloader extension.
var dl = Downloader.DBDownloader(DataObject, () => new SqlConnection(_CNS()))
    .Assign(f => f.circuits, "SELECT ID,Type,Name from dbo.Circuit", ConnectionPreExecute: "SET ARITHABORT ON")
    .Assign(f => f.circuitTypes, "SELECT * from util.CircuitType", ConnectionPreExecute: "SET ARITHABORT ON")
    
    //Wait can be called inline, or later! 
    //    You can proceed to do other operations until data is needed
    .Wait();

Console.WriteLine($"DL time: {dl.GetDownloadTime().TotalMilliseconds:F0}");
```

### Downloader Extension

There is an easy way to create the DBDownloader by using the static extension method.

```csharp
Downloader.DBDownloader(InClass, () => new Connection());
```

### Assign / AssignSingle

Assigns the downloaded data to a property of the base object. Can be called multiple times using fluent syntax to fill multiple properties. The downloader automatically manages the multithreaded and asyhcnronous operations for filling each property.

It uses [Dapper](https://github.com/DapperLib/Dapper) behind the scenes to perform the mapping and query execution. If you want to supply parameters, you can use the <mark style="color:blue;">`object`</mark>`Param` parameter.

If you're not assigning a list, but a single object, use `AssignSingle()`.

#### Example:

```csharp
var downloader = new DBDownloader<MyClass>(myInstance, connectionFactory);
downloader.Assign(x => x.PropertyName, "SELECT * FROM table");
```

### Wait

Waits for all download tasks to complete. This can be called inline or later right before the downloaded data is required. It is thread blocking.

#### Example:

```csharp
downloader.Wait();
```

### GetDownloadTime

Gets the total time taken for all download tasks to complete.

#### Example:

```csharp
TimeSpan totalTime = downloader.GetDownloadTime();
```

### Downloads

You can get to the list of tasks created by accessing this property.&#x20;

Every DownloadResult has properties for the success boolean, if an exception was thrown, the name of the property it set, and dates to indicate start and end times.&#x20;

```csharp
List<Task<DownloadResult>> Downloads;
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.perigee.software/core-modules/utility-classes/dbdownloader.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
