I have two date columns and two size columns (one size column related to one date column) like you can see in the Following table. Now I want the two arrays where in the first array it will be sort by Collected and show the cumulative effect of CollectedSize and same with Staged and StagedSize.
Required:
Collected array |
1/1/2016 | 1
11/1/2016 | 4
12/1/2016 | 6
30/1/2016 | 11
Staged array |
13/1/2016 | 3
14/1/2016 | 7
18/1/2016 | 13
16/1/2016 | 20
Table:
| Collected | CollectedSize | Staged | StagedSize |
| 11/1/2016 | 3 | 14/1/2016 | 4
| 12/1/2016 | 2 | 13/1/2016 | 3
| 30/1/2016 | 5 | 18/1/2016 | 7
| 01/1/2016 | 1 | 16/1/2016 | 6
Currently using the following code:
public class ProductionDataOverTimeVM
{
public ProductionDataOverTimeVM()
{
Collected = new List<TimeChartXAxis>();
Staged = new List<TimeChartXAxis>();
}
public List<TimeChartXAxis> Collected { get; set; }
public List<TimeChartXAxis> Staged { get; set; }
}
public class TimeChartXAxis
{
public string x { get; set; }
public string y { get; set; }
}
var queryResults = context.Datasets.ToList();
ProductionDataOverTimeVM obj = new ProductionDataOverTimeVM();
long? collectedBytes = 0;
long? Staged = 0;
foreach (var dataset in queryResults.OrderBy(d => d.Collected))
{
if (dataset.Collected != null)
{
collectedBytes = collectedBytes + dataset.CollectedSize;
obj.Collected.Add(new TimeChartXAxis
{
x = dataset.Collected != null ? BasicHelpers.FromUTCDate(dataset.Collected, parms.Offset).Value.ToString("dd/M/yyyy") : null,
y = BasicHelpers.FormatBytesToSpecificFormat(collectedBytes, format, false)
});
}
}
foreach (var dataset in queryResults.OrderBy(d => d.Staged))
{
if (dataset.Staged != null)
{
Staged = Staged + dataset.StagedSize;
obj.Staged.Add(new TimeChartXAxis
{
x = dataset.Staged != null ? BasicHelpers.FromUTCDate(dataset.Staged, parms.Offset).Value.ToString("dd/M/yyyy") : null,
y = BasicHelpers.FormatBytesToSpecificFormat(Staged, format, false)
});
}
}
What will be the best approach to do that?
What about
var arrayofOrderByString = new []{"Collected","Staged"}
foreach(var key in arrayofOrderByString){
var y=0;
SortList<Datasets>(queryResults, key, SortDirection.Descending);
queryResults.foreach(s =>{
y=s.GetType().GetProperty(key).GetValue(s, null);
obj.Collected.Add(new ProductionDataOverTimeVM{
x =BasicHelpers.FromUTCDate(s.GetType().GetProperty(key).GetValue(s, null), parms.Offset).Value.ToString("dd/M/yyyy"),
y=collectedBytes
})
})
}
public void SortList<T>(List<T> list, string columnName, SortDirection direction)
{
var property = typeof(T).GetProperty(columnName);
var multiplier = direction == SortDirection.Descending ? -1 : 1;
list.Sort((t1, t2) => {
var col1 = property.GetValue(t1);
var col2 = property.GetValue(t2);
return multiplier * Comparer<object>.Default.Compare(col1, col2);
});
}
Related
I'd like to select many values from a table with a list.
I have FabricTable(Year is int):
+----+-------+---------+------+
| Id | Color | Texture | Year |
+----+-------+---------+------+
| 1 | Red | Rough | 2019 |
+----+-------+---------+------+
| 2 | Green | Soft | 2019 |
+----+-------+---------+------+
| 3 | Blue | Rough | 2019 |
+----+-------+---------+------+
| 4 | Red | Med | 2019 |
+----+-------+---------+------+
| 5 | Blue | Soft | 2018 |
+----+-------+---------+------+
I have selectedItems list (year is int):
+---------+------+
| Texture | Year |
+---------+------+
| Rough | 2019 |
+---------+------+
| Soft | 2019 |
+---------+------+
I'd like to get the Id from table, it should result with Id = 1, 2, & 3.
How can I achieve this with Linq in C#? I just need to select by Texture & Year
Here's what I've tried but I'm not sure how to select from list with multiple values(selectedItems is a list but I don't know how to query multiple columns):
db.FabricTable.Select(o => o.Texture == selectedItems.Texture && o.Year == selectItems.Year)
You get a compiler error when using selectedItems.Texture because selectedItem is a list that contains an object with the Texture property. You need to check all of the items in the list when searching for the desired items in FabricTable:
var items = db.FabricTable.Where(o => selectedItems.Any(selectedItem => o.Texture == selectedItem.Texture && o.Year == selectedItem.Year));
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication120
{
class Program
{
static void Main(string[] args)
{
List<Item> items = new List<Item>() {
new Item() { Id = 1, Color = "Red", Texture = "Rough", Year = 2019},
new Item() { Id = 2, Color = "Green", Texture = "Soft", Year = 2019},
new Item() { Id = 3, Color = "Blue", Texture = "Rough", Year = 2019},
new Item() { Id = 4, Color = "Red", Texture = "Soft", Year = 2018}
};
DataTable dt = new DataTable();
dt.Columns.Add("Color", typeof(string));
dt.Columns.Add("Texture", typeof(string));
dt.Columns.Add("Year", typeof(int));
foreach (Item item in items.Where(x => (x.Texture == "Rough") && (x.Year == 2019)))
{
dt.Rows.Add(new object[] { item.Color, item.Texture, item.Year });
}
}
}
public class Item
{
public int Id { get; set; }
public string Color { get; set; }
public string Texture { get; set; }
public int Year { get; set; }
}
}
I'm writing a web page using C# MVC5 & MySQL, when I request a number from int field, MySQL always return a wrong number, I can't find some solution.
MySQL like:
| Id | Type | Level | Parent_id |ChildrenCount |
| 1 | T | 1 | 1 |3 |
| 2 | SC | 2 | 1 |2 |
| 3 | SH | 3 | 2 |1 |
| 4 | TK | 4 | 3 |0 |
...
I can use sql show them normal.
But C# can not.
Below is C# code.
public Item GetItem(int id, int level, int pos)
{
Item item = new Item { Id = -1 };
using (MySqlConnection con = new DBConnect().MySql())
{
string sql = $"SELECT * FROM item WHERE Parent_id={id} AND Level={level} LIMIT {pos}, 1;";
using (MySqlCommand cmd = new MySqlCommand(sql, con))
{
con.Open();
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
item.Id = reader.GetInt32(0);
item.Type = reader.GetString(1);
item.Level = reader.GetInt32(2);
item.ChildrenCount = reader.GetInt32(3);
};
}
}
return item;
}
public void GetItemList(int id, int level, int count, ref List<Item> pli, int initPos=0)
{
int pos = 0;
pos += initPos;
Item item = GetItem(id, level, pos);
if (item.Id == -1)
{
return;
}
pli.Add(item);
// Here item.Level is wrong.
if (pli.Count() < count)
{
if (item.ChildrenCount > 0)
{
int ChildPos = 0;
int newLevel = item.Level + 1;
GetItemList(item.Id, newLevel, count, ref pli, ChildPos);
}
else
{
int newPos = pos + 1;
GetItemList(id, level, count, ref pli, newPos);
}
}
}
call by
public List<Item> GetInitItem(int id)
{
List<Item> resItemList = new List<Item> { };
GetItemList(id, level: 1, count: 50, pli: ref resItemList, initPos: 0);
return resItemList;
}
other information all right, only Level column is wrong, all return 1.
That's result in page:
ID:6133 Type:T Level:1 Count:744
ID:6154 Type:SC Level:1 Count:67
I have "googled" for many hour but still I am not able to find an answer. Basically, I have a table that looks like this:
Parent | ID
null | 1
1 | 2
2 | 3
3 | 4
3 | 5
3 | 6
4 | 7
null | 8
How can I use entity linq to filter based on Id and "depth level" (which is a simple count of elements including the Id element and n - 1 elements passed the Id element)?
For example when I pass Id 2 and depth level 2
Result will be
Parent | ID
2 | 3 //level 1
3 | 4 //level 2
3 | 5 //level 2
3 | 6 //level 2
If I pass Id 3 and depth level also 2
Result will be
Parent ID
3 | 4 //level 1
3 | 5 //level 1
3 | 6 //level 1
4 | 7 //level 2
Thanks for your help
I tired to simulate your scenario in a Console application. Following is one of the possible solution. Its very basic so you need to change and use it as you need. But it returns results as per logic you mention in your question.
class Program
{
static List<Data> data = new List<Data>();
static List<Data> result = new List<Data>();
static void Main(string[] args)
{
data.Add(new Data() { Parent = null, ID = 1 });
data.Add(new Data() { Parent = 1, ID = 2 });
data.Add(new Data() { Parent = 2, ID = 3 });
data.Add(new Data() { Parent = 3, ID = 4 });
data.Add(new Data() { Parent = 4, ID = 5 });
data.Add(new Data() { Parent = null, ID = 6 });
// Take() implementation is for Depth.
result = findChildren(3).Take(2).ToList();
Console.ReadLine();
}
static List<Data> findChildren(int Id)
{
return data.Where(x => x.Parent == Id ).Union(data.Where(x => x.Parent == Id).SelectMany(y => findChildren(y.ID))).ToList();
}
}
public class Data
{
public int? Parent { get; set; }
public int ID { get; set; }
}
var Id = 2;
var Level = 2;
var head = new Item { Id = Id };
var result = new List<Item>();
for(var i = 0; i < Level; i++)
{
head = context.Table.FirstOrDefault(x => x.ParetId == head.Id);
if(head != null)
result.Add(head);
else
break;
}
I am retrieving records from a db and creating the following object:
public class RemittanceBatchProcessingModel
{
public string FileId { get; set; }
public string SourceFileName { get; set; }
public string BatchCode { get; set; }
public string BatchType { get; set; }
public decimal PaymentAmount { get; set; }
public string BillingSystemCode { get; set; }
}
Example objects created after db read:
FileId | SourceFileName | BatchCode | BatchType | PaymentAmt |BillingCode
1 | test.file1.txt | 100 | S | 1000.00 | Exc
1 | test.file1.txt | 100 | S | 2000.00 | Exc
1 | test.file1.txt | 200 | N | 500.00 | Adc
2 | test.file2.txt | 300 | S | 1200.00 | Exc
2 | test.file2.txt | 300 | S | 1500.00 | Exc
I want to create an object that has a collection of the unique files which has a collection of each summarized batch within a file. For example,
Collection of Unique Files:
FileId | SourceFileName | BatchCode | BatchType | BatchTotal |RecordCount
1 | test.file1.txt | 100 | S | 3000.00 | 2
1 | test.file1.txt | 200 | N | 500.00 | 1
2 | test.file2.txt | 100 | S | 1700.00 | 2
I am able to create my collection of batches with no issue the problem I'm having is figuring out how to create the collection of unique files with the correct batches within them. I'm attempting this using the following:
private static RemittanceCenterFilesSummaryListModel SummarizeFiles(RemittanceCenterSummaryListModel remittanceCenterSummaryListModel)
{
var summarizedBatches = SummarizeBatches(remittanceCenterSummaryListModel);
var fileResult = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord.GroupBy(x => new { x.FileId, x.SourceFileName })
.Select(x => new RemitanceCenterFileSummarizedModel()
{
FileId = x.Key.FileId,
SourceFileName = x.Key.SourceFileName,
ScannedBatchCount = x.Count(y => y.BatchType == "S"),
ScannedBatchAmount = x.Where(y => y.BatchType == "S").Sum(y => y.PaymentAmount),
NonScannedBatchCount = x.Count(y => y.BatchType != "S"),
NonScannedBatchAmount = x.Where(y => y.BatchType != "S").Sum(y => y.PaymentAmount),
});
var summaryListModel = CreateSummaryFilesListModel(fileResult);
summaryListModel.Batches = summarizedBatches.RemittanceBatchSummary;
return summaryListModel;
}
private static RemittanceCenterFilesSummaryListModel CreateSummaryFilesListModel(IEnumerable<RemitanceCenterFileSummarizedModel> summaryModels)
{
var summaryModelList = new RemittanceCenterFilesSummaryListModel();
foreach (var summaryFileRec in summaryModels)
{
var summaryModel = new RemitanceCenterFileSummarizedModel
{
FileId = summaryFileRec.FileId.ToString(CultureInfo.InvariantCulture),
SourceFileName = summaryFileRec.SourceFileName.ToString(CultureInfo.InvariantCulture),
ScannedBatchCount = summaryFileRec.ScannedBatchCount,
ScannedBatchAmount = summaryFileRec.ScannedBatchAmount,
NonScannedBatchCount = summaryFileRec.NonScannedBatchCount,
NonScannedBatchAmount = summaryFileRec.NonScannedBatchAmount
};
summaryModelList.RemittanceFilesSummary.Add(summaryModel);
}
return summaryModelList;
}
You can group it on the 4 columns including BatchType and BatchCode as well and pick the Count and sum the Amount like :
var fileResult = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord
.GroupBy(x => new
{
x.FileId,
x.SourceFileName,
x.BatchType,
x.BatchCode
})
.Select(x => new
{
FileId = x.Key.FileId,
SourceFileName = x.Key.SourceFileName,
BatchType = x.Key.BatchType,
BatchCode = x.Key.BatchCode,
BatchTotal= x.Sum(y=>y.PaymentAmt),
RecordCount = x.Count()
});
I guess you need to GroupBy FileId & BatchType instead of FileName:-
var fileResult = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord
.GroupBy(x => new { x.FileId, x.BatchType })
.Select(x =>
{
var firstObj = x.FirstOrDefault();
return new RemitanceCenterFileSummarizedModel()
{
FileId = x.Key.FileId,
SourceFileName = firstObj.SourceFileName,
BatchCode = firstObj.BatchCode,
BatchType = x.Key.BatchType,
BatchTotal = x.Sum(z => z.PaymentAmt),
RecordCount = x.Count()
};
});
Considering FileId maps to SourceFileName & BatchCode maps to BatchType you can simply store the first set in a variable like I did in firstObj to get the relevant values which are not grouped. Please check for nulls before accessing relevant properties as it may cause NRE if no set is found.
For pure linq non fluent
var files = new[] {
new { FileId = 1, SourceFileName = "test.file1.txt" , BatchCode = 100 , BatchType = "S", PaymentAmt = 1000.00 , BillingCode = "Exc" },
new { FileId = 1, SourceFileName = "test.file1.txt" , BatchCode = 100 , BatchType = "S", PaymentAmt = 2000.00 , BillingCode = "Exc" },
new { FileId = 1, SourceFileName = "test.file1.txt" , BatchCode = 200 , BatchType = "N", PaymentAmt = 500.00 , BillingCode = "Adc" },
new { FileId = 1, SourceFileName = "test.file2.txt " , BatchCode = 300 , BatchType = "S", PaymentAmt = 1200.00 , BillingCode = "Exc" },
new { FileId = 1, SourceFileName = "test.file2.txt " , BatchCode = 300 , BatchType = "S", PaymentAmt = 1500.00 , BillingCode = "Exc" }
};
var result = from file in files
group file by new { file.FileId, file.BatchCode } into fileBachGroups
select new
{
FileId = 1,
SourceFileName = fileBachGroups.First().SourceFileName,
BatchCode = fileBachGroups.Key.BatchCode,
BatchType = fileBachGroups.First().BatchType,
BatchTotal = fileBachGroups.Sum(f => f.PaymentAmt),
RecordCount = fileBachGroups.Count()
};
Console.WriteLine("FileId | SourceFileName | BatchCode | BatchType | BatchTotal |RecordCount");
foreach (var item in result)
{
Console.WriteLine("{0} | {1} | {2} | {3} | {4} | {5}",item.FileId,item.SourceFileName, item.BatchCode, item.BatchType, item.BatchTotal, item.RecordCount);
}
| FieldName | header | code |
| a1 | test | |
| a1 | test | 1 |
| a1 | test | 2 |
| a1 | test | 3 |
| a1 | test | 4 |
| a1 | test | 5 |
| b2 | prod | 1 |
| b2 | prod | 2 |
| b2 | prod | 3 |
I have the following code to loop thru the table and add the data in a hashtable.
Currently my code only adds one a1 and b2. but what I am planing to do is add them all in my hashtable with a different key.
For example: ("a11",value), ("a12",value); ("a13",value); and the same for b2..ect.
public Hashtable GetData(Table table, string headerType)
{
var data = table.CreateSet<SpecFlowData>();
var hashtable = new Hashtable();
hashtable.Clear();
foreach (var currentRow in data)
{
var key = currentRow.FieldName;
var value = new Hashtable();
GetValue(value, currentRow);
if (hashtable.ContainsKey(key)) //continue;
{
var r = new Random();
key = key + r.Next();
}
var format = (string)value["header"];
if (headerType == format)
{
hashtable.Add(key, value);
}
break;
}
return hashtable;
}
Update: Here is the getvalue method:
private static void GetValue(Hashtable value, SpecFlowData currentRow)
{
value.Clear();
value.Add("code", currentRow.Code);
value.Add("name", currentRow.FieldName);
value.Add("header", currentRow.HeaderType);
}
Why is my data not added properly. thanks for your help.
You are breaking out of the foreach loop at the end of your first iteration, so there can only be one key-value-pair in your Hashtable.
If you remove the break statement, you will get more values. As #JohnGardner mentioned, you should not use a random, because it may produce identical values. Simply use an increasing integer variable.
So after all, this should do:
public Hashtable GetData(Table table, string headerType)
{
var data = table.CreateSet<SpecFlowData>();
var hashtable = new Hashtable(); // no need to clear a newly created Hashtable
int i = 1;
foreach (var currentRow in data)
{
var key = currentRow.FieldName;
var value = GetValue(currentRow);
if (hashtable.ContainsKey(key))
{
key = key + i++;
}
var format = (string)value["header"];
if (headerType == format)
{
hashtable.Add(key, value);
}
}
return hashtable;
}
private static Hashtable GetValue(SpecFlowData currentRow)
{
var value = new Hashtable();
value.Add("code", currentRow.Code);
value.Add("name", currentRow.FieldName);
value.Add("header", currentRow.HeaderType);
}