Method inside an array in C# - c#

I just got in contact with C# and I was wondering if it's possible to call a method inside an array. I have to say that I'm working with NoSQL database (mongodb).
This is mi code, and I want to call data() method inside that JSON.
static void Main(string[] args)
{
MongoClient client = new MongoClient();
var db = client.GetDatabase("test");
var collection = db.GetCollection<BsonDocument>("collection");
var document = new BsonDocument
{
{ "date", 10/04/2018 },
{ "data", data() }
};
collection.InsertOneAsync(document);
Console.Read();
}
static void data()
{
for (int i = 1; i <= 50; i++)
{
var data = new BsonDocument
{
{ "magnitude"+i, new BsonDocument{
{ "value", 5 }
} }
};
}
}
EDIT: Basically, what I'm trying to create with C# is this json below. I already did it with PHP and now, I'm trying to do it with C#.
{
"_id" : ObjectId("5abb735eb57dce214009035a"),
"date" : 1262300400,
"data" : {
"magnitude1" : {
"value" : 60
},
"magnitude2" : {
"value" : 38
},
"magnitude3" : {
"value" : 200
},
"magnitude4" : {
"value" : 62
},
"magnitude5" : {
"value" : 153
},
"magnitude6" : {
"value" : 176
},
"magnitude7" : {
"value" : 185
},
"magnitude8" : {
"value" : 168
},
.
.
.

You can use methods to gather data but I'm not sure exactly how you're asking it. Related to the code example I'll just give a simple run down, which is basic programming in general, not just C#.
You can write methods that return void or that return a variable of some type (at a minimum).
//Returns void
public void DoSomething()
{
//Do some work
return;
}
//Returns int
public int GetSomething()
{
int result = 100;
return result;
}
When you have methods that return data you can use them as you would a variable; just remember the method will execute every time it's called so it's often best to save the data to a variable. But for your example you can do something like this.
//other code ommitted
var document = new BsonDocument
{
{ "date", 10/04/2018 },
{ "data", getDocuments() }
};
//remaining code omitted
static List<BsonDocument> getDocuments()
{
var documents = new List<BsonDocument>();
for (int i = 1; i <= 50; i++)
{
var document = new BsonDocument
{
{ "magnitude" + i, new BsonDocument { { "value", 5 } } }
};
documents.Add(document);
}
return documents;
}
Now I modified the data() method to return a list of documents and changed the naming to match it but I'm not sure what you wanted to do with the method. That was my best assumption of what you were trying to accomplish by looking at your code so feel free to ignore all of it if it's wrong.

I've could solve it thanks to #Michael .Code below in case helps to anyone.
static void Main(string[] args)
{
MongoClient client = new MongoClient();
var db = client.GetDatabase("test");
var collection = db.GetCollection<BsonDocument>("Collection");
var document = new BsonDocument
{
{ "date", 10/04/2018 },
{ "data", new BsonDocument{ getDocuments() } }
};
collection.InsertOneAsync(document);
Console.Read();
}
static BsonDocument getDocuments()
{
var documents = new BsonDocument();
for (int i = 1; i <= 5; i++)
{
var document = new BsonDocument
{
{ "magnitude" + i, new BsonDocument { { "value", 5 } } }
};
documents.AddRange(document);
}
return documents;
}

Related

How to filter the list by using LINQ

I have a list mentioned below.
var fakedata = new Dictionary<Gateway, List<FeMeasurementValues>>()
{
{
new Gateway { SiteId = 1, FirmwareVersion = "1.1.1", ConnectivityStatus = GatewayConnectivityStatus.ReadyToConnect },
new List<FeMeasurementValues>() { new FeMeasurementValues { MeasurementName = "MsgLRRID", Values = new List<FeValue> { new FeValue { Value = "FFFF123", Horodate = DateTime.Now } } } }
},
{
new Gateway { SiteId = 2, FirmwareVersion = "1.1.2", ConnectivityStatus = GatewayConnectivityStatus.Connected },
new List<FeMeasurementValues>() { new FeMeasurementValues { MeasurementName = "MsgLRRID", Values = new List<FeValue> { new FeValue { Value = "GH67123", Horodate = DateTime.Now } } } }
},
{
new Gateway { SiteId = 3, FirmwareVersion = "1.1.3", ConnectivityStatus = GatewayConnectivityStatus.Disconnected },
new List<FeMeasurementValues>() { new FeMeasurementValues { MeasurementName = "MsgLRRID", Values = new List<FeValue> { new FeValue { Value = " ", Horodate = DateTime.Now } } } }
},
{
new Gateway { SiteId = 4, FirmwareVersion = "1.1.1", ConnectivityStatus = GatewayConnectivityStatus.Connected },
new List<FeMeasurementValues>() { new FeMeasurementValues { MeasurementName = "MsgLRRID", Values = new List<FeValue> { new FeValue { Value = "SA67123", Horodate = DateTime.Now } } } }
}
};
I have two methods
"GetPublicNetworkUsedCount()" which needs to return the count of Value which starts with "FFFF"
So, In this case output should be 1.
"GetPrivateNetworkUsedCount()" which needs to return the count of Value which does not starts with "FFFF" and which includes empty values.
So, In this case output should be 3.
Below is what i have tried:
private static string GetPublicNetworkUsedCount(List<FeValue> values)
{
var countofPublicNetwork = values.Where(x => x.Value.Any(f => x.Value.StartsWith("FFFF")));
return countofPublicNetwork.Count().ToString();
}
private static string GetPrivateNetworkUsedCount(List<FeValue> values)
{
var countofPrivateNetwork = values.Where(x => x.Value.Any(f => !x.Value.StartsWith("FFFF")));
return countofPrivateNetwork.Count().ToString();
}
I'm getting the wrong output as 0 for GetPublicNetworkUsedCount and 1 for GetPrivateNetworkUsedCount.
Please help me.
x.Value.Any() will return true as soon as the condintion inside is true. which leads to return 1 convertet to a number.
to get alll entries starting with FFFF remove the Any part like:
var countofPublicNetwork = values.Where(x =>x.Value.StartsWith("FFFF"));
you can get the count directly if you substitute .Where() with .Count() like Mark mentioned in his comment.
var countofPublicNetwork = values.Count(x =>x.Value.StartsWith("FFFF"));
You have a List<FeValue>, where each object has a string Value. You are treating the string as a collection and going one step to deep, the .Any( is not needed.
So the check should just be
values.Where(x => x.Value.StartsWith("FFFF")).Count();
Or just
values.Count(x => x.Value.StartsWith("FFFF"));
See comments:
// vv I'd recommend to return int
private static string GetPublicNetworkUsedCount(List<FeValue> values)
{ // vv Any doesn't make sense here: this is a string
var countofPublicNetwork = values.Where(x => x.Value.Any(f => x.Value.StartsWith("FFFF")));
return countofPublicNetwork.Count().ToString();
}
private static string GetPrivateNetworkUsedCount(List<FeValue> values)
{
var countofPrivateNetwork = values.Where(x => x.Value.Any(f => !x.Value.StartsWith("FFFF")));
return countofPrivateNetwork.Count().ToString();
}
So, I'd do something like this:
private static int GetPublicNetworkUsedCount(List<FeValue> values)
=> values.Count(x => x.Value.StartsWith("FFFF"));
private static int GetPrivateNetworkUsedCount(List<FeValue> values)
=> values.Count(x => !x.Value.StartsWith("FFFF"));
The returned int can then be stringyfied if need be.
Maybe I'd even do
public static class FeValueListExtensions
{
public static int GetPublicNetworkUsedCount(this List<FeValue> values)
=> values.Count(x => x.Value.StartsWith("FFFF"));
public static int GetPrivateNetworkUsedCount(this List<FeValue> values)
=> values.Count(x => !x.Value.StartsWith("FFFF"));
}
which can then be used as
// Assume we have a List<FeValue> defined as
List<FeValue> feValues = ...
var publicCount = feValues.GetPublicNetworkUsedCount();

Dictionary with tuples values returning null?

I have a class with a dictionary defined as a private member :
Dictionary<int, (string, string)> arenaIdToSetAndNumber = new Dictionary<int, (string, string)>()
{
{ 70506, ("c16", "337") },
{ 70507, ("c16", "340") },
{ 70508, ("c16", "343") },
{ 70509, ("c16", "346") },
{ 70510, ("c16", "349") },
};
While debugging, I get to an item corresponding to key 70506, I see this with 2 watches:
I try doing var test = arenaIdToSetAndNumber[c.grpId].Item1 and test is set to null just as seen in the second watch! I don't understand why
The debugger and the watcher are not able to infer what is Item1 from the indexer operator [], thus will give you null in the watch. But once you run the code, it will just work fine for reading purpose. For writing purpose instead, you need to take out the whole tuple, edit it and reinsert in the dictionary:
static void Main(string[] args)
{
Dictionary<int, (string, string)> arenaIdToSetAndNumber = new Dictionary<int, (string, string)>()
{
{ 70506, ("c16", "337") },
{ 70507, ("c16", "340") },
{ 70508, ("c16", "343") },
{ 70509, ("c16", "346") },
{ 70510, ("c16", "349") },
};
var myTuple = arenaIdToSetAndNumber[70509];
myTuple.Item1 = "c18";
arenaIdToSetAndNumber[70509] = myTuple;
//System.Console.WriteLine(arenaIdToSetAndNumber[70509].Item1); // This prints c18
}
Otherwise, in one line, just recreate the whole tuple:
arenaIdToSetAndNumber[70509] = ("c18", arenaIdToSetAndNumber[70509].Item2);
All of this because the ValueTuple is a struct. Similar question here
This does not use tuples but solves your problem. Since you want to read the values create an immutable class, use properties to retrive the values.
public class Contents
{
private readonly string leftValue;
private readonly string rightValue;
public Contents(string aLeftValue, string aRightValue)
{
leftValue = aLeftValue;
rightValue = aRightValue;
}
public string LeftValue => leftValue;
public string RightValue => rightValue;
}
Modify your code to use the new class.
Dictionary<int, Contents> arenaIdToSetAndNumber = new Dictionary<int, Contents>()
{
{ 70506, new Contents("c16", "337") },
{ 70507, new Contents("c16", "340") },
{ 70508, new Contents("c16", "343") },
{ 70509, new Contents("c16", "346") },
{ 70510, new Contents("c16", "349") },
};
And you can test it with this.
var content = arenaIdToSetAndNumber[70506];
string leftValue = content.LeftValue;
string rightValue = content.RightValue;
Hope this solves your problem.

How to iterate through JObject Properties via Foreach/LINQ

I have an established JObject object. Trying to loop through it to acquire a Key/value based on anothers Key/value (example of json below with code currently stuck on)
For a tad more detail - looking to loop through "value", get the "KeyID" based on "MailState"
definitely feel like I am missing the step of filtering by MailState/ColName apparently - I have searched through threads a bunch but if someone knows of one that answered this that i was unable to find i will happily pull this down/reference it
// JSON DATA
{
"odata.metadata": "https://..com/odata/$metadata#JCJMCDXes",
"value": [
{
"KeyID": "10379",
"MailCity": "Chicago",
"MailState": "IL"
},
{
"KeyID": "9846",
"MailCity": "Chicago",
"MailState": "IL"
},
{
"KeyID": "2234",
"MailCity": "Madison",
"MailState": "WI"
}]
}
// Current code example
// class in play
public class datastorage
{
public string ID { get; set; }
public string Col { get; set; }
}
public class listData
{
public string ColName {get;set;}
}
// getVPData is a string response from a call to an API
getVPData.Replace(System.Environment.NewLine, "");
JObject jobj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(getVPData);
List<datastorage> data = new List<datastorage>();
// Loop
foreach(var r in listData) // has distinct State abeviations so only 1 occurence
{
foreach (var j in jobj) // This the right path?
{
//add KeyID into ID
data.add(new datastorage
{
ID = ,//add KeyID into ID
Col = r.ColName
});
}
}
You can use Newtonsoft.Json library to parse and loop to the items of value
here is a sample code:
dynamic json = JsonConvert.DeserializeObject(getVPData);
foreach (dynamic item in json["value"])
{
//you can access the fields inside value.
var KeyID = item["KeyID"];
var MailCity = item["MailCity"];
var MailState = item["MailState"];
//just for showing...
Console.WriteLine("KeyID:{0}, MailCity:{1}, MailState:{2}", KeyID, MailCity, MailState);
}
Let me know if the snippet works.
Straightforward ways are:
using System;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace ConsoleApp7
{
internal class Program
{
private static void Main(string[] args)
{
var mailStates = new[] {"IL", "WI"};
var jObject = (JObject) JsonConvert.DeserializeObject(json);
var values = (JArray) jObject["value"];
// 1st way
foreach (var mailState in mailStates)
{
var key = values
.Where(v => mailState == v.SelectToken("MailState").Value<string>())
.Select(v => v.Value<string>("KeyID"))
.FirstOrDefault();
Console.WriteLine($"1st case: {mailState} - {key}");
}
/* 2nd way based on JSONPath
* api: https://www.newtonsoft.com/json/help/html/QueryJsonSelectTokenJsonPath.htm
* dox: https://support.smartbear.com/alertsite/docs/monitors/api/endpoint/jsonpath.html
* tester: https://jsonpath.curiousconcept.com/
*/
foreach (var mailState in mailStates)
{
var key = values.SelectTokens($"$[?(#.MailState == '{mailState}')].KeyID")
.Select(v => v.ToString())
.FirstOrDefault();
Console.WriteLine($"2nd case: {mailState} - {key}");
}
Console.ReadKey();
}
private static string json = #"
{
""odata.metadata"": ""https://cdxapiclient.palmercg.com/odata/$metadata#JCJMCDXes"",
""value"": [
{
""KeyID"": ""10379"",
""MailCity"": ""Chicago"",
""MailState"": ""IL""
},
{
""KeyID"": ""9846"",
""MailCity"": ""Chicago"",
""MailState"": ""IL""
},
{
""KeyID"": ""2234"",
""MailCity"": ""Madison"",
""MailState"": ""WI""
}]
}";
}
}

MongoDB C# 2.4 - Find distinct values of nested array

I have documents that look like below:
{
"_id" : ObjectId("58148f4337b1fc09b8c2de9k"),
"Price" : 69.99,
"Attributes" : [
{
"Name" : "Color",
"Value" : "Grey",
},
{
"Name" : "Gender",
"Value" : "Mens",
}
]
}
I am looking to get a distinct list of Attributes.Name (so if I just had the one document as above, I would get 'Color' and 'Gender' returned).
I was able to easily get what I needed through mongo shell (db.getCollection('myCollection').distinct('Attributes.Name'), but I'm really struggling with the C# driver (version 2.4). Can someone please help me translate the shell command to C#?
I tried something like below (and many variations). I'm new to the Mongo C# driver and am just feeling a bit lost. Any help would be appreciated.
var database = client.GetDatabase("mymongodb");
IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("mycollection");
var filter = new BsonDocument();
var distinctAttributeNames = collection.Distinct<BsonDocument>("Attributes.Name", filter);
var tryAgain = collection.Distinct<BsonDocument>("{Attributes.Name}", filter);
There you go:
public class Foo
{
public ObjectId Id;
public double Price = 69.99;
public Attribute[] Attributes = {
new Attribute { Name = "Color", Value = "Grey" },
new Attribute { Name = "Gender", Value = "Men" }
};
}
public class Attribute
{
public string Name;
public string Value;
}
public class Program
{
static void Main(string[] args)
{
MongoClient client = new MongoClient();
var collection = client.GetDatabase("test").GetCollection<Foo>("test");
collection.InsertOne(new Foo());
var distinctItems = collection.Distinct(new StringFieldDefinition<Foo, string>("Attributes.Name"), FilterDefinition<Foo>.Empty).ToList();
foreach (var distinctItem in distinctItems)
{
Console.WriteLine(distinctItem);
// prints:
// Color
// Gender
}
Console.ReadLine();
}
}

MongoDB c# using new driver

I know I may sound to you guys like a total nob but I am.
I am trying to use the mongodb driver in c#. Try to do something like add a record.
I learned today all basic mongodb queries and even tried it with robomongo.
But i don't understand how to use it in c#?
how to call it from the main function??
this is the code I wrote (trying to use mongodb website tutorial):
what is await? what is Task? what does it mean and how to make it work?
Thank you a lot for helping me.
class Program
{
protected static IMongoClient _client;
protected static IMongoDatabase _database;
public static void Main()
{
_client = new MongoClient();
_database = _client.GetDatabase("test");
Task simpleTask = Tasky();
}
public async Task Tasky()
{
var document = new BsonDocument
{
{ "address" , new BsonDocument
{
{ "street", "2 Avenue" },
{ "zipcode", "10075" },
{ "building", "1480" },
{ "coord", new BsonArray { 73.9557413, 40.7720266 } }
}
},
{ "borough", "Manhattan" },
{ "cuisine", "Italian" },
{ "grades", new BsonArray
{
new BsonDocument
{
{ "date", new DateTime(2014, 10, 1, 0, 0, 0, DateTimeKind.Utc) },
{ "grade", "A" },
{ "score", 11 }
},
new BsonDocument
{
{ "date", new DateTime(2014, 1, 6, 0, 0, 0, DateTimeKind.Utc) },
{ "grade", "B" },
{ "score", 17 }
}
}
},
{ "name", "Vella" },
{ "restaurant_id", "41704620" }
};
var collection = _database.GetCollection<BsonDocument>("restaurants");
await collection.InsertOneAsync(document);
}
}
Try to understand simpler version, then read about async/await. Add some documents to your collection using mongo shell and try this:
var collection = new MongoClient("mongodb://localhost").GetServer()
.GetDatabase("your_db").GetCollection<BsonDocument>("your_collection");
var cursor = collection.FindAll();
foreach(var doc in cursor) {
Console.WriteLine(doc);
}
cursor is used to get documents one by one.

Categories

Resources