Skip to content

Instantly share code, notes, and snippets.

@petevb
Last active May 16, 2018 08:03
Show Gist options
  • Save petevb/f0b47873ef36eeb4e50a29a9c3871071 to your computer and use it in GitHub Desktop.
Save petevb/f0b47873ef36eeb4e50a29a9c3871071 to your computer and use it in GitHub Desktop.
[LINQPad to CosmosDB (local emulator)] https://gist.github.com/stuarthallows/999db511fc80c4d9891265088ac3e271 #CosmosDB #LINQPad
// Write code to test your extensions here. Press F5 to compile and run.
void Main()
{
Fetch();
Create();
}
void Fetch()
{
var src = new TtcDBRepository(BaseRepository.LocalEmulator);
var todos = src.GetItemsAsync<TodoItem>(item => true);
todos.Result.Dump();
}
void Create()
{
var source = new DocumentDBRepository(BaseRepository.LocalEmulator /*, null, "ToDoList", "Items"*/);
var all = source.GetItemsAsync<TodoItem>(item => true).Result;
all.Dump();
var dest = new DocumentDBRepository(BaseRepository.LocalEmulator, null, "Backups", "TodoList-Items");
foreach (var doc in all)
{
doc.PartitionKey = doc.PartitionKey;
var newItem = dest.CreateItemAsync(doc).Result;
newItem.Dump();
}
var backup = dest.GetItemsAsync<TodoItem>(item => true).Result;
backup.Dump();
}
public static class MyExtensions
{
// Write custom extension methods here. They will be available to all queries.
}
public class TodoItem : Document
{
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "isComplete")]
public bool Completed { get; set; }
}
public class Document : Microsoft.Azure.Documents.Document, IPartitionKey
{
[JsonProperty(PropertyName = "partitionKey")]
public string PartitionKey { get; set; }
[JsonProperty(PropertyName = "dateModified")]
public DateTime? DateModified
{
get
{
return this.Timestamp;
}
}
}
// You can also define non-static classes, enums, etc.
public class CosmosDBDocument : IDocument, IPartitionKey
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "partitionKey")]
public string PartitionKey { get; set; }
[JsonProperty(PropertyName = "dateCreated")]
public DateTime DateCreated { get; set; }
[JsonProperty(PropertyName = "dateModified")]
public DateTime? DateModified { get; set; }
[JsonProperty(PropertyName = "_etag")]
public string ETag { get; set; }
[JsonProperty(PropertyName = "_self")]
public string SelfIdentifier { get; set; }
}
public interface IDocument : IPartitionKey
{
// [JsonProperty(PropertyName = "id")]
// string Id { get; set; }
// [JsonProperty(PropertyName = "partitionKey")]
// new string PartitionKey { get; set; }
DateTime DateCreated { get; set; }
new DateTime? DateModified { get; set; }
[JsonProperty(PropertyName = "_etag")]
new string ETag { get; set; }
[JsonProperty(PropertyName = "_self")]
string SelfIdentifier { get; set; }
}
public interface IPartitionKey
{
[JsonProperty(PropertyName = "id")]
string Id { get; set; }
[JsonProperty(PropertyName = "partitionKey")]
string PartitionKey { get; }
[JsonProperty(PropertyName = "_etag")]
string ETag { get; }
DateTime? DateModified { get; }
}
public class DocumentDBRepository : BaseRepository
{
public DocumentDBRepository(string endpoint = null, string token = null, string databaseId = "ToDoList", string collectionId = "Items")
: base(endpoint, token, databaseId, collectionId)
{
}
public new async Task<T> CreateItemAsync<T>(T item) where T : Document
{
return await base.CreateItemAsync<T>(item);
}
public async Task<Document> GetItemAsync(string id)
{
return await base.GetItemAsync<Document>(id);
}
public async Task<IEnumerable<Document>> GetItemsAsync(Expression<Func<Document, bool>> predicate)
{
return await base.GetItemsAsync<Document>(predicate);
}
}
public class TtcDBRepository : BaseRepository
{
public TtcDBRepository(string endpoint = null, string token = null, string databaseId = "ToDoList", string collectionId = "Items")
: base(endpoint, token, databaseId, collectionId)
{
}
public async new Task<T> CreateItemAsync<T>(T item) where T : class, IDocument
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
if (string.IsNullOrWhiteSpace(item.Id))
{
throw new ArgumentException("Cannot add to repository; item has a blank Id", nameof(item));
}
if (string.IsNullOrWhiteSpace(item.PartitionKey))
{
throw new ArgumentException("Cannot add to repository; item has a blank PartitionKey", nameof(item));
}
if (item.DateCreated != DateTime.MinValue)
{
// item.DateCreated = item.DateCreated;
item.DateModified = DateTime.UtcNow;
}
else
{
item.DateCreated = DateTime.UtcNow;
// item.DateModified = null;
}
var collectionUri = UriFactory.CreateDocumentCollectionUri(this.databaseId, this.collectionId);
var response = await this.client.CreateDocumentAsync(collectionUri, item);
item.ETag = response.Resource.ETag;
item.SelfIdentifier = response.Resource.SelfLink;
return item;
}
}
public class BaseRepository
{
public const string LocalEmulator = "https://localhost:8081/";
// local emulator key is publicly available (https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator).
private const string LocalKey = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
protected string databaseId = "ToDoList";
protected string collectionId = "Items";
protected DocumentClient client;
protected BaseRepository(string endpoint = null, string token = null, string databaseId = "ToDoList", string collectionId = "Items")
{
endpoint = getEndpoint(endpoint);
token = getAuthKey(token);
client = new DocumentClient(new Uri(endpoint), token);
this.databaseId = databaseId;
this.collectionId = collectionId;
CreateDatabaseIfNotExistsAsync().Wait();
CreateCollectionIfNotExistsAsync().Wait();
}
public async Task<T> GetItemAsync<T>(string id) where T : class, IPartitionKey
{
try
{
var documentUri = UriFactory.CreateDocumentUri(this.databaseId, this.collectionId, id);
Microsoft.Azure.Documents.Document document = await client.ReadDocumentAsync(documentUri);
return (T)(dynamic)document;
}
catch (DocumentClientException e) when (e.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return null;
}
}
public async Task<IEnumerable<T>> GetItemsAsync<T>(Expression<Func<T, bool>> predicate) where T : class, IPartitionKey
{
var collectionUri = UriFactory.CreateDocumentCollectionUri(this.databaseId, this.collectionId);
IDocumentQuery<T> query = client.CreateDocumentQuery<T>(
collectionUri,
new FeedOptions
{
MaxItemCount = -1,
EnableCrossPartitionQuery = true
})
.Where(predicate)
.AsDocumentQuery();
List<T> results = new List<T>();
while (query.HasMoreResults)
{
results.AddRange(await query.ExecuteNextAsync<T>());
}
return results;
}
protected virtual async Task<T> CreateItemAsync<T>(T item) where T : class, IPartitionKey
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
var collectionUri = UriFactory.CreateDocumentCollectionUri(this.databaseId, this.collectionId);
var requestOptions = item.PartitionKey == null ? null : new RequestOptions { PartitionKey = new PartitionKey(item.PartitionKey) };
Microsoft.Azure.Documents.Document document = await client.CreateDocumentAsync(collectionUri, item, requestOptions);
item.Id = document.Id;
return item;
}
public async Task<T> UpdateItemAsync<T>(string id, T item) where T : class, IPartitionKey
{
var documentUri = UriFactory.CreateDocumentUri(this.databaseId, this.collectionId, id);
var document = await this.client.ReplaceDocumentAsync(documentUri, item);
return (T)(dynamic)document.Resource;
}
public async Task DeleteItemAsync(string id)
{
var documentUri = UriFactory.CreateDocumentUri(this.databaseId, this.collectionId, id);
await this.client.DeleteDocumentAsync(documentUri);
}
private async Task CreateDatabaseIfNotExistsAsync()
{
try
{
var databaseUri = UriFactory.CreateDatabaseUri(this.databaseId);
await client.ReadDatabaseAsync(databaseUri);
}
catch (DocumentClientException e) when (e.StatusCode == System.Net.HttpStatusCode.NotFound)
{
await client.CreateDatabaseAsync(new Database { Id = this.databaseId });
}
}
private async Task CreateCollectionIfNotExistsAsync()
{
try
{
var collectionUri = UriFactory.CreateDocumentCollectionUri(this.databaseId, this.collectionId);
await client.ReadDocumentCollectionAsync(collectionUri);
}
catch (DocumentClientException e) when (e.StatusCode == System.Net.HttpStatusCode.NotFound)
{
var databaseUri = UriFactory.CreateDatabaseUri(this.databaseId);
await client.CreateDocumentCollectionAsync(
databaseUri,
new DocumentCollection { Id = this.collectionId },
new RequestOptions { OfferThroughput = 400 });
}
}
private string getEndpoint(string endpoint = null)
{
if (string.IsNullOrWhiteSpace(endpoint))
{
endpoint = Util.ReadLine("endpoint (or blank for local emulator)");
endpoint = string.IsNullOrWhiteSpace(endpoint) ? LocalEmulator : endpoint;
}
return endpoint;
}
private string getAuthKey(string authKey = null)
{
if (string.IsNullOrWhiteSpace(authKey))
{
authKey = Util.GetPassword("auth key");
authKey = string.IsNullOrWhiteSpace(authKey) ? BaseRepository.LocalKey : authKey;
}
return authKey;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment