CosmosDB with MongoDB API - c#

Hi I am a newbie on MongoDB and CosmosDB and I try to this in c#
MongoClientSettings settings = MongoClientSettings.FromUrl(
new MongoUrl(connectionString)
);
settings.SslSettings =
new SslSettings() { EnabledSslProtocols = SslProtocols.Tls12 };
var mongoClient = new MongoClient(settings);
var mongoDatabase = mongoClient.GetDatabase("MYDATABASE");
var mongoCollection = mongoDatabase.GetCollection<BsonDocument>("MYCOLLECTION");
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Lt("mac", "001BC50670101BB8") & builder.Gte("date", "2016-09-18T00:00:00Z") & builder.Gte("date", "2017-09-22T00:00:00Z");
var query = mongoCollection.Find<BsonDocument>(filter).ToList<BsonDocument>();
But when it runs the query on the server I get this error:
Errors":["An invalid query has been specified with filters against path(s) that are not range-indexed. Consider adding allow scan header in the request."
I have found that I should add the "x-ms-documentdb-query-enable-scan" header to my request. But how I can do this?

Solution found in comment section:
Query changed from
builder.Lt("mac", "001BC50670101BB8")
to
builder.Eq("mac", "001BC50670101BB8")

Related

Create a Cosmos Db and Container in C#

I am trying to create a database and container using C# I am trying to use the newest version of Azure.ResourceManager.CosmosDB 1.2.0.
In a previos version I used:
var client = new CosmosDBManagementClient("someendpoint", new DefaultAzureCredential());
var database = await client.SqlResources.StartCreateUpdateSqlDatabaseAsync(
AzureResourceGroup, AccountName, DatabaseName,
new SqlDatabaseCreateUpdateParameters(
new SqlDatabaseResource(DatabaseName),
new CreateUpdateOptions()
)
);
var armcontainer = await client.SqlResources.StartCreateUpdateSqlContainerAsync(
AzureResourceGroup, AccountName, DatabaseName,
ContainerName,
GetContainerParameters()
);
However, the CosmosDBManagementClient is no longer in library.
I know there is:
var client = new CosmosClient(endpoint, new DefaultAzureCredential());
await client.CreateDatabaseIfNotExistsAsync("testing",
throughput: null, new RequestOptions());
I also can't get this to work due to 403 error, even with the contributor permissions, but I know this was an error because you are supposed to use the resource manager.
Any suggestions would be appreciated.
I haven't worked with passwordless access but have you tried providing the id explictely?
string userAssignedClientId = "<your managed identity client Id>";
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId });
var client = new CosmosClient(endpoint, new DefaultAzureCredential());
If this doesn't work you could try the connection string approach:
using CosmosClient client = new(
accountEndpoint: "endpoint here",
authKeyOrResourceToken: "key here");

Creating snapshot and export in new Azure SDK .NET - Azure.ResourceManager

Because old Azure SDK for .NET is deprecated, I'm trying to migrate it to new version. I've been stucked with finding substitions for old methods and properties in new SDK. We do a snapshot of existing database and export to Storage Account.
Snippet of old approach:
var sp = new ServicePrincipalLoginInformation()
{
ClientId = clientId,
ClientSecret = clientSecret
};
var credentials = new AzureCredentials(sp, tenantId, AzureEnvironment.AzureGlobalCloud);
var azureClient = Authenticate(credentials).WithSubscription(subscriptionId);
var sqlServer = await azureClient.SqlServers.GetByIdAsync(db.SourceServerId);
var serverDbs = await sqlServer.Databases.ListAsync();
var snapshotDb = serverDbs.FirstOrDefault(i => i.Name == snapshotDbName);
if(snapshotDb is not null)
return;
snapshotDb = await azureClient.SqlServers.Databases
.Define(snapshotDbName)
.WithExistingSqlServer(sqlServer)
.WithSourceDatabase(sourceDatabaseId)
.WithMode(CreateMode.Copy)
.CreateAsync(cancellationToken);
.
.
.
var storageAccount = azureClient.StorageAccounts.GetByIdAsync(storageId);
await snapshotDb.ExportTo(storageAccount, storageContainer, outputFileName)
.WithSqlAdministratorLoginAndPassword(user, password)
.ExecuteAsync(cancellationToken);
According to documentation, I was able to get this:
var sp = new ClientSecretCredential(tenantId, clientId, clientSecret);
var azureClient = new ArmClient(sp, subscriptionId);
var ri = new ResourceIdentifier(NOT SURE WHAT SHOULD BE HERE);
var resGroup = azure.GetResourceGroupResource(ri);
var sqlServerResponse = await resGroup.GetSqlServers().GetAsync(sourceServerId);
var sqlServer = sqlServers.Value;
var serverDBs = sqlServer.GetSqlDatabases();
var snapshotDB = serverDBs.FirstOrDefault(x => x.Data.Name == db.SnapshotDbName);
What are substitution commands, which handle creating snapshot and exporting to Storage Account base on parameters used in deprecated sample? Or do I miss some Package?
We have a general guidance for using our latest version of .NET SDK against resource management.
Regarding your issue, you can refer to code below
var resourceGroup = _client.GetDefaultSubscription().GetResourceGroup(resourceGroupName).Value;
var sqlServer = resourceGroup.GetSqlServer("mySqlServerName").Value;
var sqlDB = sqlServer.GetSqlDatabase("myDbName").Value;
var exportResult= sqlDB.Export(Azure.WaitUntil.Completed, new Azure.ResourceManager.Sql.Models.DatabaseExportDefinition("storageKeyType", "storageKey", new Uri("storageUri"), "adminLogin", "adminLoginPWD")).Value;
The _client here is ArmClient object,
your code var ri = new ResourceIdentifier(NOT SURE WHAT SHOULD BE HERE); is not necessary, may I know why do you want to create a resource identifier here?
Please make sure you are using 1.1.0 version of Azure SDK for SQL libirary in .NET
We are open to any feedback regarding our new SDK, feel free to let us know your thoughts on our new SDK in this survey

Creating Azure VM via C# Throws Error While Creating Resource Group

I'm attempting to create a VM programmatically...actually, following an example in a book. Before running the program I went ahead and created an Azure AD application and service principal via the portal https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal. (On a side note, maybe someone can explain to me why one needs to do this, but can create a VM straightaway via the portal without creating a service principal/AD app.)
While running the app, I'm able to successfully create the management client. Next step is to create the resource group, and that's where it fails with a "System.Net.Http.HttpRequestException: 'No such host is known.'" error. Please advise as to what could be the problem here. Thank you.
//Create the management client. This will be used for all the operations we will perform in Azure.
var credentials = SdkContext.AzureCredentialsFactory.FromFile("../../../azureauth.properties");
var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credentials).WithDefaultSubscription();
//Create a resource group
var groupName = "az204-ResourceGroup";
var vmName = "az204VMTesting";
var location = Region.USEast;
var vNetName = "az204VNET";
var vNetAddress = "172.16.0.0/16";
var subnetName = "az204Subnet";
var subnetAddress = "172.16.0.0/24";
var nicName = "az204NIC";
var adminUser = "azureadminuser";
var adminPassword = "Pa$$w0rd!2019";
Console.WriteLine($"Creating resource group {groupName} ... ");
//Below fails with 'No such host is known'
var resourceGroup = azure.ResourceGroups.Define(groupName).WithRegion(location).Create();
I tried this code in my system .Try with this code
using Microsoft.Azure.Management.Compute.Fluent.Models;
using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
namespace AzureVirtualMachine
{
class Program
{
static void Main(string[] args)
{
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal("clientId", "clientSecret", "tenantId", AzureEnvironment.AzureGlobalCloud);
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithSubscription("SubscriptionID”)
var groupName = "sampleResourceGroup";
var vmName = "VMWithCSharp";
var location = Region.EuropeWest;
var resourceGroup = azure.ResourceGroups.Define(groupName)
.WithRegion(location)
.Create();
var network = azure.Networks.Define("sampleVirtualNetwork")
.WithRegion(location)
.WithExistingResourceGroup(groupName)
.WithAddressSpace("10.0.0.0/16")
.WithSubnet("sampleSubNet", "10.0.0.0/24")
.Create();
var publicIPAddress = azure.PublicIPAddresses.Define("samplePublicIP")
.WithRegion(location)
.WithExistingResourceGroup(groupName)
.WithDynamicIP()
.Create();
var networkInterface = azure.NetworkInterfaces.Define("sampleNetWorkInterface")
.WithRegion(location)
.WithExistingResourceGroup(groupName)
.WithExistingPrimaryNetwork(network)
.WithSubnet("sampleSubNet")
.WithPrimaryPrivateIPAddressDynamic()
.WithExistingPrimaryPublicIPAddress(publicIPAddress)
.Create();
var availabilitySet = azure.AvailabilitySets.Define("sampleAvailabilitySet")
.WithRegion(location)
.WithExistingResourceGroup(groupName)
.WithSku(AvailabilitySetSkuTypes.Aligned)
.Create();
azure.VirtualMachines.Define(vmName)
.WithRegion(location)
.WithExistingResourceGroup(groupName)
.WithExistingPrimaryNetworkInterface(networkInterface)
.WithLatestWindowsImage("MicrosoftWindowsServer", "WindowsServer", "2012-R2-Datacenter")
.WithAdminUsername("sampleUser")
.WithAdminPassword("Sample123467")
.WithComputerName(vmName)
.WithExistingAvailabilitySet(availabilitySet)
.WithSize(VirtualMachineSizeTypes.StandardB1s)
.Create();
}
}
}
Output:
I resolved the issue by replacing AzureCredentialsFactory.FromFile with AzureCredentialsFactory.FromServicePrincipal. Thanks ShrutiJoshi-MT for the input. I simply created a json file with the necessary credentials.
I still had some issues related to authorization. It turns out I didn't give the App Service appropriate authorization level. This post helped resolve that issue: The client with object id does not have authorization to perform action 'Microsoft.DataFactory/datafactories/datapipelines/read' over scope.
Final code:
string jsonString = File.ReadAllText("../../../azureauth.json");
AuthItem authItem = JsonSerializer.Deserialize<AuthItem>(jsonString);
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(authItem.ClientId, authItem.SecretValue, authItem.TenantId, AzureEnvironment.AzureGlobalCloud);
//Create the management client. This will be used for all the operations we will perform in Azure.
var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credentials).WithSubscription(authItem.Subscription);
//Create a resource group
var groupName = "az204-ResourceGroup";
var vmName = "az204VMTesting";
var location = Region.USEast;
var vNetName = "az204VNET";
var vNetAddress = "172.16.0.0/16";
var subnetName = "az204Subnet";
var subnetAddress = "172.16.0.0/24";
var nicName = "az204NIC";
var adminUser = "azureadminuser";
var adminPassword = "Pa$$w0rd!2019";
Console.WriteLine($"Creating resource group {groupName} ... ");
var resourceGroup = azure.ResourceGroups.Define(groupName).WithRegion(location).Create();
//Every VM needs to be connected to a virtual network
Console.WriteLine($"Creating virtual network {vNetName} ...");
var network = azure.Networks.Define(vNetName)
.WithRegion(location)
.WithExistingResourceGroup(groupName)
.WithAddressSpace(vNetAddress)
.WithSubnet(subnetName, subnetAddress)
.Create();
//Any VM needs a network interface for connecting to the virtual network
Console.WriteLine($"Creating network interface {nicName} ... ");
var nic = azure.NetworkInterfaces.Define(nicName)
.WithRegion(location)
.WithExistingResourceGroup(groupName)
.WithExistingPrimaryNetwork(network)
.WithSubnet(subnetName)
.WithPrimaryPrivateIPAddressDynamic()
.Create();
//Create the VM
Console.WriteLine($"Creating VM {vmName} ... ");
azure.VirtualMachines.Define(vmName)
.WithRegion(location)
.WithExistingResourceGroup(groupName)
.WithExistingPrimaryNetworkInterface(nic)
.WithLatestWindowsImage("MicrosoftWindowsServer", "WindowsServer", "2012-R2-Datacenter")
.WithAdminUsername(adminUser)
.WithAdminPassword(adminPassword)
.WithComputerName(vmName)
.WithSize(VirtualMachineSizeTypes.StandardDS2V2)
.Create();

PowerBI embed token with RLS through C# API

We want to provide embedded PowerBI reports to our customers. Initially, we're looking at using one report with a dataset that contains data for all customers. I have created a service principal (app only auth) that has access to a workspace where I've published the report. I've also created a role "business_customer" with a DAX expression ([CustomerNumber] = USERNAME()) on this report.
I'm trying to get an embed token for the report with row level security through the C# API (Microsoft.PowerBI.Api):
var tenantId = "<tenantId>";
var datasetId = "<datasetId>";
var reportId = "<reportId>";
var groupId = "<groupId>";
var applicationPassword = "<applicationPassword>";
var context = new AuthenticationContext($"https://login.microsoftonline.com/{tenantId}/");
var clientCredential = new ClientCredential(applicationId, applicationPassword);
var result = context.AcquireTokenAsync("https://analysis.windows.net/powerbi/api",
clientCredential).Result;
var authHeader = new TokenCredentials(result.AccessToken, "Bearer");
var client = new PowerBIClient(new Uri("https://api.powerbi.com"), authHeader);
var groups = client.Groups.GetGroups();
var tokenRequest = new GenerateTokenRequest(TokenAccessLevel.View, datasetId,
new EffectiveIdentity("username", new List<string> { datasetId },
new List<string> { "business_customer" }));
var embedToken = client.Reports.GenerateTokenInGroupAsync(new Guid(groupId), new Guid(reportId),
tokenRequest, cancellationToken: CancellationToken.None).Result;
This fails on the GenerateTokenInGroupsAsync call:
"Invalid request: Creating embed token for accessing dataset <datasetId> shouldn't have effective identity"
I've tried with different usernames and I've tried leaving the username blank, but all of my attempts have failed.
Is there a way of getting an embed token this way or am I on the wrong path? What would be the "correct" way of solving this case?
Thanks in advance

Microsoft Graph - Filtering in SDK C#

Based on another post, I can filter via HTTP requests as follows:
https://graph.microsoft.com/v1.0/me/events?
$filter=categories/any(a:a+eq+'Red+Category')
I am not sure what the a:a stands for here but it works.
I want to replicate this in Microsoft Graph SDK, I am using a query option as per below which does not return any results:
List<QueryOption> options = new List<QueryOption>
{
new QueryOption("$filter",
"categories/any(a:a+eq+'Red+Category'")
};
You seem to be executing a search instead of a filter in your c# code.
Try using:
var request = graphClient.Users[userId].Events.Request().Filter("categories/any(a:a+eq+'Red+Category')");
var result = await request.GetAsync();
Or alternatively:
List<QueryOption> options = new List<QueryOption>
{
new QueryOption("$filter",
"categories/any(a:a+eq+'Red+Category')")
};

Categories

Resources