I have a data like this in my database:
But when I output this on a stackedcolumn, I get this result and it has gap and it didnt start at 0
Here's my code:
string query = "SELECT * FROM TBL_SAMPLE INNER JOIN TBL_AREA ON TBL_SAMPLE.AREA = TBL_AREA.AREA";
DataTable dt = GetData(query);
//Get the DISTINCT Foods.
List<string> countries = (from p in dt.AsEnumerable()
select p.Field<string>("FOOD")).Distinct().ToList();
//Loop through the Foods.
foreach (string food in countries)
{
//Add Series to the Chart.
Chart1.Series.Add(new Series(food));
Chart1.Series[food].IsValueShownAsLabel = true;
//Get the Area for each Food.
int[] x = (from p in dt.AsEnumerable()
where p.Field<string>("FOOD") == food
select p.Field<int>("AREA_ID")).ToArray();
//Get the Total each food.
int[] y = (from p in dt.AsEnumerable()
where p.Field<string>("FOOD") == food
select p.Field<int>("TOTAL")).ToArray();
Chart1.Series[food].ChartType = SeriesChartType.StackedColumn;
Chart1.Series[food].Points.DataBindXY(x, y);
}
Chart1.Legends[0].Enabled = true;
Related
I have a database which holds data i need and i want to display these data in several different labels. I am choosing a Primary Key that represents rows in datatable from combobox and every selected index change i want to retrieve other related details to that specific Primary Key (MID) into labels.
I tried using below code;
private void CBMeasDBMID_SelectedIndexChanged(object sender, EventArgs e)
{
using (LinqDataClassesDataContext dataContext = new
LinqDataClassesDataContext())
{
var query = from x in dataContext.MeasResults
where x.MoldID == cBMeasDBMID.SelectedValue.ToString()
group x by x.MeasId into grp
select grp.OrderByDescending(x => x.Date).First();
var result = query.OrderByDescending(x => x.Date).Take(5);
daGridLastMeas.AutoGenerateColumns = false;
daGridLastMeas.Columns["MeasId"].DataPropertyName = "MeasId";
daGridLastMeas.Columns["Date"].DataPropertyName = "Date";
daGridLastMeas.Columns["Plane"].DataPropertyName = "Plane";
daGridLastMeas.Columns["Position"].DataPropertyName = "Postn";
daGridLastMeas.DataSource = result;
var manuf = from y in dataContext.Moulds
where y.MID == cBMeasDBMID.SelectedValue.ToString()
select y.manuf;
lblManufac.Text = manuf.ToString();
var size = from a in dataContext.Moulds
where a.MID == cBMeasDBMID.SelectedValue.ToString()
select a.Size;
lblSize.Text = size.ToString();
var lastmeas = from c in dataContext.MeasResults
where c.MoldID == cBMeasDBMID.SelectedValue.ToString()
select c.Date;
lblLastMeasDate.Text = lastmeas.ToString();
var wi = from d in dataContext.Moulds
where d.MID == cBMeasDBMID.SelectedValue.ToString()
select d.AWI;
lblWi.Text = wi.ToString();
}
}
My problem is code doesn't retrieve the data, instead when i first click to combobox to choose an ID, all labels show SELECT text which is Primary Key selection ComboBox's default text and afterwards there is no change or data retrieve even though i change the selected index.
How can i fix this issue?
var manuf = (from y in dataContext.Moulds
where y.MID == cBMeasDBMID.SelectedValue.ToString()
select y.manuf).FirstOrDefault();
lblManufac.Text = manuf.ToString();
var size = (from a in dataContext.Moulds
where a.MID == cBMeasDBMID.SelectedValue.ToString()
select a.Size).FirstOrDefault();
lblSize.Text = size.ToString();
var lastmeas = (from c in dataContext.MeasResults
where c.MoldID == cBMeasDBMID.SelectedValue.ToString()
select c.Date).FirstOrDefault();
lblLastMeasDate.Text = lastmeas.ToString();
var wi = (from d in dataContext.Moulds
where d.MID == cBMeasDBMID.SelectedValue.ToString()
select d.AWI).FirstOrDefault();
lblWi.Text = wi.ToString();
Think this will solve your problem
I'm trying to display the amount of sold shoes in a chart.
I have four tables such as tblCategory, tblProduct, tblTransaction and tblTransactionItem.
I have three categories (MenShose, WomanShose, and KiddsShose as you see in the picture).
On the X-axis I want to display the category name and shose size like for example Wemanshose-35 there "WomenShe is categoryName and 35 is the size of the shose."
I tried this but it is giving me the wrong result.
public DisplaySales()
{
InitializeComponent();
chart1.Series.Clear();
var series = chart1.Series.Add("Series1");
series.XValueMember = "ProduktId";
series.YValueMembers = "TolatlSold";
series.Name = "Shose";
chart1.ChartAreas["ChartArea1"].AxisX.Interval = 1;
chart1.Series["Shose"].IsValueShownAsLabel = true;
series.CustomProperties = "LabelStyle=Left";
ShowTodaysSoldProduct();
}
// And here is what I'm trying but it shows me the wrong result. Please Help!
private void ShowTodaysSoldProduct()
{
using (Db db = new Db())
{
DateTime today = DateTime.Today;
DateTime tomorrow = today.AddDays(1);
var result = (from tr in db.TransactionItems
join t in db.Transactions on tr.TransactionId equals t.TransactionId
//join p in db.Products on tr.ProductId equals p.ProductId
join c in db.Categories on tr.CategoryId equals c.CategoryId
where t.TransactionDate >= today && t.TransactionDate < tomorrow
group tr by tr.categories.CategoryName into g
select new ProductSaled
{
ProduktId = g.Key, // Before g.Key I want to display CategoryName too
TolatlSold = g.Count()
}).ToList();
chart1.DataSource = result;
chart1.DataBind();
chart1.Show();
}
}
I'm struggling with what is a rather simple SQL select statement. How can this be translated into LINQ?
select
o.IdOrder, Date, s.suma, name, adresa
from
Clients c
join
Orders o on (c.IdClient = o.IdClient)
join
(select IdOrder, sum(price) suma
from OrderProduct
group by IdOrder) s on (o.IdOrder = s.IdOrder);
If you could point me in the right direction, I would greatly appreciate it.
This is what I have so far:
var y = from w in db.OrderProducts
group w by w.IdOrder into TotaledOrder
select new
{
IdOrder = TotaledOrder.Key,
price = TotaledOrder.Sum(s => s.price)
};
var i = 0;
var cc = new dynamic[100];
foreach (var item in y)
{
cc[i++] = db.Orders.Where(t => t.IdOrder == item.IdOrder)
.Select(p => new
{
IdOrder = item.IdOrder,
price = item.price,
}).Single();
}
Your SQL doesn't really give an idea on your underlying structure. By a guess on column names:
var result = from o in db.Orders
select new {
IDOrder = o.IDOrder,
Date = o.Date,
Suma = o.OrderProduct.Sum( op => op.Price),
Name = o.Client.Name,
Adresa = o.Client.Adresa
};
(I have no idea what you meant by the loop in your code.)
I'm trying to join two DataTables on a dynamic number of columns. I've gotten as far as the code below. The problem is the ON statement of the join. How can I make this dynamic based on how many column names are in the list "joinColumnNames".
I was thinking I will need to build some sort of expression tree, but I can't find any examples of how to do this with multiple join columns and with the DataRow object which doesn't have properties for each column.
private DataTable Join(List<string> joinColumnNames, DataTable pullX, DataTable pullY)
{
DataTable joinedTable = new DataTable();
// Add all the columns from pullX
foreach (string colName in joinColumnNames)
{
joinedTable.Columns.Add(pullX.Columns[colName]);
}
// Add unique columns from PullY
foreach (DataColumn col in pullY.Columns)
{
if (!joinedTable.Columns.Contains((col.ColumnName)))
{
joinedTable.Columns.Add(col);
}
}
var Join = (from PX in pullX.AsEnumerable()
join PY in pullY.AsEnumerable() on
// This must be dynamic and join on every column mentioned in joinColumnNames
new { A = PX[joinColumnNames[0]], B = PX[joinColumnNames[1]] } equals new { A = PY[joinColumnNames[0]], B = PY[joinColumnNames[1]] }
into Outer
from PY in Outer.DefaultIfEmpty<DataRow>(pullY.NewRow())
select new { PX, PY });
foreach (var item in Join)
{
DataRow newRow = joinedTable.NewRow();
foreach (DataColumn col in joinedTable.Columns)
{
var pullXValue = item.PX.Table.Columns.Contains(col.ColumnName) ? item.PX[col.ColumnName] : string.Empty;
var pullYValue = item.PY.Table.Columns.Contains(col.ColumnName) ? item.PY[col.ColumnName] : string.Empty;
newRow[col.ColumnName] = (pullXValue == null || string.IsNullOrEmpty(pullXValue.ToString())) ? pullYValue : pullXValue;
}
joinedTable.Rows.Add(newRow);
}
return joinedTable;
}
Adding a specific example to show input/output using 3 join columns (Country, Company, and DateId):
Pull X:
Country Company DateId Sales
United States Test1 Ltd 20160722 $25
Canada Test3 Ltd 20160723 $30
Italy Test4 Ltd 20160724 $40
India Test2 Ltd 20160725 $35
Pull Y:
Country Company DateId Downloads
United States Test1 Ltd 20160722 500
Mexico Test2 Ltd 20160723 300
Italy Test4 Ltd 20160724 900
Result:
Country Company DateId Sales Downloads
United States Test1 Ltd 20160722 $25 500
Canada Test3 Ltd 20160723 $30
Mexico Test2 Ltd 20160723 300
Italy Test4 Ltd 20160724 $40 900
India Test2 Ltd 20160725 $35
var Join =
from PX in pullX.AsEnumerable()
join PY in pullY.AsEnumerable()
on string.Join("\0", joinColumnNames.Select(c => PX[c]))
equals string.Join("\0", joinColumnNames.Select(c => PY[c]))
into Outer
from PY in Outer.DefaultIfEmpty<DataRow>(pullY.NewRow())
select new { PX, PY };
Another way is to have both DataTable in a DataSet and use DataRelation
How To: Use DataRelation to perform a join on two DataTables in a DataSet?
Since you are using LINQ to Objects, there is no need to use expression trees. You can solve your problem with a custom equality comparer.
Create an equality comparer that can compare equality between two DataRow objects based on the values of specific columns. Here is an example:
public class MyEqualityComparer : IEqualityComparer<DataRow>
{
private readonly string[] columnNames;
public MyEqualityComparer(string[] columnNames)
{
this.columnNames = columnNames;
}
public bool Equals(DataRow x, DataRow y)
{
return columnNames.All(cn => x[cn].Equals(y[cn]));
}
public int GetHashCode(DataRow obj)
{
unchecked
{
int hash = 19;
foreach (var value in columnNames.Select(cn => obj[cn]))
{
hash = hash * 31 + value.GetHashCode();
}
return hash;
}
}
}
Then you can use it to make the join like this:
public class TwoRows
{
public DataRow Row1 { get; set; }
public DataRow Row2 { get; set; }
}
private static List<TwoRows> LeftOuterJoin(
List<string> joinColumnNames,
DataTable leftTable,
DataTable rightTable)
{
return leftTable
.AsEnumerable()
.GroupJoin(
rightTable.AsEnumerable(),
l => l,
r => r,
(l, rlist) => new {LeftValue = l, RightValues = rlist},
new MyEqualityComparer(joinColumnNames.ToArray()))
.SelectMany(
x => x.RightValues.DefaultIfEmpty(rightTable.NewRow()),
(x, y) => new TwoRows {Row1 = x.LeftValue, Row2 = y})
.ToList();
}
Please note that I am using method syntax because I don't think that you can use a custom equality comparer otherwise.
Please note that the method does a left outer join, not a full outer join. Based on the example you provided, you seem to want a full outer join. To do this you need to do two left outer joins (see this answer). Here is how the full method would look like:
private static DataTable FullOuterJoin(
List<string> joinColumnNames,
DataTable pullX,
DataTable pullY)
{
var pullYOtherColumns =
pullY.Columns
.Cast<DataColumn>()
.Where(x => !joinColumnNames.Contains(x.ColumnName))
.ToList();
var allColumns =
pullX.Columns
.Cast<DataColumn>()
.Concat(pullYOtherColumns)
.ToArray();
var allColumnsClone =
allColumns
.Select(x => new DataColumn(x.ColumnName, x.DataType))
.ToArray();
DataTable joinedTable = new DataTable();
joinedTable.Columns.AddRange(allColumnsClone);
var first =
LeftOuterJoin(joinColumnNames, pullX, pullY);
var resultRows = new List<DataRow>();
foreach (var item in first)
{
DataRow newRow = joinedTable.NewRow();
foreach (DataColumn col in joinedTable.Columns)
{
var value = pullX.Columns.Contains(col.ColumnName)
? item.Row1[col.ColumnName]
: item.Row2[col.ColumnName];
newRow[col.ColumnName] = value;
}
resultRows.Add(newRow);
}
var second =
LeftOuterJoin(joinColumnNames, pullY, pullX);
foreach (var item in second)
{
DataRow newRow = joinedTable.NewRow();
foreach (DataColumn col in joinedTable.Columns)
{
var value = pullY.Columns.Contains(col.ColumnName)
? item.Row1[col.ColumnName]
: item.Row2[col.ColumnName];
newRow[col.ColumnName] = value;
}
resultRows.Add(newRow);
}
var uniqueRows =
resultRows
.Distinct(
new MyEqualityComparer(
joinedTable.Columns
.Cast<DataColumn>()
.Select(x => x.ColumnName)
.ToArray()));
foreach (var uniqueRow in uniqueRows)
joinedTable.Rows.Add(uniqueRow);
return joinedTable;
}
Please note also how I clone the columns. You cannot use the same column object in two tables.
void refreshtable()
{
var query = (from x in de.HeaderTrainingAllocations
join y in de.MsTrainings on x.TrainingID equals y.TrainingID
join z in de.MsUsers on x.UserID equals z.UserID
select new
{
x.AllocationID,
x.TrainingID,
z.UserName,
x.TrainingStartDate,
TrainingEndDate = System.Data.Objects.EntityFunctions.AddDays(x.TrainingStartDate, ((y.TrainingDuration - 1) * 7)),
y.TrainingDuration,
x.Capacity
}
);//get all data from tables
dataGridView1.DataSource = query;
for (int i = 0; i < dataGridView1.RowCount; i++)
{
int currentcapacity;
Int32.TryParse(dataGridView1.Rows[i].Cells[6].Value.ToString(),out currentcapacity);
String idA = dataGridView1.Rows[i].Cells[0].Value.ToString(); //read allocation ID on cell 0
var cek = (from x in de.DetailTrainingAllocations
where x.AllocationID==idA
select x).Count(); //to get amount of data in table detailTransaction
dataGridView1.Rows[i].Cells[6].Value =currentcapacity- cek;//this code won't change the value of the rows in datagridview
}
}
This code is working perfectly but the last code didn't work for some reason,the values in row X at column 6 didn't change at all. I have almost no solution for this in my mind.
This is the most direct conversion, although you really should be doing a JOIN on DetailTrainingAllocations, rather than making a loop, doing one query for each record.
void refreshtable()
{
var query = (from x in de.HeaderTrainingAllocations
join y in de.MsTrainings on x.TrainingID equals y.TrainingID
join z in de.MsUsers on x.UserID equals z.UserID
select new
{
x.AllocationID,
x.TrainingID,
z.UserName,
x.TrainingStartDate,
TrainingEndDate = System.Data.Objects.EntityFunctions.AddDays(x.TrainingStartDate, ((y.TrainingDuration - 1) * 7)),
y.TrainingDuration,
x.Capacity
}
).ToList();//get all data from tables
foreach (var z in query)
{
var cek = (from x in de.DetailTrainingAllocations
where x.AllocationID==z.AllocationID
select x).Count(); //to get amount of data in table detailTransaction
z.Capacity-=cek;//this code won't change the value of the rows in datagridview
}
dataGridView1.DataSource = query;
}