How to use InsertMany properly Mongodb C# - c#

Hi I wont to pass some synthetic data to my database with the method InsertMany i have write the flowing code:
My Main:
static void Main(string[] args)
{
MongoCRUD db = new MongoCRUD("testClass");
List<GlobalUrbanPoint> syntheticData = CreateSunfeticData(20);
db.InsertMultipleRecords<GlobalUrbanPoint>("geo3", syntheticData);
}
My model class:
public class GlobalUrbanPoint
{
[BsonId]
public ObjectId Id{ get; set; }
public string NAME { get; set; }
}
The function for the synthetic data:
public static List<GlobalUrbanPoint> CreateSunfeticData(int NumberOfDocumet)
{
List<GlobalUrbanPoint> SyntheticList = new List<GlobalUrbanPoint>();
var SyntheticObject = new GlobalUrbanPoint();
for (var i = 1; i < NumberOfDocumet; i++)
{
SyntheticObject.NAME = (i+1).ToString();
SyntheticList.Add(SyntheticObject);
}
return SyntheticList;
}
And for my operation i use MongoCRUD
public class MongoCRUD
{
private IMongoDatabase db;
public MongoCRUD(string database)
{
var client = new MongoClient();
db = client.GetDatabase(database);
}
public void InsertRecord<T>(string table, T record)
{
var collection = db.GetCollection<T>(table);
collection.InsertOne(record);
}
public void InsertMultipleRecords<T>(string table, List<T> records)
{
var collection = db.GetCollection<T>(table);
collection.InsertMany(records);
}
}
When i run the code i get an error E11000 duplicate key error collection. I check the definition of InsertMany and it takes for arguments IEnumerable<TDocument> documents. It is an easy way to convert List<T> to IEnumerable<TDocument>?
What i need to change my synthetic function or my InsertMultipleRecords funtion. Any sugestion?
Thank you for your time.

After some digging i found that the object that i create in synthetic function has the same _id. For that i needed to change the creation of the object, inside of for loop. And my problem it was not in InsertMultipleRecords.
public static List<GlobalUrbanPoint> CreateSunfeticData(int NumberOfDocumet)
{
List<GlobalUrbanPoint> SyntheticList = new List<GlobalUrbanPoint>();
for (var i = 1; i < NumberOfDocumet; i++)
{
var SyntheticObject = new GlobalUrbanPoint();
SyntheticObject.NAME = (i+1).ToString();
SyntheticList.Add(SyntheticObject);
}
return SyntheticList;
}

Related

Can I use join in Entity Framwork Pagination syntax?

I was wondering if someone can help here.I'm new to Entity Framwork. I have 2 different Query.I want to join them and get 1.Here is my code:
public static List<BankDepositHistory> GetAllByPagination(int page ,int stepes)
{
page=page-1;
using(MyketAdsEntities context = new MyketAdsEntities())
{
var transactionlist = context.BankDepositHistories.ToList();
var start = page * stepes;
var result= context.BankDepositHistories.OrderByDescending(c=>c.AccountId)
//anny code that give me count as field
.Skip(start)
.Take(stepes)
.ToList();
return (result);
}
}
public static int GetCount()
{
using (MyketAdsEntities context = new MyketAdsEntities())
{
int count = context.BankDepositHistories.Count();
return count;
}
}
As you see I have 2 method. I just want to have GetAllByPagination.
Many thanks
Suppose you have below Entity, Then below setup should work.
public BankDepositHistory
{
public string UserName {get;set}
//etc..
}
Create a View Model
public class BankDepositHistoryVM
{
public List<BankDepositHistory> bankDetails {get;set;}
public int Count {get;set;}
}
Return View Model
public static List<BankDepositHistoryVM> GetAllByPagination(int page ,int stepes)
{
page=page-1;
using(MyketAdsEntities context = new MyketAdsEntities())
{
var transactionlist = context.BankDepositHistories.ToList();
var start = page * stepes;
var result= context.BankDepositHistories.OrderByDescending(c=>c.AccountId)
.Skip(start)
.Take(stepes)
.ToList();
List<BankDepositHistoryVM> resultVM = new List<BankDepositHistoryVM>();
resultVM.bankDetails = result;
resultVM.Count = result.Count();
return resultVM;
}
}
Call the method:
List<BankDepositHistory> bankDetails = className.GetAllByPagination.bankDetails;
int count = className.GetAllByPagination.Count;
List<BankDepositHistoryVM> allDetails = className.GetAllByPagination();
Hope helps.

C# How to optimize this small piece of code correctly?

I've written a small program where I need to insert some objects (employees in my case) in my MongoDB database. Each employee needs to get a random name from a predefined list with strings.
This is what I came up with and is working:
class Program
{
public class Employee
{
public string Name { get; set; }
}
static void Main(string[] args)
{
MongoClient client = new MongoClient();
var server = client.GetServer();
var db = server.GetDatabase("testdb");
var collection = db.GetCollection<Employee>("testcollection");
Random random = new Random();
List<string> names = new List<string>() {"John","Matthew","Chris"};
for (int i = 0; i < 5; i++)
{
int nameIndex = random.Next(0, 3);
string nameValue = names[nameIndex];
Employee employee = new Employee
{
Name = nameValue
};
collection.Save(employee);
}
}
}
However, this code feels like a bit dirty and I am lookingfor a nice way to clean this up. Especially if I want to add more properties to my employee object.
Edit: #Eric Lippert
Of course! To start with, practically everything happens in the main method. With a single list it's fine, but I'd like to add more data to my employee object. It won't be tiny in the future.
So, if I want to add a few more List's, I have to duplicate my current code. For example, I'd like to iterate over another list with job types (10 items) and another one for locations (50 items). For each property I want to add to my Employee-object, I have to write a new line of the Next()-function from my Random object.
Edit 3:
public static IMongoDatabase Connect()
{
MongoClient client = new MongoClient();
var db = client.GetDatabase("testdb");
return db;
}
static void Main(string[] args)
{
Connect();
var collection = db.GetCollection<Employee>("testcollection");
}
Error: The name 'db' doesnt exist in the current context.
If you want to apply more random values from other lists you can do the following, which basically comes down to removing the unnecessary nameIndex and nameValue variables:
for (int i = 0; i < 5; i++)
{
Employee employee = new Employee
{
Name = names[random.Next(0, names.Count)]
};
collection.Save(employee);
}
You could abstract the separate parts in to new classes say a DatabaseSeeder and Database, this just cleans up the responsibilities instead of having it all in the main method
class Program
{
public class Employee
{
public string Name { get; set; }
}
public class Database
{
public ICollection<Employee> GetCollection()
{
MongoClient client = new MongoClient();
var server = client.GetServer();
var db = server.GetDatabase("testdb");
var collection = db.GetCollection<Employee>("testcollection");
}
}
public class DatabaseSeeder
{
private ICollection<Employee> collection;
public DatabaseSeeder(ICollection<Employee> collection)
{
this.collection = collection;
}
public void Seed()
{
Random random = new Random();
List<string> names = new List<string>() {"John","Matthew","Chris"};
for (int i = 0; i < 5; i++)
{
int nameIndex = random.Next(0, 3);
string nameValue = names[nameIndex];
Employee employee = new Employee
{
Name = nameValue
};
collection.Save(employee);
}
}
}
static void Main(string[] args)
{
var collection = new Database().GetCollection();
var databaseSeeder = new DatabaseSeeder(collection);
databaseSeeder.Seed();
}
}

Seperation of db connection in seperate class file doesn't work

Rookie here needing help. I'm trying to build a prototype with the neo4j .NET driver using Bolt. My aim with the prototype is building multiple methods for creation and searches in the db, but only one method to connect to the db - here I'm continuously having problems. I've Googled all weekend for examples, tutorials and traversed through the documentation and now I need your help.
Programs.cs
using System;
using DTUneo4jConsoleApp.Db;
namespace DTUneo4jConsoleApp
{
public class Program
{
public static void Main(string[] args)
{
MyProperties something = new MyProperties();
neo4jdb session = new neo4jdb();
session.Run($"CREATE (a:Person {{name:'{something.Name}', title:'{something.Title}'}})");
var result = session.Run($"MATCH (a:Person) WHERE a.name = '{something.Name}' RETURN a.name AS name, a.title AS title");
foreach (var record in result)
{
Console.WriteLine($"{record["title"].As<string>()} {record["name"].As<string>()}");
}
Console.ReadKey();
}
}
public class MyProperties
{
public string Name { get; set; }
public string Title { get; set; }
}
}
db.cs
using Neo4j.Driver.V1;
namespace DTUneo4jConsoleApp.Db
{
public class neo4jdb
{
public static void Connection()
{
using (var driver = GraphDatabase.Driver("bolt://localhost", AuthTokens.Basic("user", "pass")))
using (var session = driver.Session())
{
}
}
}
}
When I instantiate the neo4jdb session = new neo4jdb(); I don't get i.e. the Run() method from the driver.
I hope someone can guide me in the right direction.
I am doing it like this:
public static List<IStatementResult> ExecuteCypher(List<Statement> statements)
{
List<IStatementResult> results = new List<IStatementResult>();
using (var driver = GraphDatabase.Driver("bolt://localhost", AuthTokens.Basic("user", "pass")))
{
using (var session = driver.Session())
{
using (var tx = session.BeginTransaction())
{
foreach (var statement in statements)
{
results.Add(tx.Run(statement));
}
tx.Success();
}
}
}
return results;
}
usage:
MyProperties something = new MyProperties();
var createCypher = new Statement($"CREATE (a:Person {{name:'{something.Name}', title:'{something.Title}'}})");
var matchCypher = new Statement($"MATCH (a:Person) WHERE a.name = '{something.Name}' RETURN a.name AS name, a.title AS title");
var statements = new List<Statement>();
statements.Add(createCypher);
statements.Add(matchCypher);
var results = ExecuteCypher(statements);
//you can now query result for each statement or
//your query your desired result
foreach (var record in results.Last())
{
Console.WriteLine($"{record["title"].As<string>()} {record["name"].As<string>()}");
}
In this way I can also create multiple records in a single transaction and get the result of all those as well.

Assignment to struct array inside method does not work in C#?

Here is the code snippet from my LinqPad:
public class Elephant{
public int Size;
public Elephant()
{
Size = 1;
}
}
public struct Ant{
public int Size;
}
private T[] Transform2AnotherType<T>(Elephant[] elephantList)
where T:new()
{
dynamic tArray = new T[elephantList.Length];
for (int i = 0; i < elephantList.Length; i++)
{
tArray[i] = new T();
tArray[i].Size = 100;
//tArray[i].Dump();
}
return tArray;
}
void Main()
{
var elephantList = new Elephant[2];
var elephant1 = new Elephant();
var elephant2 = new Elephant();
elephantList[0] = elephant1;
elephantList[1] = elephant2;
elephantList.Dump();
var r = Transform2AnotherType<Ant>(elephantList);
r.Dump();
}
I want to change one object array of known type,Elephant,to another object array of type T. T is not a class,but limited to struct which
provided by the already existed API.And every instance of type T shares some common property,says Size,but also has their own particular property which
I have omitted in my example code.So I put dynamic keyword inside the Transform2AnotherType<T>.
And I could not even to use Dump to make sure if the assignment has made effect,thus will throw RuntimeBinderException.
My question is: how to correctly make the assignment in such a struct array and return it back properly?
I suggest change your code like this:
public class Elephant
{
public Elephant()
{
Size = 1;
}
public int Size { get; set; }
}
public struct Ant
{
public int Size { get; set; }
}
private static T[] Transform2AnotherType<T>(Elephant[] elephantList)
where T : new()
{
T[] tArray = new T[elephantList.Length];
for (int i = 0; i < elephantList.Length; i++)
{
dynamic arrayElement = new T();
arrayElement.Size = 100;
tArray[i] = arrayElement;
//tArray[i].Dump();
}
return tArray;
}
static void Main()
{
var elephantList = new Elephant[2];
var elephant1 = new Elephant();
var elephant2 = new Elephant();
elephantList[0] = elephant1;
elephantList[1] = elephant2;
//elephantList.Dump();
var r = Transform2AnotherType<Ant>(elephantList);
//r.Dump();
}

Using DefaultIfEmpty with an object?

I saw an example on MSDN where it would let you specify the default value if nothing is returned. See below:
List<int> months = new List<int> { };
int firstMonth2 = months.DefaultIfEmpty(1).First();
Is it possible to use this functionality with an object? Example:
class object
{
int id;
string name;
}
code:
List<myObjec> objs = new List<myObjec> {};
string defaultName = objs.DefaultIfEmpty(/*something to define object in here*/).name;
UPDATE:
I was thinking I could do something like this:
List<myObjec> objs = new List<myObjec> {};
string defaultName = objs.DefaultIfEmpty(new myObjec(-1,"test")).name;
But haven't been able to. It should be noted that I am actually trying to use this method on an object defined in my DBML using LINQ-To-SQL. Not sure if that makes a difference in this case or not.
You need to pass an instantiated class as a parameter of the DefaultIfEmpty.
class Program
{
static void Main(string[] args)
{
var lTest = new List<Test>();
var s = lTest.DefaultIfEmpty(new Test() { i = 1, name = "testing" }).First().name;
Console.WriteLine(s);
Console.ReadLine();
}
}
public class Test
{
public int i { get; set; }
public string name { get; set; }
}
To add to it and make it a bit more elegant (IMO) add a default constructor:
class Program
{
static void Main(string[] args)
{
var lTest = new List<Test>();
var s = lTest.DefaultIfEmpty(new Test()).First().name;
Console.WriteLine(s);
Console.ReadLine();
}
}
public class Test
{
public int i { get; set; }
public string name { get; set; }
public Test() { i = 2; name = "testing2"; }
}
As per the MSDN page on this Extension Method you can do what you want:
http://msdn.microsoft.com/en-us/library/bb355419.aspx
Check the sample on this page for an example on how to use this with an object.
i must admit i am not too sure i understand your question, but i'll try to suggest using double question mark if the returned object might be null. Like so:
myList.FirstOrDefault() ?? new myObject();
You can create a default Object Like this:
Object o_Obj_Default = new Object();
o_Obj_Default.id = 3;
o_Obj_Default.name = "C";
And add it to your default value :
string defaultName = objs.DefaultIfEmpty(o_Obj_Default).First().name;
If your list "objs" is empty, the result will be "C"

Categories

Resources