Just got to grips with RavenDB - which is awesome - however I am getting a little stuck with a query. I running a foreach and using the Store() method to save some data and once complete using the SaveChanges() method.
Once I have stored this information, I need to reference this information to store some additional information (don't worry if you slightly confused at this point the code will make it clear!) but when I reference the information there is no information to be found.
So, first of all I add some data:
foreach (var development in developments)
{
Console.WriteLine(" - Working on Developmnent ID: " + development.devID);
Session.Store(new Domain.Development
{
Id = "D" + Convert.ToString(development.devID),
Name = development.devName,
Street = development.devStreet,
Town = development.devTown,
County = development.devCounty,
Postcode = development.devPostcode,
Country = development.devCounty,
Description = "",
Longitude = GeoData.Longitude(development.devPostcode),
Latitude = GeoData.Latitude(development.devPostcode)
});
}
Now, because of the limitations with the number of queries that can be ran within the session, I retrieve the whole dataset and store in memory:
var developmentList = from d in Session.Query<Domain.Development>()
select d;
Now when I add a break point at the end of this there is no data to be found. Do I need to create another session to retrieve this data?
I have also tried
var developmentList = Session.Query<Domain.Development>();
Here is the code where I create the session too:
internal static DocumentStore Store;
internal static IDocumentSession Session { get; set; }
internal <<Constructor>> ...
Store = new DocumentStore { ConnectionStringName = "RavenDB" };
Store.Initialize();
IndexCreation.CreateIndexes(Assembly.GetCallingAssembly(), Store);
Session = Store.OpenSession();
It's not recommended you do this. Goes back to safe by default concept of RavenDB.
If you just stored those values, why do you need to save them to the database and the re-load them from the database? Just use the in memory collection and that would be it.
Related
I just want to check if my RepoItemInfo object (which is username Joe McAdam btw) is equal to string data.
I just tracked this element in Chrome, stored it in my repository and it is a span with #innertext="JoeMcAdam"
Then I made code module for mapping these objects in C# code:
public RepoItemInfo LeftNameRepoItem {get {return _pageHome.Home.ImeLijevoInfo; }}
And I have prepared data Name in my context file for this LeftName to check if they are equal:
void ITestModule.Run()
{
var dto = new LoginDto () {
Name = "Joe McAdam",
WaitTimeLimit = 20000,
};
LoginDtoContext.template = dto;
}
I just need a proper code example for checking if they are eqal. What should I do? Do I have to make some adapter for this RepoItemInfo to convert it in string, text or something else?
I hope I provided enough details about my problem.
Thanks in advance!
I have a User class that accumulates lots of DataTime entries in some List<DateTime> Entries field.
Occasionally, I need to get last 12 Entries (or less, if not reached to 12). It can get to very large numbers.
I can add new Entry object to dedicated collection, but then I have to add ObjectId User field to refer the related user.
It seems like a big overhead, for each entry that holds only a DateTime, to add another field of ObjectId. It may double the collection size.
As I occasionally need to quickly get only last 12 entries of 100,000 for instance, I cannot place these entries in a per-user collection like:
class PerUserEntries {
public ObjectId TheUser;
public List<DateTime> Entries;
}
Because it's not possible to fetch only N entries from an embedded array in a mongo query, AFAIK (if I'm wrong, it would be very gladdening!).
So am I doomed to double my collection size or is there a way around it?
Update, according to #profesor79's answer:
If your answer works, that will be perfect! but unfortunately it fails...
Since I needed to filter on the user entity as well, here is what I did:
With this data:
class EndUserRecordEx {
public ObjectId Id { get; set; }
public string UserName;
public List<EncounterData> Encounters
}
I am trying this:
var query = EuBatch.Find(u => u.UserName == endUser.UserName)
.Project<BsonDocument>(
Builders<EndUserRecordEx>.Projection.Slice(
u => u.Encounters, 0, 12));
var queryString = query.ToString();
var requests = await query.ToListAsync(); // MongoCommandException
This is the query I get in queryString:
find({ "UserName" : "qXyF2uxkcESCTk0zD93Sc+U5fdvUMPow" }, { "Encounters" : { "$slice" : [0, 15] } })
Here is the error (the MongoCommandException.Result):
{
{
"_t" : "OKMongoResponse",
"ok" : 0,
"code" : 9,
"errmsg" : "Syntax error, incorrect syntax near '17'.",
"$err" : "Syntax error, incorrect syntax near '17'."
}
}
Update: problem identified...
Recently, Microsoft announced their DocumentDB protocol support for MongoDB. Apparently, it doesn't support yet all projection operators. I tried it with mLab.com, and it works.
You can use PerUserEntries as this is a valuable document structure.
To get part of that array we need to add projection to query, so we can get only x elements and this is done server side.
Please see snippet below:
static void Main(string[] args)
{
// To directly connect to a single MongoDB server
// or use a connection string
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("test");
var collection = database.GetCollection<PerUserEntries>("tar");
var newData = new PerUserEntries();
newData.Entries = new List<DateTime>();
for (var i = 0; i < 1000; i++)
{
newData.Entries.Add(DateTime.Now.AddSeconds(i));
}
collection.InsertOne(newData);
var list =
collection.Find(new BsonDocument())
.Project<BsonDocument>
(Builders<PerUserEntries>.Projection.Slice(x => x.Entries, 0, 3))
.ToList();
Console.ReadLine();
}
public class PerUserEntries
{
public List<DateTime> Entries;
public ObjectId TheUser;
public ObjectId Id { get; set; }
}
Using the example code from the Unity Developer Guide | Parse
# https://www.parse.com/docs/unity_guide#objects-updating
// Create the object.
var gameScore = new ParseObject("GameScore")
{
{ "score", 1337 },
{ "playerName", "Sean Plott" },
{ "cheatMode", false },
{ "skills", new List<string> { "pwnage", "flying" } },
};
gameScore.SaveAsync().ContinueWith(t =>
{
// Now let's update it with some new data. In this case, only cheatMode
// and score will get sent to the cloud. playerName hasn't changed.
gameScore["cheatMode"] = true;
It just adds a new row and leaves the original row unchanged.
I guess i'm thinking Parse would do something "SQL like" such as UPDATE where primaryKey = 123.
Searching for an answer i found this code #
https://parse.com/questions/updating-a-field-without-retrieving-the-object-first, but there was no example in C#. All attempts to port this to C# result in multiple syntax errors.
UnityScript:
// Create a pointer to an object of class Point with id dlkj83d
var Point = Parse.Object.extend("Point");
var point = new Point();
point.id = "dlkj83d";
// Set a new value on quantity
point.set("quantity", 6);
// Save
point.save(null, {
success: function(point) {
// Saved successfully.
},
error: function(point, error) {
// The save failed.
// error is a Parse.Error with an error code and description.
}
});
Does Parse have some way to update a row that already exists using C#? And where is it in the docs? And how can their own example be so useless?
One of the posts related to my question stated "retrieve the object, then write it back with the changes" and i had not the faintest idea how to execute the stated objective (especially after the epic fail of Parse Documentation's example code)
Here is what i have been able to figure out and make work:
var query = new ParseQuery<ParseObject>("Tokens")
.WhereEqualTo ("objectId", "XC18riofu9");
query.FindAsync().ContinueWith(t =>
{
var tokens = t.Result;
IEnumerator<ParseObject> enumerator = tokens.GetEnumerator();
enumerator.MoveNext();
var token = enumerator.Current;
token["power"] = 20;
return token.SaveAsync();
}).Unwrap().ContinueWith(t =>
{
// Everything is done!
//Debug.Log("Token has been updated!");
});
the first part retrieves the object with the stated objectId, the second part sets the fields in the object. The third part reports all is well with the operation.
it's a monkey see, monkey do understanding at this point being that i do not understand the finer points in the code.
the code can be tested by creating a class named "Tokens". in that class create a tokenName field and a power field. make a few rows with Fire, water, mud as the tokenNames. Replace the objectId in the .WhereEqualTo clause with a valid objectId or any other search parameters you like. Execute the code and observe the changes in the Parse Data Browser.
For extra credit create the class required to implement the example code from the Chaining Tasks Together section of Parse's Documentation.
https://www.parse.com/docs/unity_guide#tasks-chaining
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 :)
I'm trying to create an entity in CRM 2011 (not an out of the box kind, but what in CRM 4 would have been called a DynamicEntity... one with my custom attributes). The code below gives me this error and I'm not sure why. This exact same code works if I remove the new_accounttype attribute and try to use another custom attribute.
CRM seems to have taken issue with the "OptionSetValue" being set as the value for that key value pair. new_accounttype is a picklist (or OptionSet in CRM 2011) and that value of 100000003 was pulled from the front end so it's a valid value.
Error: A validation error occurred. The value of 'new_accounttype' on
record of type 'account' is outside the valid range.
What am I doing wrong?
public static void CreateAccount(string accountName, string accountType)
{
//Create properties
KeyValuePairOfstringanyType[] attributes = new KeyValuePairOfstringanyType[2];
attributes[0] = new KeyValuePairOfstringanyType() { key = "name", value = accountName ?? "" };
attributes[1] = new KeyValuePairOfstringanyType() { key = "new_accounttype", value = new OptionSetValue() { Value = 100000003 } };
////Create DynamicEntity
Entity accountToCreate = new Entity();
accountToCreate.LogicalName = "account";
accountToCreate.Attributes = attributes;
try
{
service.Create(accountToCreate);
}
}
I agree that what you have should work fine. This can only mean that the value isn't published or is incorrect. As #glosrob mentions, check that the changes are actually published. Confirm these values by looking at the published form and seeing if your new value is present (and perhaps double check by using IE Developer Tools - hit F12 - and confirm that the value in the select>option object in the HTML contains the integer you expect).
As an aside, your code looks more complex than necessary (IMHO!). I believe this is easier to read an no less efficient:
Try this:
public static void CreateAccount(string accountName, string accountType)
{
////Create DynamicEntity
Entity accountToCreate = new Entity();
accountToCreate.LogicalName = "account";
accountToCreate.Attributes = attributes;
//Append properties
accountToCreate.Attributes.Add("name", accountName ?? "" );
accountToCreate.Attributes.Add("new_accounttype", new OptionSetValue(100000003);
try
{
service.Create(accountToCreate);
}
}
Give this a shot: key = "new_accounttype", value = new OptionSetValue(100000003)