How do I re-use Azure Cosmos UDFs? - azure

I am using a User Defined Function across multiple collections within multiple Cosmos databases. Is there a way to store it somewhere and deploy it to all of these collections/databases at once? Or a way to update them all at the same time? Currently I am having to go through and manually update each UDF within each collection within each database.

You can write console application for updating UDF-
private async Task<string> CreateUDFAsync(string collectionUri, string udfName, string udfBody)
{
ResourceResponse<UserDefinedFunction> response = null;
try
{
var existingUdf = await this.cosmosDbClient.ReadUserDefinedFunctionAsync($"{collectionUri}/udfs/{udfName}");
existingUdf.Resource.Body = udfBody;
response = await this.cosmosDbClient.ReplaceUserDefinedFunctionAsync(existingUdf.Resource);
}
catch (DocumentClientException ex)
{
response = await this.cosmosDbClient.CreateUserDefinedFunctionAsync(collectionUri,
new UserDefinedFunction
{
Id = udfName,
Body = udfBody
});
}
return response.Resource.AltLink;
}
It will replace existing UDF and Create new in case missing

At the Cosmos DB resource model structure stored procedures, UDFs, merge procedures, triggers and conflicts are Container level resources.
You have to create them for each container.

Related

Cosmos DB: How to detect request charges with LINQ queries

In Cosmos DB v3, I'm getting an IOrderedQueryable<T> using GetItemLinqQueryable<T>. This allows me to write custom queries. The problem is I'd like to track request charges whenever a query is materialized. How can this be accomplished?
When I execute methods like ReadItemAsyncand ExecuteStoredProcedureAsync, the returned object has a RequestCharge property, but I need to detect charges with linq queries.
You can use the extension method ToFeedIterator on your IOrderedQueryable.
using Microsoft.Azure.Cosmos.Linq;
var query = container.GetItemLinqQueryable<MyClass>()
.Where(c => true)
.ToFeedIterator();
while (query.HasMoreResults)
{
var response = await query.ReadNextAsync();
Console.WriteLine(response.RequestCharge);
foreach (var myClassInstance in response)
{
// do stuff
}
}
edit: if you need count or any aggregate function:
var query = container.GetItemLinqQueryable<MyClass>()
.Where(c => true);
Response<int> x = await query.CountAsync();
Console.WriteLine(x.RequestCharge);
int count = x; // Autoboxing
You can find the full list of available extension functions on GitHub.

Kusto Query from c#

I want to retrieve data from Kusto DB from c# app can any one help me on this.
I have knowledge on writing the Kusto queries but I need some help on pulling data from Azure Kusto DB hosted in Azure.
I tried the following code but it's not working:
var client = Kusto.Data.Net.Client.KustoClientFactory.CreateCslQueryProvider("https://help.kusto.windows.net/Samples;Fed=true");
var reader = client.ExecuteQuery("MyTable | count");
// Read the first row from reader -- it's 0'th column is the count of records in MyTable
// Don't forget to dispose of reader when done.
Could you please elaborate what's not working (what is the error message you're getting) with the code above?
In addition, a full (though simple) example can be found below:
// This sample illustrates how to query Kusto using the Kusto.Data .NET library.
//
// For the purpose of demonstration, the query being sent retrieves multiple result sets.
//
// The program should execute in an interactive context (so that on first run the user
// will get asked to sign in to Azure AD to access the Kusto service).
class Program
{
const string Cluster = "https://help.kusto.windows.net";
const string Database = "Samples";
static void Main()
{
// The query provider is the main interface to use when querying Kusto.
// It is recommended that the provider be created once for a specific target database,
// and then be reused many times (potentially across threads) until it is disposed-of.
var kcsb = new KustoConnectionStringBuilder(Cluster, Database)
.WithAadUserPromptAuthentication();
using (var queryProvider = KustoClientFactory.CreateCslQueryProvider(kcsb))
{
// The query -- Note that for demonstration purposes, we send a query that asks for two different
// result sets (HowManyRecords and SampleRecords).
var query = "StormEvents | count | as HowManyRecords; StormEvents | limit 10 | project StartTime, EventType, State | as SampleRecords";
// It is strongly recommended that each request has its own unique
// request identifier. This is mandatory for some scenarios (such as cancelling queries)
// and will make troubleshooting easier in others.
var clientRequestProperties = new ClientRequestProperties() { ClientRequestId = Guid.NewGuid().ToString() };
using (var reader = queryProvider.ExecuteQuery(query, clientRequestProperties))
{
// Read HowManyRecords
while (reader.Read())
{
var howManyRecords = reader.GetInt64(0);
Console.WriteLine($"There are {howManyRecords} records in the table");
}
// Move on to the next result set, SampleRecords
reader.NextResult();
Console.WriteLine();
while (reader.Read())
{
// Important note: For demonstration purposes we show how to read the data
// using the "bare bones" IDataReader interface. In a production environment
// one would normally use some ORM library to automatically map the data from
// IDataReader into a strongly-typed record type (e.g. Dapper.Net, AutoMapper, etc.)
DateTime time = reader.GetDateTime(0);
string type = reader.GetString(1);
string state = reader.GetString(2);
Console.WriteLine("{0}\t{1,-20}\t{2}", time, type, state);
}
}
}
}
}

Seeing lots of exception in collectionSelfLink

I'm seeing a lot of exceptions in the collectionSelfLink when making DocumentDb call -- see image below.
I'm able to connect to DocumentDb and read data but these exceptions concern me -- especially in something that's pretty straight forward like a collectionSelfLink.
Any idea what may be causing them and how to fix them?
Here's the function that's using the selfLink
public async Task<IEnumerable<T>> ReadQuery<T>(string dbName, string collectionId, SqlQuerySpec query)
{
// Prepare collection self link
// IMPORTANT: This is where I'm seeing those exceptions when I inspect the collectionLink. Otherwise, I'm NOT getting any errors.
var collectionLink = UriFactory.CreateDocumentCollectionUri(dbName, collectionId);
var result = _client.CreateDocumentQuery<T>(collectionLink, query, null);
_client.CreateDocumentQuery<T>(collectionLink);
return await result.QueryAsync();
}
And here's the QueryAsync() extension method
public async static Task<IEnumerable<T>> QueryAsync<T>(this IQueryable<T> query)
{
var docQuery = query.AsDocumentQuery();
var batches = new List<IEnumerable<T>>();
do
{
var batch = await docQuery.ExecuteNextAsync<T>();
batches.Add(batch);
}
while (docQuery.HasMoreResults);
var docs = batches.SelectMany(b => b);
return docs;
}
So SelfLink is an internal property that is set by DocumentDB. It cannot be set by the user and will only be populated on resources that have been returned from a call to the server.
The UriFactory code that you are using is construction a link that can be used to execute operations, but it is not a SelfLink.
If you are looking at a SelfLink property on a newly initialized DocumentCollection() object the SelfLink will be null as it has not been persisted on the server yet. This would explain all those errors in debug watch.

How can I create a new database in mongodb after dropping it?

In my end to end tests, I want to drop the "test" database, and then create a new test db. Dropping an entire database is simple:
mongoose.connection.db.command( {dropDatabase:1}, function(err, result) {
console.log(err);
console.log(result);
});
But now how do I now create the test db? I can't find a createDatabase or useDatabase command in the docs. Do I have to disconnect and reconnnect, or is there a proper command? It would be bizarre if the only way to create a db was as a side effect of connecting to a server.
update
I found some C# code that appears to create a database, and it looks like it connects, drops the database, connects again (without disconnecting?) and that creates the new db. This is what I will do for now.
public static MongoDatabase CreateDatabase()
{
return GetDatabase(true);
}
public static MongoDatabase OpenDatabase()
{
return GetDatabase(false);
}
private static MongoDatabase GetDatabase(bool clear)
{
var connectionString = ConfigurationManager.ConnectionStrings["MongoDB"].ConnectionString;
var databaseName = GetDatabaseName(connectionString);
var server = new MongoClient(connectionString).GetServer();
if (clear)
server.DropDatabase(databaseName);
return server.GetDatabase(databaseName);
}
mongodb will create (or recreate) it automatically the next time a document is saved to a collection in that database. You shouldn't need any special code and I think you don't need to reconnect either, just save a document in your tests and you should be good to go. FYI this same pattern applies to mongodb collections - they are implicit create on write.

Overriding delete operation on Azure Mobile Services table

I'd like to override delete operation on my Azure Mobile Services table to make it more like update then real delete. I have additional column named IsDeleted and I'd like to set it's value to true when delete operation is executed.
I figured out, that what I need is:
fire my own 'update' inside del function,
delete current request.execute()
prepare and sent response by myself
That meens my del function should look like that:
function del(id, user, request) {
// execute update query to set 'isDeleted' - true
// return standard response
request.respond();
}
As you can see I'm missing the first part of the function - the update one. Could you help me writing it? I read Mobile Services server script reference but there is no info about making additional queries inside a server script function.
There are basically two ways to do that - using the tables object, and using the mssql object. The links point to the appropriate reference.
Using mssql (I didn't try it, you may need to update your SQL statement):
function del(id, user, request) {
var sql = 'UPDATE <yourTableName> SET isDeleted = true WHERE id = ?';
mssql.query(sql, [id], {
success: function() {
request.respond(statusCodes.OK);
}
});
}
Using tables (again, only tested in notepad):
function del(id, user, request) {
var table = tables.getTable('YourTableName');
table.where({ id: id }).read({
success: function(items) {
if (items.length === 0) {
request.respond(statusCodes.NOT_FOUND);
} else {
var item = items[0];
item.isDeleted = true;
table.update(item, {
success: function() {
request.respond(statusCodes.OK, item);
}
});
}
}
});
}
There is a Node.js driver for SQL Server that you might want to check out.
The script component of Mobile Services uses node.js. You might want to check out the session from AzureConf called Javascript, meet cloud

Resources