How to retrieve the couchbase view results using iteration? - c#

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 });

Related

Returning a List<> inheritance C#

class cuentaBancaria
{
public cuentaBancaria()
{
}
public cuentaBancaria(string nombreCliente, string numCuenta, double tipoInteres, double saldo)
{
this.nombreCliente = nombreCliente;
this.numCuenta = numCuenta;
this.tipoInteres = tipoInteres;
this.saldo = saldo;
}
public string nombreCliente { get; set; }
public string numCuenta { get; set; }
public double tipoInteres { get; set; }
public double saldo { get; set; }
public static List<cuentaBancaria> cuentas = new List<cuentaBancaria>()
{
new cuentaBancaria ("John Doe", "123456", 1.5, 159),
new Tarjeta ("John Doe", "123456" , 1.5, 159, "123456789012", "John Doe", TipoTarjeta.CREDITO)
};
}
TipoTarjeta:
enum TipoTarjeta
{
CREDITO,
DEBITO,
MONEDERO,
FINANCIACION
}
Tarjeta:
class Tarjeta : cuentaBancaria
{
public Tarjeta()
{
}
public Tarjeta(string nombreCliente, string numCuenta, double tipoInteres, double saldo, string numTarjeta, string nombre, TipoTarjeta tipoTarjeta)
{
base.nombreCliente = nombreCliente;
base.numCuenta = numCuenta;
base.tipoInteres = tipoInteres;
base.saldo = saldo;
this.numTarjeta = numTarjeta;
this.nombre = nombre;
this.tipoTarjeta = tipoTarjeta;
}
public string numTarjeta { get; set; }
public string nombre { get; set; }
public TipoTarjeta tipoTarjeta { get; set; }
}
I want to return the elements that has a TipoTarjeta.XXX but when I try the
cuentas.Where(c => c.tipoTarjeta == tipo)
I get the error that is an element of the child (Tarjeta) not cuentaBancaria.
How can I only get those elements with that type?
You have a type mismatch.
Your function is declared such that it returns List<cuentaBancaria>, but Where is a LINQ extension method that returns an IEnumerable<cuentBancaria>.
To resolve your issue, add a call to the ToList() extension method as follows:
cuentas.Where(c => c.tipoTarjeta == tipo).ToList()
UPDATE
I copied your code to VSCode and this version of Main works for me. From what I could tell, you needed to reference cuentas through cuentaBancaria; also, the property you were referencing in the Where clause was incorrect, based on the class definition.
public static void Main()
{
var tipo = 3.15;
var result = cuentaBancaria.cuentas.Where(c => c.tipoInteres == tipo).ToList();
foreach (var item in result)
{
Console.WriteLine(item.tipoInteres);
}
}
You first need to filter the list to only the types of Tarjeta, and then you can filter by properties of Tarjeta. You can do this using .OfType<T>() in LINQ:
cuentas.OfType<Tarjeta>().Where(c => c.tipoTarjeta == tipo)

Allowing a user to select column headers to import

I'm using LINQtoCSV within a program that allows the user to import an order from a CSV file. I have all the code working however, if the CSV file doesn't have the exact column headers then it doesn't work.
Below is my class that LINQtoCSV reads into -
public class orderProduct
{
public orderProduct() { }
public string product { get; set; }
public string price { get; set; }
public string orderQty { get; set; }
public string value { get; set; }
public string calculateValue()
{
return (Convert.ToDouble(price) * Convert.ToDouble(orderQty)).ToString();
}
}
If the CSV file doesn't have the exact headers it won't work. The data I actually only need is the first 4 strings.
Below is my function that actually reads in the data.
private void csvParse()
{
// order.Clear();
string fileName = txt_filePath.Text.ToString().Trim();
try
{
CsvContext cc = new CsvContext();
CsvFileDescription inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true
};
IEnumerable<orderProduct> fromCSV = cc.Read<orderProduct>(fileName, inputFileDescription);
foreach (var d in fromCSV)
{
MessageBox.Show($#"Product:{d.product},Quantity:""{d.orderQty}"",Price:""{d.price}""");
orderReturn.Add(d);
}
this.DialogResult = DialogResult.Yes;
this.Close();
}
catch (Exception ex)
{
if (ex.ToString().Contains("being used by another process"))
{
MessageBox.Show("Error: Please close the file in Excel and try again");
}
else
{
MessageBox.Show(ex.ToString());
}
}
}
I want the user to be able to just pass in a file and then select the relevant columns which relate to the corresponding values and then read in the data ignoring any columns that haven't been selected.
Hope this all makes sense, is something like this possible within LINQtoCSV
You have to add IgnoreUnknownColumns = true to your CsvFileDescription
CSV:
product,price,someColumn,orderQty,value,otherColumn
my product,$123,xx,2,$246,aa
my other product,$10,yy,3,$30,bb
Working code (I modified your code a little bit, to run it in a console)
using System;
using System.Collections.Generic;
using LINQtoCSV;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
csvParse();
Console.ReadLine();
}
private static void csvParse()
{
string fileName = "../../../test.csv"; // provide a valid path to the file
CsvContext cc = new CsvContext();
CsvFileDescription inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true,
IgnoreUnknownColumns = true // add this line
};
IEnumerable<orderProduct> fromCSV = cc.Read<orderProduct>(fileName, inputFileDescription);
foreach (var d in fromCSV)
{
Console.WriteLine($#"Product:{d.product},Quantity:""{d.orderQty}"",Price:""{d.price}""");
}
}
}
public class orderProduct
{
public orderProduct() { }
public string product { get; set; }
public string price { get; set; }
public string orderQty { get; set; }
public string value { get; set; }
public string calculateValue()
{
return (Convert.ToDouble(price) * Convert.ToDouble(orderQty)).ToString();
}
}
}
Output:
Product:my product,Quantity:"2",Price:"$123"
Product:my other product,Quantity:"3",Price:"$10"
If your properties have different names than CSV columns, you should use CsvColumn attribute:
public class OrderProduct
{
[CsvColumn(Name = "product")]
public string Product { get; set; }
[CsvColumn(Name = "price")]
public string Price { get; set; }
[CsvColumn(Name = "orderQty")]
public string OrderQuantity { get; set; }
public string Value { get; set; }
public string calculateValue()
{
return (Convert.ToDouble(Price) * Convert.ToDouble(OrderQuantity)).ToString();
}
}
Or if you prefer mapping columns by their indices:
public class OrderProduct
{
[CsvColumn(FieldIndex = 0)]
public string Product { get; set; }
[CsvColumn(FieldIndex = 1)]
public string Price { get; set; }
[CsvColumn(FieldIndex = 2)]
public string OrderQuantity { get; set; }
public string Value { get; set; }
public string calculateValue()
{
return (Convert.ToDouble(Price) * Convert.ToDouble(OrderQuantity)).ToString();
}
}
If you have to specify the columns on the fly, the only way seems to be to read raw data and process it yourself (the solution is based on this article):
internal class DataRow : List<DataRowItem>, IDataRow
{
}
...
int productColumnIndex = 0; // your users will provide it
var fromCSV = cc.Read<DataRow>(fileName);
foreach (var row in fromCSV)
{
var orderProduct = new OrderProduct
{
Product = row[productColumnIndex].Value,
};
Console.WriteLine(orderProduct.Product);
}

C# Linq - Select Multiple Fields where one field should also be filtered with a select

I'm a little bit stuck in Linq.
So first - I show you first the entities. I have a List let's name it "PersonalList" with another List of ListMembers.
public class PersonalList
{
public PersonalList();
public List<ListMember> ListMembers { get; set; }
public long ListNumber {get; set; }
public string Description {get; set;}
}
Here is the ListMember Class:
public class ListMember
{
public ListMember();
public string MemberName{ get; set; }
public long ListId {get; set; }
public string MemberType {get; set; }
public string Position {get; set; }
}
So now im my AppClass I have a List of the PersonalLists.
And I want to create a Dictionary, which has the PersonalList.ListNumber as Key and the Value should be the MemberName AND the MemberType.
What I have tried in first step is:
var personalLists = _allPersonalLists.Select(x => new {x.ListNumber, x.ListMembers).ToArray();
This solves the Problem with ListNumbers as Key. Now I want to have the ListMembers to be filtered so I have tried:
var personalLists = _allPersonalLists.Select(x => new {x.ListNumber, x.ListMembers.Select(y => new {y.MemberName, y.MemberType})}).ToArray();
But here - I get a compile error with following error message:
Error CS0746: Invalid anonymous type member declarator. Anonymous type
members must be declared with a member assignment, simple name or
member access.
So how can I achieve my goal? Any suggestions?
I tried to simulate your scenario and following solution will work for you.
public class PersonalList
{
public List<ListMember> ListMembers { get; set; }
public long ListNumber { get; set; }
public string Description { get; set; }
}
public class ListMember
{
public string MemberName { get; set; }
public long ListId { get; set; }
public string MemberType { get; set; }
public string Position { get; set; }
}
static void Main(string[] args)
{
List<PersonalList> _allPersonalLists = new List<PersonalList>();
for (int i = 1; i <= 5; i++)
{
List<ListMember> ListMembers = new List<ListMember>();
for (int j = 1; j <= 3; j++)
ListMembers.Add(new ListMember() { ListId = j, MemberName = "Member" + i + j, MemberType = "Type" + i, Position = "Position" + i });
_allPersonalLists.Add(new PersonalList() { ListNumber = i, ListMembers = ListMembers, Description = "Desc" + i });
}
var personalLists = _allPersonalLists.ToDictionary(x => x.ListNumber, x => x.ListMembers.Select(y => new { y.MemberName, y.MemberType }).ToList());
Console.ReadLine();
}
var personalLists = _allPersonalLists
.Select(x => new
{
x.ListNumber,
members = x.ListMembers
.Select(y => new
{
y.MemberName,
y.MemberType
}).ToList()
}).ToArray();
`.ToList()` i included to keep actual values otherwise it will be enumerable

How do I create and insert one-to-many object with entity framework c#

I'm trying to create an object and insert to the database but keep getting the same error no matter what I try.
The row that I get the error on is ColumnGroupTest.ValidValues.Add(memberComment1); the error is
error message
NullReferenceException was unhandled by user code
my models
public class StoreColumnName
{
public int Id { get; set; }
public string StoreColumnGroupName { get; set; }
public string ColumnName { get; set; }
public string ColumnType { get; set; }
public List<StoreValidValue> ValidValues { get; set; }
}
public class StoreValidValue
{
public int Id { get; set; }
public string ValidValue { get; set; }
public StoreColumnName StoreColumnName { get; set; }
}
my controller
public ActionResult Index()
{
XDocument document = XDocument.Load(#"C:\Users\Physical.xml");
var result = document.Descendants("ColumnGroup");
foreach(var item in result){
var ColumnGroupName = item.Attribute("name").Value;
var Columns = item.Descendants("Column");
foreach (var itemColumn in Columns)
{
StoreColumnName ColumnGroup = new StoreColumnName();
var ColumnGroupTest = new StoreColumnName
{
StoreColumnGroupName = ColumnGroupName,
ColumnName = itemColumn.Attribute("name").Value,
ColumnType = itemColumn.Attribute("type").Value,
Id = 11
};
var ValidValues = itemColumn.Descendants("ValidValues");
var Values = ValidValues.Descendants("Value");
foreach (var Value in Values)
{
var memberComment1 = new StoreValidValue
{
StoreColumnName = ColumnGroupTest,
ValidValue = Value.Value,
Id = 101
};
ColumnGroupTest.ValidValues.Add(memberComment1);
}
}
}
return View();
}
(I gladly take tips on what I can improve when asking for help/guiding here).
Can anyone help ?
The issue that you're having is that you don't initialize your ValidValues property to a list. By default, those types of properties initialize to null unless you specify differently.
The best approach is to add that initialization to your constructor of that object.
public StoreColumnName() {
this.ValidValues = new List<StoreValidValue>();
}

Codefirst degrades over time

The program below is a socket program that receives data at a pretty fast pace. It runs fine with the CodeFirst section disabled. If I enable it, the program starts out fine but then degrades slowly to the point where nothing appears to be written to the SQL EXPRESS 2012 db. I check this by running the SQL statement below which just selects the last five rows n SQL Management Studio 2012.
Is there something that I am doing wrong?
select * from [MarketDataEntities]
where MarketDataEntities.MarketDataEntityID not in (
select top (
(select count(*) from [MarketDataEntities]) - 5
) MarketDataEntities.MarketDataEntityID
from [MarketDataEntities]
)
using (var dbTDC = new TickDataTestContext())
{
var tde = new SymbolTickDataEntity { Symbol = symbol };
if (!dbTDC.SymbolTickDataDbSet.Any(a => a.Symbol.Equals(symbol)))
{
dbTDC.SymbolTickDataDbSet.Add(tde);
dbTDC.SaveChanges();
}
var mdde = new MarketDataDepthEntity();
dbTDC.MarketDataDepthDbSet.Add(mdde);
dbTDC.SaveChanges();
while (true)
{
// Wait for next request from client
int len = socket.Receive(zmq_buffer);
if (len < 1)
{
Console.WriteLine("Len < 1");
continue;
}
//Console.WriteLine("Got quote");
count++;
// Copy the bytes
byte[] bytes = new byte[len];
Buffer.BlockCopy(zmq_buffer, 0, bytes, 0, len);
MarketDataDepth mdd = MarketDataDepth.CreateBuilder().MergeFrom(bytes).Build();
PrintMarketDataDepth(mdd);
#if false
for (int i = 0; i < mdd.MdCount; i++)
{
MarketData md = mdd.MdList[i];
string timestamp = md.Time;
int index = timestamp.IndexOf(",");
if(-1 != index)
timestamp = timestamp.Remove(index);
DateTime parseResult;
if (false == System.DateTime.TryParseExact(timestamp, format, provider, DateTimeStyles.None, out parseResult))
continue;
var mde = new MarketDataEntity
{
NMDDTag = (long)mdd.NMDDTag,
QType = (0 == md.QuoteType ? QuoteType.Bid : QuoteType.Ask),
QPrice = md.Price,
QSize = md.Size,
QSource = md.Source,
QLiquidityTag = md.ID,
QSilo = md.Silo,
QTimeStamp = parseResult
};
dbTDC.MarketDataDbSet.Add(mde);
mdde.Depth.Add(mde);
}
if (0 == count % 500)
dbTDC.SaveChanges();
#endif
}
}
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
}
}
public enum QuoteType { Bid = 0, Ask }
public class MarketDataEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int MarketDataEntityID { get; set; }
public long NMDDTag { get; set; }
public QuoteType QType { get; set; }
public double QPrice { get; set; }
public double QSize { get; set; }
public string QSource { get; set; }
public string QLiquidityTag { get; set; }
public string QSilo { get; set;}
[Column("timestamp", TypeName = "datetime2")]
public DateTime QTimeStamp { get; set; }
}
public class MarketDataDepthEntity
{
public int MarketDataDepthEntityID { get; set; }
public virtual IList<MarketDataEntity> Depth { get; set; }
[Column("timestamp", TypeName = "datetime2")]
public DateTime TimeStamp { get; set; }
public MarketDataDepthEntity() { Depth = new List<MarketDataEntity>(); }
}
public class SymbolTickDataEntity
{
public int SymbolTickDataEntityID { get; set; }
[Key]
[Required]
public string Symbol { get; set; }
public virtual IList<MarketDataDepthEntity> Mdds { get; set; }
public SymbolTickDataEntity() { Mdds = new List<MarketDataDepthEntity>(); }
}
public class TickDataTestContext : DbContext
{
public DbSet<MarketDataEntity> MarketDataDbSet { get; set; }
public DbSet<MarketDataDepthEntity> MarketDataDepthDbSet { get; set; }
public DbSet<SymbolTickDataEntity> SymbolTickDataDbSet { get; set; }
}
From your code looks like you are keeping around the TickDataTestContext for the lifetime of your application. So as you keep adding data the local cache keeps increasing increasing memory usage hence performance degradation.
You should rewrite the code to create a new instance of TickDataTestContext for each request that needs to be saved then do the work, save changes and dispose the context.

Categories