TableStorage.Abstractions
2.1.0
See the version list below for details.
dotnet add package TableStorage.Abstractions --version 2.1.0
NuGet\Install-Package TableStorage.Abstractions -Version 2.1.0
<PackageReference Include="TableStorage.Abstractions" Version="2.1.0" />
paket add TableStorage.Abstractions --version 2.1.0
#r "nuget: TableStorage.Abstractions, 2.1.0"
// Install TableStorage.Abstractions as a Cake Addin #addin nuget:?package=TableStorage.Abstractions&version=2.1.0 // Install TableStorage.Abstractions as a Cake Tool #tool nuget:?package=TableStorage.Abstractions&version=2.1.0
TableStorage.Abstractions
Repository wrapper for Azure Table Storage in C# .NET 4.5.2, .NET 4.6, .NET 4.6.1
Starting work with Azure Table Storage has been interesting and very different from working with SQL Server which I have done for many years. After reading a number of articles about it and using it I realised a generic wrapper would be useful to create and so this is that creation.
Based on multiple articles from Microsoft and others to try and get a performant wrapper and aid unit testing of code using Azure Table Storage.
https://azure.microsoft.com/en-gb/blog/managing-concurrency-in-microsoft-azure-storage-2/
https://docs.microsoft.com/en-us/azure/storage/storage-table-design-guide
https://docs.particular.net/nservicebus/azure-storage-persistence/performance-tuning
http://robertgreiner.com/2012/06/why-is-azure-table-storage-so-slow/
Optimisations are controlled by the Table Storage Options Class. The defaults are applied as below if not overridden:
public class TableStorageOptions
{
public bool UseNagleAlgorithm { get; set; } = false;
public bool Expect100Continue { get; set; } = false;
public int ConnectionLimit { get; set; } = 10;
public int Retries { get; set; } = 3;
public double RetryWaitTimeInSeconds { get; set; } = 1;
public bool EnsureTableExists { get; set; } = true;
}
Example entity:
public class TestTableEntity : TableEntity
{
public int Age { get; set; }
public string Email { get; set; }
public TestTableEntity() {}
public TestTableEntity(string name, string surname)
{
PartitionKey = surname;
RowKey = name;
}
}
Example usage:
var tableStorage = new TableStore<TestTableEntity>("MyTable", "UseDevelopmentStorage=true");
var entity = new TestTableEntity("John", "Smith") { Age = 21, Email = "john.smith@something.com" };
await tableStorage.InsertAsync(entity);
// Get the entries by the row key
var result = tableStorage.GetByRowKey("John").ToList();
Inserting multiple entries into table storage requires each entry to have the same partition key for a batch. This implementation in the wrapper does this job for you so that you can just pass a list of entities.
Example Insert of multiple records
var tableStorage = new TableStore<TestTableEntity>("MyTable", "UseDevelopmentStorage=true");
var entries = new List<TestTableEntity>
{
new TestTableEntity("John", "Smith") {Age = 21, Email = "john.smith@something.com"},
new TestTableEntity("Jane", "Smith") {Age = 28, Email = "jane.smith@something.com"},
new TestTableEntity("Bill", "Smith") { Age = 38, Email = "bill.smith@another.com"},
new TestTableEntity("Fred", "Jones") {Age = 32, Email = "fred.jones@somewhere.com"},
new TestTableEntity("Bill", "Jones") {Age = 45, Email = "bill.jones@somewhere.com"},
new TestTableEntity("Bill", "King") {Age = 45, Email = "bill.king@email.com"},
new TestTableEntity("Fred", "Bloggs") { Age = 32, Email = "fred.bloggs@email.com" }
};
await tableStorage.InsertAsync(entries);
The library also includes a factory class to make it easier when using dependency injection
public class TestTableStorageClient
{
private ITableStore<MyStuff> _store;
public TestTableStorageClient(ITableStoreFactory factory)
{
_store = factory.CreateTableStore<MyStuff>("MyTable", "UseDevelopmentStorage=true");
}
}
Table Storage does not really have generic way of filtering data as yet. So there are some methods to help with that. NOTE: The filtering works by getting all records so on large datasets this will be slow. Testing showed ~1.3 seconds for 10,000 records Testing when paged by 100 ~0.0300 seconds for 10,000 records returning 100 records
var tableStorage = new TableStore<TestTableEntity>("MyTable", "UseDevelopmentStorage=true");
var results = tableStorage.GetRecordsByFilter(x => x.Age > 21 && x.Age < 25);
And with basic paging starting at 0 and returning 100 NOTE: The start is number of records e.g. 20, 100 would start at record 20 and then return a maxiumum of 100 after that
var tableStorage = new TableStore<TestTableEntity>("MyTable", "UseDevelopmentStorage=true");
var results = tableStorage.GetRecordsByFilter(x => x.Age > 21 && x.Age < 25, 0, 100);
There is also the consideration of using Reactive Extensions (RX - http://reactivex.io/) to observe the results from a get all records call or a get filtered records.
var tableStorage = new TableStore<TestTableEntity>("MyTable", "UseDevelopmentStorage=true");
var theObserver = tableStorage.GetAllRecordsObservable();
theObserver.Where(x => x.Age > 21 && x.Age < 25).Take(100).Subscribe(x =>
{
// Do something with the table entry
});
or
var tableStorage = new TableStore<TestTableEntity>("MyTable", "UseDevelopmentStorage=true");
var theObserver = tableStorage.GetRecordsByFilterObservable(x => x.Age > 21 && x.Age < 25, 0, 100);
theObserver.Subscribe(x =>
{
// Do something with the table entry
});
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET Framework | net452 is compatible. net46 is compatible. net461 is compatible. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
-
- FluentValidation (>= 7.5.2)
- System.Reactive (>= 3.1.1)
- System.Reactive.Linq (>= 3.1.1)
- Useful.Extensions (>= 2.1.0)
- WindowsAzure.Storage (>= 9.1.1)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on TableStorage.Abstractions:
Package | Downloads |
---|---|
TableStorage.Abstractions.POCO
A repository wrapper for Azure Table Storage that uses POCOs (Plain Old CLR Objects) instead of objects that implemeent ITableEntity. The Azure Storage SDK requires that objects that it works with to implement the ITableEntity interface. This puts us into one of two places that are often not desirable: You implement the ITableEntity interace, or inherit from TableEntity. This is easy, but now you've got a leaky abstraction, as well as properties that won't make much sense in your domain (e.g. instead of a UserId, you've now got a RowKey, of the wrong type), or you have fields that are out of place, like ETag and Timestamp. You create DTOs to save to ship data back and forth from the domain to Table Storage. This is a common style, but often is overkill, especially if we're just looking for a simple abstraction on top of Azure Table Storage. This simple library seeks to take care of the mapping for us, so that you can continue to write your domain objects as POCOs, while still being able to leverage the Azure Storage SDK. The library will convert simple properties to fields in Azure Table Storage. Complex types will serialize as json. |
|
TableStorage.Abstractions.Trie
An implementation of a trie-like data structure using Azure Table Storage to enable type-ahead style searching. Targets netcoreapp2.1, netstandard2.0 and net461. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
3.3.10 | 54,766 | 6/11/2023 |
3.3.9 | 595 | 6/11/2023 |
3.3.7 | 1,793 | 2/7/2023 |
3.3.6 | 698 | 2/4/2023 |
3.3.0 | 27,781 | 1/15/2022 |
3.2.4 | 28,037 | 11/7/2020 |
3.2.2 | 7,132 | 5/3/2020 |
3.2.1 | 1,182 | 5/3/2020 |
3.1.0 | 11,308 | 2/23/2020 |
3.0.1-preview | 1,055 | 2/2/2020 |
3.0.0 | 1,558 | 1/26/2020 |
2.3.0 | 28,002 | 4/28/2019 |
2.2.0 | 8,409 | 1/6/2019 |
2.1.2 | 3,559 | 10/8/2018 |
2.1.1 | 1,982 | 7/1/2018 |
2.1.0 | 1,750 | 4/22/2018 |
2.0.0 | 1,954 | 2/11/2018 |
1.1.1 | 3,226 | 2/11/2018 |
1.1.0 | 6,446 | 9/3/2017 |
1.0.6 | 9,703 | 8/22/2017 |
1.0.5 | 1,807 | 8/19/2017 |
1.0.4 | 1,814 | 8/19/2017 |
1.0.3 | 1,628 | 7/29/2017 |
1.0.2 | 1,672 | 1/8/2017 |
1.0.1 | 4,610 | 11/20/2016 |
Added time string style searching to most of the search methods. The time can be specified using value and time type e.g. 10m for 10 minutes, 1h for 1 hour, 1d for 1 day, etc.