Unable to store and retrieve data from LiteDb - c#

I am trying to write one object to LiteDb and read it back.
I have tried following code but somehow all parameters of LiteDbParamEntry object are returned as NULL or zero.
public class LiteDbParamEntry
{
[BsonId]
public int Id
{
get { return (Index * 0x100) + SubIndex; }
}
public ushort Index;
public ushort SubIndex;
public string Text;
}
public class LiteDbParamValueStorage
{
private const string _liteDbPath = "MyLiteData.db";
public LiteDbParamValueStorage()
{
WriteEntry(123, 25);
ReadEntry(123, 25);
}
public void WriteEntry(ushort index, ushort subIndex)
{
using (var db = new LiteDatabase(_liteDbPath))
{
var entry = new LiteDbParamEntry {Index = index, SubIndex = subIndex, Text = "SomeText"};
var entries = db.GetCollection<LiteDbParamEntry>("LiteDbParamEntry");
entries.Insert(entry);
}
}
public void ReadEntry(ushort index, ushort subIndex)
{
using (var db = new LiteDatabase(_liteDbPath))
{
var collection = db.GetCollection<LiteDbParamEntry>("LiteDbParamEntry");
var paramEntry = collection.FindById((index * 0x100) + subIndex);
if (paramEntry != null)
Console.WriteLine(paramEntry.Text); //paramEntry.Text is returned as Null
else
return;
}
}
}
Can somebody please point me in right direction?

Finally, i've found what's wrong with your code... You forgot to add { get; set; } instruction on the right side of field declaration ;)
Take a look here:
public class LiteDbParamEntry
{
[BsonId]
public int Id
{
get { return (Index * 0x100) + SubIndex; }
}
public ushort Index { get; set; } //getter/setter added
public ushort SubIndex { get; set; } //getter/setter added
public string Text { get; set; } //getter/setter added
}
Good luck!

Related

Delete a record by matching Value

I have a dictionary where values are stored in the following format -
userID, empDetails
For example,
1234, 'empName,jobDesc,CardNumber,Type'
I have to compare this information with another set of information such that -
If entered userId is present in the above dictionary, then remove this record from the dictionary.
If entered CardNumber is present (here userId is not known) in the above dictionary, then remove this record from the dictionary.
The first condition is simple and can be done by
dictionary.Remove(key)
But I am confused as to how would I implement the second condition. I want something like
if(CardNumber.PresentinAboveDictionary)
then
Remove that record
I know we can compare a partial string in a key like this, but I want to remove the record.
Check if any part of a hashtable value contains certain string c#
Assuming the employment details in your dictionary are a string in the specified format you would need to:
Search the values within the dictionary
Parse/Split the values to get the card numbers
Check the card numbers to see if they match the card number you are checking
Return the key value pair when a match occurs
Remove the entry for the key in the returned key value pair
Example code for the solution:
var dictionary = new Dictionary<int, string>() { { 1, "empName,jobDesc,124124134,Type" } };
var cardNumber = 124124134;
var entry = dictionary.FirstOrDefault(x => DoEmploymentDetailsContainCardNumber(x.Value, cardNumber));
if (!entry.Equals(default(KeyValuePair<int, string>)))
{
dictionary.Remove(entry.Key);
}
Method that checks if card number is present in employment details:
private static bool DoEmploymentDetailsContainCardNumber(string empDetails, int cardNumber)
{
var splitEmpDetails = empDetails.Split(',');
var empDetailsCardNumber = splitEmpDetails[2];
return empDetailsCardNumber == cardNumber.ToString();
}
Instead of Dictionary you can use a strongly typed List
Use the Linq builtin Remove method
Use Parallel.ForEach, iterate the list and remove the item (beware, takes more time)
pseudo code:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.Collections;
namespace ConsoleApp4
{
public class Employee
{
public Employee(int userID, string empDetails)
{
string[] props = empDetails.Split(new char[] { ',' }, StringSplitOptions.None);
this.userID = userID;
this.empName = props[0];
this.jobDesc = props[1];
this.CardNumber = props[2];
this.Type = props[3];
}
public int userID { get; set; }
public string empName { get; set; }
public string jobDesc { get; set; }
public string CardNumber { get; set; }
public string Type { get; set; }
}
public class MyCustomList : List<Employee>
{
public void Add(int userID, string empDetails)
{
this.Add(new Employee(userID, empDetails));
}
public bool Remove(string CardNumber)
{
bool found = false ;
Parallel.ForEach(this,
(i, state) =>
{
if (i.CardNumber == CardNumber)
{
this.Remove(i);
state.Break();
}
});
return found;
}
public bool RemoveV2(string CardNumber)
{
bool found = false;
if (this.Any(x => x.CardNumber == CardNumber))
{
this.Remove(this.Where(x => x.CardNumber == CardNumber).First());
found = true;
}
return found;
}
}
class Program
{
static void Main(string[] args)
{
var dict = new MyCustomList();//userID, empDetails list
dict.Add(12341, "empName1,jobDesc,CardNumber1,Type");
dict.Add(12342, "empName2,jobDesc,CardNumber2,Type");
dict.Add(12343, "empName3,jobDesc,CardNumber3,Type");
dict.Add(12344, "empName4,jobDesc,CardNumber4,Type");
dict.Add(12345, "empName5,jobDesc,CardNumber5,Type");
dict.Add(12346, "empName6,jobDesc,CardNumber6,Type");
dict.Add(12347, "empName7,jobDesc,CardNumber7,Type");
dict.Add(12348, "empName8,jobDesc,CardNumber8,Type");
//remove CardNumber5
dict.Remove("CardNumber5");
Console.Write(dict);
}
}
}
you can follow the simple approach to remove the key by using a loop here.
Here I am assuming that there is no key with a value of -1 in the dictionary.
int keyToRemove = -1;
foreach (var entry in dictionary)
{
if (entry.Value.Contains(CardNumber))
{
keyToRemove = entry.Key;
break;
}
}
if (keyToRemove != -1)
{
dictionary.Remove(keyToRemove);
}
This is possibly overkill and is not optimised for reading the full dataset repeatedly but it is considerably faster than the accepted solution. I put together a test of the solution below which did the following:
Generated 1,000,000 data rows with unique IDs and card numbers (the solution would also work if the card numbers were not unique)
Randomly removed 100,000 data items by ID and 100,000 data items by card number
Generated a list of the remaining data items
The process took around 75 seconds.
I then tried to repeat steps 1) and 2) using the accepted answer - after around 10 minutes it's about 7% of the way through removing data items. Therefore I think the solution below is around 2 orders of magnitude faster for this type of operation.
There are probably better doubley linked list implementations out there but I am not too familiar with any of them.
namespace Question
{
public class EmployeeCollection
{
private readonly Dictionary<int, ListNode<EmployeeDetails>> _idDictionary = new();
private readonly Dictionary<string, Dictionary<int, EmployeeDetails>> _cardNumberDictionary = new();
private readonly LinkedList<EmployeeDetails> _list = new();
public void AddEmployee(EmployeeDetails details)
{
var node = new ListNode<EmployeeDetails>(details);
_list.AddToStart(node);
_idDictionary.Add(details.Id, node);
if(!_cardNumberDictionary.ContainsKey(details.CardNumber))
{
_cardNumberDictionary.Add(details.CardNumber, new Dictionary<int, EmployeeDetails>());
}
_cardNumberDictionary[details.CardNumber].Add(details.Id, details);
}
public void RemoveById(int id)
{
if (_idDictionary.TryGetValue(id, out var node))
{
_idDictionary.Remove(id);
_list.Remove(node);
var list = _cardNumberDictionary[node.Value.CardNumber];
list.Remove(id);
if(list.Count == 0)
{
_cardNumberDictionary.Remove(node.Value.CardNumber);
}
}
}
public void RemoveByCardNumber(string cardNumber)
{
if (_cardNumberDictionary.TryGetValue(cardNumber, out var employees))
{
_cardNumberDictionary.Remove(cardNumber);
foreach (var employee in employees)
{
if (_idDictionary.TryGetValue(employee.Key, out var node))
{
_list.Remove(node);
}
}
}
}
public IEnumerable<EmployeeDetails> Employees => _list.GetAllValues();
public EmployeeDetails? GetById(int id)
{
if(_idDictionary.ContainsKey(id))
{
return _idDictionary[id].Value;
}
return null;
}
}
public class EmployeeDetails
{
public int Id { get; init; }
public string Name { get; init; }
public string JobDescription { get; init; }
public string CardNumber { get; init; }
public string Type { get; init; }
public static EmployeeDetails FromData(int id, string details)
{
var parts = details.Split(',');
return new EmployeeDetails
{
Id = id,
Name = parts[0],
JobDescription = parts[1],
CardNumber = parts[2],
Type = parts[3],
};
}
}
public class LinkedList<T>
{
public int Count { get; private set; }
private ListNode<T>? Start { get; set; }
private ListNode<T>? End { get; set; }
public bool IsEmpty => Count == 0;
public void AddToStart(ListNode<T> node)
{
ArgumentNullException.ThrowIfNull(nameof(node));
node.Next = null;
node.Previous = null;
if (IsEmpty)
{
Start = End = node;
}
else
{
Start!.Previous = node;
node.Next = Start;
Start = node;
}
Count++;
}
public void Remove(ListNode<T> node)
{
if (node != Start)
{
node.Previous!.Next = node.Next;
}
else
{
Start = node.Next;
}
if (node != End)
{
node.Next!.Previous = node.Previous;
}
else
{
End = node.Previous;
}
Count--;
}
public IEnumerable<T> GetAllValues()
{
var counter = Start;
while (counter != null)
{
yield return counter.Value;
counter = counter.Next;
}
}
}
public class ListNode<T>
{
public T Value { get; }
public ListNode<T>? Previous { get; set; }
public ListNode<T>? Next { get; set; }
public ListNode(T value)
{
Value = value;
}
}
}
you can do something like this.
var recordsToRemove = dictionary.Where(x => x.Value.Contains("what you are looking for"))
.ToList();
if (recordsToRemove.Any())
{
foreach (var record in recordsToRemove)
{
dictionary.Remove(record.Key);
}
}

Can't search for the max value into an array

My problem is that i can't search into an array using linq in order to find an object property and set that as an id.
I need the method to search in the array for other model.idCliente and set that value as the "nextid + 1", in order to use it as id and the next array index.
Since the array's empty, the program adds the new object correctly, but when entering in the else if case, i get an axception for "a as null".
This is my code (where i get an exception on the else if linq line saying that "a" is null):
//Arrays
ClienteModel[] MemoryClienti = new ClienteModel[19];
OrdineModel[] MemoryOrdini = new OrdineModel[19];
//Aggiungi
public bool CreateCliente(ClienteModel model)
{
if (MemoryClienti[0] == null)
{
int defaultID = 0;
int defaultIndex = 0;
model.IDCliente = defaultID;
MemoryClienti[defaultIndex] = model;
}
else if (MemoryClienti[0]!=null)
{
var maxID = MemoryClienti.Max(a => a.IDCliente);
model.IDCliente = maxID++;
MemoryClienti[maxID++] = model;
}
return true;
}
This is the code of the form click:
//Aggiungi Cliente
private void aggiungiClienteButton_Click(object sender, EventArgs e)
{
clienteModel.Cognome = cognomeTextBox.Text;
clienteModel.Nome = nomeTextBox.Text;
clienteModel.Indirizzo = indirizzoTextbox.Text;
dbMemoryManager.CreateCliente(clienteModel);
MessageBox.Show("Cliente aggiunto correttamente.");
cognomeTextBox.Text = String.Empty;
nomeTextBox.Text = String.Empty;
indirizzoTextbox.Text = String.Empty;
}
This is the ClienteModel class:
public class ClienteModel
{
public int IDCliente { get; set; }
public string Cognome { get; set; }
public string Nome { get; set; }
public string Indirizzo { get; set; }
}
Wouldn't the following code achieve what you are trying to do?
ClienteModel[] MemoryClienti = new ClienteModel[19];
OrdineModel[] MemoryOrdini = new OrdineModel[19];
int maxID = 0; /* 0 is not a valid ID. IDs start from 1 */
//Aggiungi
public bool CreateCliente(ClienteModel model)
{
if(maxID <= MemoryClienti.Length) {
MemoryClienti[maxID++] = model; // copy the reference
model.IDCliente = maxID; // update the object's ID
return true;
} else {
return false; // can't add. array is full
}
}
If you are also doing deletions, you are better off using a List as others have also suggested.

How to transform list of hierarchyid into a binary tree

I am working on a multi-level marketing (binary) which looks like this:
(but the binary tree is not required to be perfect. A node can have 0-2 child)
My problem is the data that I fetch from the database is flat list.
Notice that I am using hierarchyid (sql server 2014)
Basically the TextNode column is like a breadcrumb.
every slash / represents a level.
If I have TextNode of /1/ as root. then every node that starts with /1/ belongs to that root which are /1/, /1/1/ and /1/1/1/ (the root node is included which will be the level 0)
I've tried the accepted answer in this question but its not working.
How can I transform the flatlist to a Binary Tree so that I can easily traverse and display it on a screen?
Im using C#, ASP MVC 5, SQL Server 2014 if it matters.
I implement exactly this code According to Alex implementation but as is mentioned in some case it didn't work correctly .. have a look to my Image and my code (which copied from Alex post) [data in the database are correct but in tree view seems some problems ]
public class Row : IRow<string>
{
public string TextNode { get; }
public string Value { get; }
public long Id { get; }
public string FIN { get; }
public Row(string textNode, string userName, long id, string fin)
{
FIN = fin;
Id = id;
TextNode = textNode;
Value = userName;
}
}
public interface IRow<out T>
{
string TextNode { get; }
long Id { get; }
string FIN { get; }
T Value { get; }
}
public class TreeNode<T>
{
private struct NodeDescriptor
{
public int Level { get; }
public int ParentIndex { get; }
public NodeDescriptor(IRow<T> row)
{
var split = row.TextNode.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
Level = split.Length;
ParentIndex = split.Length > 1 ? int.Parse(split[split.Length - 2]) - 1 : 0;
}
}
public T title { get; }
public long Id { get; }
public string FIN { get; }
public List<TreeNode<T>> children { get; }
private TreeNode(T value, long id, string fin)
{
Id = id;
FIN = fin;
title = value;
children = new List<TreeNode<T>>();
}
public static TreeNode<T> Parse(IReadOnlyList<IRow<T>> rows)
{
if (rows.Count == 0)
return null;
var result = new TreeNode<T>(rows[0].Value, rows[0].Id, rows[0].FIN);
FillParents(new[] { result }, rows, 1, 1);
return result;
}
private static void FillParents(IList<TreeNode<T>> parents, IReadOnlyList<IRow<T>> rows, int index, int currentLevel)
{
var result = new List<TreeNode<T>>();
for (int i = index; i < rows.Count; i++)
{
var descriptor = new NodeDescriptor(rows[i]);
if (descriptor.Level != currentLevel)
{
FillParents(result, rows, i, descriptor.Level);
return;
}
var treeNode = new TreeNode<T>(rows[i].Value, rows[i].Id, rows[i].FIN);
parents[descriptor.ParentIndex].children.Add(treeNode);
result.Add(treeNode);
}
}
}
g
this is also my JSON output for more information :
{"title":"Earth","Id":32,"FIN":"FIN","children":[{"title":"Europe","Id":33,"FIN":"FIN001","children":[{"title":"France","Id":35,"FIN":"FIN001001","children":[{"title":"Paris","Id":36,"FIN":"FIN001001001","children":[]},{"title":"Brasilia","Id":41,"FIN":"FIN002001001","children":[]},{"title":"Bahia","Id":42,"FIN":"FIN002001002","children":[]}]},{"title":"Spain","Id":38,"FIN":"FIN001002","children":[{"title":"Madrid","Id":37,"FIN":"FIN001002001","children":[{"title":"Salvador","Id":43,"FIN":"FIN002001002001","children":[]}]}]},{"title":"Italy","Id":45,"FIN":"FIN001003","children":[]},{"title":"Germany","Id":48,"FIN":"FIN001004","children":[]},{"title":"test","Id":10049,"FIN":"FIN001005","children":[]}]},{"title":"South America","Id":34,"FIN":"FIN002","children":[{"title":"Brazil","Id":40,"FIN":"FIN002001","children":[{"title":"Morano","Id":47,"FIN":"FIN001003001","children":[]}]}]},{"title":"Antarctica","Id":39,"FIN":"FIN003","children":[{"title":"McMurdo Station","Id":44,"FIN":"FIN003001","children":[]}]}]}
Here is a very simple implementation (assuming that Nodes are in the right order), which may be enhanced in multiple ways
public interface IRow<out T>
{
string TextNode { get; }
T Value { get; }
}
public class TreeNode<T>
{
private struct NodeDescriptor
{
public int Level { get; }
public int ParentIndex { get; }
public NodeDescriptor(IRow<T> row)
{
var split = row.TextNode.Split(new [] {"/"}, StringSplitOptions.RemoveEmptyEntries);
Level = split.Length;
ParentIndex = split.Length > 1 ? int.Parse(split[split.Length - 2]) - 1 : 0;
}
}
public T Value { get; }
public List<TreeNode<T>> Descendants { get; }
private TreeNode(T value)
{
Value = value;
Descendants = new List<TreeNode<T>>();
}
public static TreeNode<T> Parse(IReadOnlyList<IRow<T>> rows)
{
if (rows.Count == 0)
return null;
var result = new TreeNode<T>(rows[0].Value);
FillParents(new[] {result}, rows, 1, 1);
return result;
}
private static void FillParents(IList<TreeNode<T>> parents, IReadOnlyList<IRow<T>> rows, int index, int currentLevel)
{
var result = new List<TreeNode<T>>();
for (int i = index; i < rows.Count; i++)
{
var descriptor = new NodeDescriptor(rows[i]);
if (descriptor.Level != currentLevel)
{
FillParents(result, rows, i, descriptor.Level);
return;
}
var treeNode = new TreeNode<T>(rows[i].Value);
parents[descriptor.ParentIndex].Descendants.Add(treeNode);
result.Add(treeNode);
}
}
}
Sample usage:
public class Row : IRow<string>
{
public string TextNode { get; }
public string Value { get; }
public Row(string textNode, string userName)
{
TextNode = textNode;
Value = userName;
}
}
class Program
{
static void Main(string[] args)
{
IRow<string>[] rows =
{
new Row("/", "Ahmed"),
new Row("/1/", "Saeed"),
new Row("/2/", "Amjid"),
new Row("/1/1/", "Noura"),
new Row("/2/1/", "Noura01"),
new Row("/2/2/", "Reem01"),
new Row("/1/1/1", "Under_noura")
};
var tree = TreeNode<string>.Parse(rows);
PrintTree(tree);
}
private static void PrintTree<T>(TreeNode<T> tree, int level = 0)
{
string prefix = new string('-', level*2);
Console.WriteLine("{0}{1}", prefix, tree.Value);
foreach (var node in tree.Descendants)
{
PrintTree(node, level + 1);
}
}
}

Add child to class properties in for cycle

I have a problems with adding subelements off AddressElement objects
My test class:
public class AddressElement
{
public AddressElement[] AddressElement1 { get; set; }
public string PostIndex { get; set; }
}
My test interface:
public interface IAddress
{
string PostIndex { get; }
}
private AddressElement CreateAddressElement(IAddress address)
{
return new AddressElement
{
PostIndex = address.PostIndex
};
}
private int startIndex = 0;
private int finalIndex = 5;
Get elements method:
private AddressElement[] GetAddressElements(List addresses, int startIndex, int finalIndex)
{
List addressElements = new List();
for (int i = startIndex; i < finalIndex; i++)
{
if (i == startIndex)
{
addressElements.Add(CreateAddressElement(addresses[i]));
if (i != startIndex )
{
AddressElement addressElement = addressElements[startIndex];
addressElements[startIndex].AddressElement1 = new[] { CreateAddressElement(addresses[i]) };
}
I need add all subelements of AddressElement in for cycle: addressElements[startIndex].AddressElement1[startIndex].AddressElement1[startIndex].AddressElement1[startIndex].AddressElement1[startIndex]....
You can do this by using Linq :
private AddressElement[] GetAddressElements(List addresses, int startIndex, int finalIndex) {
return addresses.Skip(startIndex).Take(finalIndex - startIndex).Select(s => CreateAddressElement(s)).ToArray() ;
}
Hope it will help you.

How to retrieve the couchbase view results using iteration?

This is my code for retrieving the list of comments from couchbase. The design document name is "Task" and the view name is: "GetComments".
public List<CommentsVO> GetComments(string TaskID, int LastCommentID, int totalCommentCount)
{
int startCount = LastCommentID - 1;
int endCount = startCount - 19;
int remainingCount = totalCommentCount - endCount;
if (endCount < 0)
{
endCount = 0;// totalCommentCount - remainingCount;
}
IView<CommentsVO> results = oCouchbase.GetView<CommentsVO>("Task", "GetComments");
results.StartKey(new object[] { TaskID, startCount }).EndKey(new object[] { TaskID, endCount });
if (results != null)
{
List<CommentsVO> resultlist = new List<CommentsVO>();
foreach (CommentsVO vo in results)//Here it is not entering inside the loop... Am i missing anything in this condition
{
resultlist.Add(vo);
}
resultlist.Reverse();
return resultlist;
}
return null;
}
My CommentsVo code is:
public class CommentsVO
{
public CommentsVO()
{
CommentedOn = Convert.ToString(DateTime.Now);
IsActive = "1";
}
[JsonIgnore]
public string TaskID { get; set; }
[JsonProperty("commented_user_id")]
public string CommentedUserID { get; set; }
[JsonProperty("commented_user_name")]
public string CommentedUserName { get; set; }
[JsonProperty("comment_description")]
public string CommentDescription { get; set; }
[JsonProperty("commented_on")]
public string CommentedOn { get; set; }
[JsonProperty("is_active")]
public string IsActive { get; set; }
[JsonProperty("seq")]
public string Sequence { get; set; }
}
My couchbase view code is:
function(doc) {
for(var i in doc.comments) {
emit([doc._id,doc.comments[i].seq],doc.comments[i]);
}
}
I have tried without using startkey and endkey its iterating but when i tried using startkey and endkey it is not entering inside the loop..
Kindly help me out..
When using a composite key, you would specify an array of keys in StartKey/EndKey. In your code, you're actually overwriting the keys with your second calls to StarKey and EndKey.
So something like:
results.StartKey(new object[] { TaskId, startCount }).EndKey(new object[] { TaskId, endCount });

Categories