I'm developing a project using CosmosDb and Microsoft Azure Document library with c#.
I want to execute a stored procedure that retrieve all the record of a contsiner but the code retrieve only 100 record.
The code is the following :
string collectionToUse;
string partition;
if (typeof(T).ToString().IndexOf("Telemetry") != -1)
{
DocumentDBRepository<EBB.Web.Telemerty.Models.Telemetry>.Initialize();
collectionToUse = AppSettings.collection;
partition = "id";
}
else
{
DocumentDBRepository<EBB.Web.Telemerty.Models.Events>.Initialize();
collectionToUse = AppSettings.collection2;
partition = "uid";
}
Uri uri =
UriFactory.CreateStoredProcedureUri(AppSettings.database, collectionToUse, AppSettings.spName);
RequestOptions options = new RequestOptions { PartitionKey = new PartitionKey(partition) };
var result = await client.ExecuteStoredProcedureAsync<string>(uri, options, null);
List<T> list = new List<T>();
list = JsonConvert.DeserializeObject<List<T>>(result.Response);
return list;
What is the problem?
Thanks in advance for help me.
Simone
In Cosmos DB stored procedures cannot return all the documents in the container because the scope of the stored procedure execution isn't the full container but rather ONLY the logical partition that you specify in the RequestOptions. This means that your SP will only return documents that have this logical partition value in their properties.
Related
I am creating stored procedures in SQL Server database and have been having issues returning the data when called.
I have managed to get it to work, but it feels as if it is a hack job and that I am doing it incorrectly. Please see the code below and let me know if there is a better way to go about doing this. Thank you for taking the time to help me.
create procedure FetchSumOfEmpSalariesByCity
as
begin
select
sum(e.SAL) as TotalSalary, d.LOC as Location
from
EMPS e
join
DEPTs d on e.DEPTNO = d.DEPTNO
group by
d.LOC
end
public class SumOfEmpsSalaryByCity
{
[Key]
public int TotalSalary { get; set; }
public string Location { get; set; }
}
[HttpGet]
[Route("salary")]
public IHttpActionResult GetEMPsSal()
{
using (var db = new KemmitContext())
{
var sp = db.SumOfEmpsSalaryByCities.SqlQuery("FetchSumOfEmpSalariesByCity");
return Ok(sp.ToList());
}
}
I want to do this the correct way. Is there a way to do this without a model? Or am I going about this the right way?
I break these tasks down like this; should it be done with EF or in the database and if it's in the database, should it be a View or an Sp?
Whenever I'm simply selecting data, I use EF either direct to the table for very simple queries or I create a database View for any joins, etc. This can be done in EF but it's god-awful, in any case, IMO these tasks belong in the database, right tool, right job. If you're using code-first, getting your Views across is a bit involved, let me know if you're doing that.
var model = db.v_ObservationAutoComplete // This can be direct to a table or a view
.Where(oa => oa.Observation.Contains(term))
.OrderBy(oa => oa.Observation)
.Select(oa => new
{
label = oa.Observation
}).Take(10);
When I have to update something in a single table, I use EF
t_Section eSection = new t_Section
{
SectionId = model.SectionId,
Section = model.Section,
SectionTypeId = model.SectionTypeId,
SectionOrdinal = model.SectionOrdinal,
ModifyDate = DateTime.Now,
ModifyUserName = User.Identity.Name,
LastChangeId = newChangeId
};
db.Entry(eSection).State = EntityState.Modified;
db.SaveChanges();
If I have to do a multi-table update, I have a couple of different methodologies; 1) returning a simple bool value for a status code/scalar value, or I have to return a result set after doing whatever update I made.
This returns a List
List<string> elements = new List<string>();
try
{
SqlParameter[] parms = new[]
{
new SqlParameter("mpid", myProtocolsId),
new SqlParameter("elid", elementId)
};
elements = db.Database.SqlQuery<string>("p_MyProtocolsOverviewElementRemove #myProtocolsId = #mpid, #elementId = #elid", parms).ToList();
return Json(elements);
}
catch (Exception e)
{
return Json(null);
}
And if I just need a simple value back, something like this;
SqlParameter[] parms = new[]
{
new SqlParameter("chid", changeId),
new SqlParameter("prid", change.ObjectId),
new SqlParameter("psid", change.ProtocolSectionId),
new SqlParameter("inid", change.SecondaryObjectId),
new SqlParameter("acun", User.Identity.Name)
};
result = db.Database.SqlQuery<int>("p_MyProtocolsContentUpdateInterventionAdd #changeId = #chid, #protocolId = #prid, #protocolSectionId = #psid, #interventionId = #inid, #acceptUserName = #acun", parms).FirstOrDefault();
Hope this helps!
I have 2 collections in my database. Let's say collection_1 and collection_2. I want to copy or move all of my documents in collection_1 to collection_2 using C#.
Any idea please?
Here's a solution to copy between databases. If they are on the same database then it is even more simple, just use one mongo client
var fromConnectionString = "mongodb://localhost:27017"; // if copy between same database then obviously you only need one connectionstring and one MongoClient
var toConnectionString = "mongodb://localhost:27017";
var sourceClient = new MongoClient(fromConnectionString);
var copyFromDb = sourceClient.GetDatabase("CopyFromDatabaseName");
var copyCollection = copyFromDb.GetCollection<BsonDocument>("FromCollectionName").AsQueryable(); // or use the c# class in the collection
var targetClient = new MongoClient(toConnectionString);
var targetMongoDb = targetClient.GetDatabase("CopyToDatabase");
var targetCollection = targetMongoDb.GetCollection<BsonDocument>("ToCollectionName");
targetCollection.InsertMany(copyCollection);
With database query.
Source :https://docs.mongodb.com/manual/reference/method/db.cloneCollection/
db.cloneCollection('mongodb.example.net:27017', 'profiles', { 'active' : true } )
With C#
Source: Duplicate a mongodb collection
var source = db.GetCollection("test");
var dest = db.GetCollection("testcopy");
dest.InsertBatch(source.FindAll());
Using CosmoDb with MongoDb api from c# I can update a document with filter condition rather than using the Id.
For example this code work fine with CosmoDb with MongoDb api.
public bool UpdateTask(MyTask myTask)
{
var mongoCollection = GetBsonCollectionForEdit();
var builder = Builders<BsonDocument>.Filter;
var filterName = builder.Eq("Name", myTask.Name);
var filterCategory = builder.Eq("Category", myTask.Category);
var filter = builder.And(new[] { filterName, filterCategory });
var replaceUpdate = Builders<BsonDocument>.Update;
var ret = mongoCollection.ReplaceOne(filter, myTask.ToBsonDocument());
return ret.ModifiedCount == 1;
}
Can I do the same thing with CosmoDb using the SQL DocumentDb api ?
(Without implement UDF or StoredPoc)
Thanks
No, but you can perform a query for the criteria using CreateDocumentQuery, then iterate through the matching IDs and perform an update on each of them using ReplaceDocumentAsync.
I would need a way to know the most efficient way to see if a table in azure storage has any data
Exemple
cloudTable.ExecuteQuery("what do i do");
Thanks for the suggestions! I finally did something like this:
var query = new TableQuery<T>()
{
TakeCount = 1,
SelectColumns = new List<string>()
{
"PartitionKey"
}
};
var table = await this.GetTableAsync();
var segment = await table.ExecuteQuerySegmentedAsync(query, null);
return segment.Results.Any();
You could do this which limits your query to 1 record if there is data.
// select value = take smallest data field to avoid returning everything for a record
var query = new TableQuery().Select(new List<string>(){"smallcolumn"}).Take(1);
I am trying to update a row in a (typed) MongoDB collection with the C# driver. When handling data of that particular collection of type MongoCollection<User>, I tend to avoid retrieving sensitive data from the collection (salt, password hash, etc.)
Now I am trying to update a User instance. However, I never actually retrieved sensitive data in the first place, so I guess this data would be default(byte[]) in the retrieved model instance (as far as I can tell) before I apply modifications and submit the new data to the collection.
Maybe I am overseeing something trivial in the MongoDB C# driver how I can use MongoCollection<T>.Save(T item) without updating specific properties such as User.PasswordHash or User.PasswordSalt? Should I retrieve the full record first, update "safe" properties there, and write it back? Or is there a fancy option to exclude certain fields from the update?
Thanks in advance
Save(someValue) is for the case where you want the resulting record to be or become the full object (someValue) you passed in.
You can use
var query = Query.EQ("_id","123");
var sortBy = SortBy.Null;
var update = Update.Inc("LoginCount",1).Set("LastLogin",DateTime.UtcNow); // some update, you can chain a series of update commands here
MongoCollection<User>.FindAndModify(query,sortby,update);
method.
Using FindAndModify you can specify exactly which fields in an existing record to change and leave the rest alone.
You can see an example here.
The only thing you need from the existing record would be its _id, the 2 secret fields need not be loaded or ever mapped back into your POCO object.
It´s possible to add more criterias in the Where-statement. Like this:
var db = ReferenceTreeDb.Database;
var packageCol = db.GetCollection<Package>("dotnetpackage");
var filter = Builders<Package>.Filter.Where(_ => _.packageName == packageItem.PackageName.ToLower() && _.isLatestVersion);
var update = Builders<Package>.Update.Set(_ => _.isLatestVersion, false);
var options = new FindOneAndUpdateOptions<Package>();
packageCol.FindOneAndUpdate(filter, update, options);
Had the same problem and since I wanted to have 1 generic method for all types and didn't want to create my own implementation using Reflection, I end up with the following generic solution (simplified to show all in one method):
Task<bool> Update(string Id, T item)
{
var serializerSettings = new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
var bson = new BsonDocument() { { "$set", BsonDocument.Parse(JsonConvert.SerializeObject(item, serializerSettings)) } };
await database.GetCollection<T>(collectionName).UpdateOneAsync(Builders<T>.Filter.Eq("Id", Id), bson);
}
Notes:
Make sure all fields that must not update are set to default value.
If you need to set field to default value, you need to either use DefaultValueHandling.Include, or write custom method for that update
When performance matters, write custom update methods using Builders<T>.Update
P.S.: It's obviously should have been implemented by MongoDB .Net Driver, however I couldn't find it anywhere in the docs, maybe I just looked the wrong way.
Well there are many ways to updated value in mongodb.
Below is one of the simplest way I choose to update a field value in mongodb collection.
public string UpdateData()
{
string data = string.Empty;
string param= "{$set: { name:'Developerrr New' } }";
string filter= "{ 'name' : 'Developerrr '}";
try
{
//******get connections values from web.config file*****
var connectionString = ConfigurationManager.AppSettings["connectionString"];
var databseName = ConfigurationManager.AppSettings["database"];
var tableName = ConfigurationManager.AppSettings["table"];
//******Connect to mongodb**********
var client = new MongoClient(connectionString);
var dataBases = client.GetDatabase(databseName);
var dataCollection = dataBases.GetCollection<BsonDocument>(tableName);
//****** convert filter and updating value to BsonDocument*******
BsonDocument filterDoc = BsonDocument.Parse(filter);
BsonDocument document = BsonDocument.Parse(param);
//********Update value using UpdateOne method*****
dataCollection.UpdateOne(filterDoc, document);
data = "Success";
}
catch (Exception err)
{
data = "Failed - " + err;
}
return data;
}
Hoping this will help you :)