I am stuck on this problem. I want to get users who are in the "Developer" role, who either are not assigned any tasks or are assigned 3 or fewer tasks which are marked "Active" or "Testing".
I don't know how to make a statement where I get all tasks with Status "Active, Testing" and sum them up for my count statement.
//here i specific role for users
var role = unitOfWork.RoleRepository._context.Roles.SingleOrDefault(m => m.Name == "Developer");
var query = (from u in users
where u.Roles.Any(r => r.RoleId == role.Id)
from t in u.ProjectTasks.Where(x => x.Users.Any(user => user.Id == u.Id)).DefaultIfEmpty()
//here I am able to get those users without assigned tasks but I dont know how to make the second condition with 3 or less tasks
where ((u.ProjectTasks.Count() == 0) || u.ProjectTasks.Any(z => z.Status == Status.Active || z.Status == Status.Testing))
select new { User = u } into Users
group Users by Users.User).ToList();
Here is my database model:
Perhaps the LINQ Count function is called for:
var query = (from u in users
where u.Roles.Any(r => r.RoleId == role.Id)
from t in u.ProjectTasks.Where(x => x.Users.Any(user => user.Id == u.Id)).DefaultIfEmpty()
where ((u.ProjectTasks.Count() == 0) || u.ProjectTasks.Count(z => z.Status == Status.Active || z.Status == Status.Testing) <= 3)
select new { User = u } into Users
group Usersby Users.User).ToList();
For examples of usages: http://www.csharp-examples.net/linq-count/
I simulated the database with DataTable to show how it is done
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DataTable AspNetRoles = new DataTable();
AspNetRoles.Columns.Add("Id", typeof(int));
AspNetRoles.Columns.Add("Name", typeof(string));
AspNetRoles.Rows.Add(new object[] { 123, "Developer" });
AspNetRoles.Rows.Add(new object[] { 456, "Non Developer" });
DataTable AspNetUserRoles = new DataTable();
AspNetUserRoles.Columns.Add("UserId", typeof(int));
AspNetUserRoles.Columns.Add("RoleId", typeof(int));
AspNetUserRoles.Rows.Add(new object[] { 100, 123 });
AspNetUserRoles.Rows.Add(new object[] { 200, 456 });
AspNetUserRoles.Rows.Add(new object[] { 300, 123 });
AspNetUserRoles.Rows.Add(new object[] { 400, 456 });
DataTable AspNetUsers = new DataTable();
AspNetUsers.Columns.Add("Id", typeof(int));
AspNetUsers.Rows.Add(new object[] { 100 });
AspNetUsers.Rows.Add(new object[] { 200 });
AspNetUsers.Rows.Add(new object[] { 300 });
AspNetUsers.Rows.Add(new object[] { 400 });
DataTable UserToTask = new DataTable();
UserToTask.Columns.Add("UserId", typeof(int));
UserToTask.Columns.Add("TaskId", typeof(int));
UserToTask.Rows.Add(new object[] { 100, 1000 });
UserToTask.Rows.Add(new object[] { 100, 1001 });
UserToTask.Rows.Add(new object[] { 100, 1002 });
UserToTask.Rows.Add(new object[] { 200, 1001 });
UserToTask.Rows.Add(new object[] { 200, 1004 });
UserToTask.Rows.Add(new object[] { 200, 1006 });
UserToTask.Rows.Add(new object[] { 300, 1005 });
UserToTask.Rows.Add(new object[] { 300, 1006 });
UserToTask.Rows.Add(new object[] { 400, 1007 });
UserToTask.Rows.Add(new object[] { 400, 1008 });
DataTable ProjectTasks = new DataTable();
ProjectTasks.Columns.Add("Id", typeof(int));
ProjectTasks.Columns.Add("Status", typeof(string));
ProjectTasks.Rows.Add(new object[] { 1000, "Active" });
ProjectTasks.Rows.Add(new object[] { 1001, "Testing" });
ProjectTasks.Rows.Add(new object[] { 1002, "Idle" });
ProjectTasks.Rows.Add(new object[] { 1003, "Active" });
ProjectTasks.Rows.Add(new object[] { 1004, "Testing" });
ProjectTasks.Rows.Add(new object[] { 1005, "Idle" });
ProjectTasks.Rows.Add(new object[] { 1006, "Active" });
ProjectTasks.Rows.Add(new object[] { 1007, "Testing" });
ProjectTasks.Rows.Add(new object[] { 1008, "Idle" });
var results = (from aspNetUser in AspNetUsers.AsEnumerable()
join task in UserToTask.AsEnumerable() on aspNetUser.Field<int>("Id") equals task.Field<int>("UserId")
join proj in ProjectTasks.AsEnumerable() on task.Field<int>("TaskId") equals proj.Field<int>("Id")
join aspNetUserRole in AspNetUserRoles.AsEnumerable() on aspNetUser.Field<int>("Id") equals aspNetUserRole.Field<int>("UserId")
join aspNetRole in AspNetRoles.AsEnumerable() on aspNetUserRole.Field<int>("RoleId") equals aspNetRole.Field<int>("Id")
select new { aspNetUser = aspNetUser, task = task, proj = proj, aspNetUserRole = aspNetUserRole, aspNetRole = aspNetRole }).ToList();
var finalResults = results.GroupBy(x => x.aspNetUser.Field<int>("Id"))
.Where(x => (x.Select(y => y.task).Count() == 0) || (x.Where(y => (y.proj.Field<string>("Status") == "Active") || (y.proj.Field<string>("Status") == "Testing"))).Count() <= 3).ToList();
}
}
}
Related
I have got this situation with a datatable like this
C1 C2 C3
A AA 4
BB 6
B CC 3
DD 3
EE 4
C FF 5
GG 5
and my output should be like this
C1 C2 C3
A AA,BB 10
B CC,DD,EE 10
C FF,GG 10
How can i group by the column with the space till the next value comes up
What i did was i took all the row itemarray and then using some string manipulation and regex got the row value as for the first two values like this and assigned to a variable in a query using Let
A,AA,BB,10|B,CC,DD,EE,10 but then i cannot add it using the
**DT.clone.rows.Add(x.split("|"c))* method as there its not incrementing and adding the whole joined string
Any other input where i can manipulate and add it (P.S i know linq is querying language)
Thank you for your time
You can use .GroupBy to get result needed
Here is your class:
public class Data
{
public string C1 { get; set; }
public string C2 { get; set; }
public int C3 { get; set; }
}
Imagine that you have list of Data objects, so your GroupBy expression will be following:
var result = list.GroupBy(g => g.C1, (a, b) => new {C1 = a, C2 = b.ToList()})
.Select(g => new
{
g.C1,
C2 = string.Join(",", g.C2.Select(m => m.C2)),
C3 = g.C2.Sum(m => m.C3)
})
.ToList();
A simple .GroupBy can give you expected result, Edited to handle Null or WhiteSpace Columns
var res = ListModel.Where(e => !string.IsNullOrWhiteSpace(e.C1)
&& !string.IsNullOrWhiteSpace(e.C2))
.GroupBy(e => e.C1).Select(e => new
{
e.Key,
c2 = string.Join(",", e.Select(x => x.C2).ToList()),
c3 = e.Sum(x => x.C3)
}).ToList();
Hello All first of all Thank you for your time and effort i Did this use case using this code
This gave me all row item array in string and than in the end with a little Split method i was able to add it to my datatable
String.Join("|",(System.Text.RegularExpressions.Regex.Replace(String.Join("|",(From roww In DT.AsEnumerable() Select String.Join(",",roww.ItemArray) ).ToList),"\|,",",")).Split("|"c).
Select(Function(q)CStr(q)+","+CStr(String.join("|",System.Text.RegularExpressions.Regex.Matches(CStr(q),"\d+").Cast(Of match)).Split("|"c).Sum(Function(r) CInt(r) ))).tolist),",\d+,",",")```
Try following code which is tested
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DataTable dt1 = new DataTable();
dt1.Columns.Add("C1", typeof(string));
dt1.Columns.Add("C2", typeof(string));
dt1.Columns.Add("C3", typeof(int));
dt1.Rows.Add(new object[] { "A", "AA", 4});
dt1.Rows.Add(new object[] { null, "BB", 6});
dt1.Rows.Add(new object[] { "B", "CC", 3});
dt1.Rows.Add(new object[] { null, "DD", 3});
dt1.Rows.Add(new object[] { null, "EE", 4});
dt1.Rows.Add(new object[] { "C", "FF", 5});
dt1.Rows.Add(new object[] { null, "GG", 5});
//replace nulls in column 1 with actual values
string previous = "";
foreach(DataRow row in dt1.AsEnumerable())
{
if (row.Field<string>("C1") == null)
{
row["C1"] = previous;
}
else
{
previous = row.Field<string>("C1");
}
}
DataTable dt2 = dt1.Clone();
var groups = dt1.AsEnumerable().GroupBy(x => x.Field<string>("C1")).ToList();
foreach (var group in groups)
{
dt2.Rows.Add(new object[] {
group.Key,
string.Join(",", group.Select(x => x.Field<string>("C2"))),
group.Select(x => x.Field<int>("C3")).Sum()
});
}
}
}
}
Yet another way using Skip, TakeWhile, and GroupBy extensions:
DataTable dt1 = new DataTable();
dt1.Columns.Add("C1", typeof(string));
dt1.Columns.Add("C2", typeof(string));
dt1.Columns.Add("C3", typeof(int));
//The output table.
DataTable dt2 = dt1.Clone();
dt1.Rows.Add(new object[] { "A", "AA", 3 });
dt1.Rows.Add(new object[] { null, "BB", 6 });
dt1.Rows.Add(new object[] { "B", "CC", 3 });
dt1.Rows.Add(new object[] { null, "DD", 3 });
dt1.Rows.Add(new object[] { null, "EE", 4 });
dt1.Rows.Add(new object[] { "C", "FF", 5 });
dt1.Rows.Add(new object[] { null, "GG", 6 });
var rows = dt1.Rows.Cast<DataRow>().AsEnumerable();
foreach (var row in rows.Where(r => r.Field<string>("C1") != null))
{
var indx = dt1.Rows.IndexOf(row) + 1;
var q = rows
.Skip(indx)
.TakeWhile(t => t.Field<string>("C1") == null)
.GroupBy(g => g.Field<string>("C1"))
.Select(g => new
{
C1 = row.Field<string>("C1"),
C2 = $"{row.Field<string>("C2")}, {string.Join(", ", g.Select(s => s.Field<string>("C2")))}",
C3 = row.Field<int>("C3") + g.Sum(s => s.Field<int>("C3")),
}).FirstOrDefault();
if (q != null)
dt2.Rows.Add(q.C1, q.C2, q.C3);
}
dataGridView1.DataSource = null;
dataGridView1.DataSource = dt2;
The idea behind this snippet is to:
Get the complete rows and iterate through them.
For each complete row, we get it's index from the original DataTable and add 1 to make a starting search point for the incomplete rows. The Skip extension is the method to achieve that.
The TakeWhile extension function gets the incomplete rows and stops at the next complete row.
The GroupBy extension function groups the incomplete rows to concatenate their C2 values and sum their C3 values, add the results to the values of the complete row and create a temporary anonymous object to hold these values.
Extract the anonymous object and add a new DataRow to the output DataTable.
And finally, bind the output DataTable to a DGV.
Happy 2020 for all.
Firstly, this is for a legacy application, so I cannot radically change any logic.
I have database with two tables that do not have any relationships. I asked if I change this, but was told I cannot.
These tables can be described as
Create Table T1
[doc_id] [int] NOT NULL, -- Primary Key
[customer_acc_no] [varchar](16) NULL,
[gcompany] [varchar](30) NULL,
....
extra fields
and table
Create Table T2
[UserURN] [int] NOT NULL, -- All three fields make up
[AccountNumber] [varchar](20) NOT NULL, -- the primary key
[Company] [varchar](50) NOT NULL,
....
extra fields
As you can see, not only are the field names different, but they have different lengths too.
I am using the Repository and UnitOfWork patterns. So far I have managed to code the following:
private IRepository<T1> _t1Repository;
private IRepository<T2> _t2Repository;
These are populated within the constructor.
Next I use the following code to configure get a queryable repository.
var retVal = _t1Repository.Queryable();
From this, I am trying to add the following join.
from q in T1
join w in T2
on new { X1 = q.gcompany, X2 = q.Customer_acc_no }
equals new { X1 = w.Company, X2 = w.AccountNumber }
I am thinking it would be along the lines of:
var query = T1.GroupJoin(T2,
c => c.gcompany,
o => o.Company,
(c, result) => new Result(c.doc_id, result))
.GroupJoin(T2,
c => c.Customer_acc_no,
o => o.AccountNumber ,
(c, result) => new Result(c.doc_id, result));
but i'm not sure as all attempts so far end in errors within visual studio.
See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication42
{
class Program
{
static void Main(string[] args)
{
DataTable dt1 = new DataTable();
dt1.Columns.Add("doc_id", typeof(int));
dt1.Columns.Add("customer_acc_no", typeof(string));
dt1.Columns.Add("gcompany", typeof(string));
dt1.Rows.Add(new object[] { 1, "100", "abc" });
dt1.Rows.Add(new object[] { 2, "100", "def" });
dt1.Rows.Add(new object[] { 3, "100", "def" });
dt1.Rows.Add(new object[] { 4, "101", "abc" });
dt1.Rows.Add(new object[] { 5, "101", "ghi" });
dt1.Rows.Add(new object[] { 6, "102", "jkl" });
dt1.Rows.Add(new object[] { 7, "102", "abc" });
dt1.Rows.Add(new object[] { 8, "102", "def" });
dt1.Rows.Add(new object[] { 9, "103", "abc" });
dt1.Rows.Add(new object[] { 10, "103", "abc" });
DataTable dt2 = new DataTable();
dt2.Columns.Add("UserURN", typeof(int));
dt2.Columns.Add("AccountNumber", typeof(string));
dt2.Columns.Add("Company", typeof(string));
dt2.Rows.Add(new object[] { 11, "100", "abc" });
dt2.Rows.Add(new object[] { 12, "100", "def" });
dt2.Rows.Add(new object[] { 13, "100", "def" });
dt2.Rows.Add(new object[] { 14, "101", "abc" });
dt2.Rows.Add(new object[] { 15, "101", "ghi" });
dt2.Rows.Add(new object[] { 16, "102", "jkl" });
dt2.Rows.Add(new object[] { 17, "102", "abc" });
dt2.Rows.Add(new object[] { 18, "102", "def" });
dt2.Rows.Add(new object[] { 19, "103", "abc" });
dt2.Rows.Add(new object[] { 20, "103", "abc" });
var results = from r1 in dt1.AsEnumerable()
join r2 in dt2.AsEnumerable() on
new { x1 = r1.Field<string>("customer_acc_no"), x2 = r1.Field<string>("gcompany") } equals
new { x1 = r2.Field<string>("AccountNumber"), x2 = r2.Field<string>("Company") }
select new { t1 = r1, t2 = r2 };
}
}
}
I have two tables:
Retailers
Invoices
Retailers has two columns:
1.1. RetailerID
1.2. RetailerName
Invoices has three columns:
2.1. InvoiceID
2.2. InvoiceProfit
2.3. RetailerID
Retailers.RetailerID is linked to Invoices.RetailerID (one-to-many).
What I want to do is write a linq (or in the form of a lambda exp) that returns Retailer.RetailerID, Retailer.RetailerName, Invoice.InvoiceProfit.
I can do this like so:
var retailers = from r in db.Retailers select t;
var invoices = from i in db.Invoices select i;
var retailersAndInvoices = from r in retailers join i in invoices on r.RetailerID equals i.RetailerID select new {t.RetailerName, i.InvoiceProfit};
I want to return only Distinct RetailerNames and the Sum of all Invoices.InvoiceProfit next to each one - the purpose being "Top Ten Retailers"!
How can i do this?
Use GroupBy to convert a flat list to groups by RetailerName
Use Sum(i => i.InvoiceProfit) to compute totals
Use new { ... } to pair up retailers with their profit totals
Use OrderByDescending(p => p.TotalProfit) to get high-profit retailers to the top
Use Take(10) to limit the list to ten items.
Overall query would look like this:
var topTen = retailersAndInvoices
.GroupBy(ri => ri.RetailerName)
.Select(g => new {
Retailer = g.Key
, TotalProfit = g => g.Sum(i => i.InvoiceProfit)
})
.OrderByDescending(p => p.TotalProfit)
.Take(10)
.ToList();
I use combination of lambda and linq. See msdn : https://code.msdn.microsoft.com/LINQ-Join-Operators-dabef4e9
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication28
{
class Program
{
static void Main(string[] args)
{
DataTable retailers = new DataTable();
retailers.Columns.Add("RetailerID", typeof(int));
retailers.Columns.Add("RetailerName", typeof(string));
retailers.Rows.Add(new object[] { 123, "abc" });
retailers.Rows.Add(new object[] { 124, "abd" });
retailers.Rows.Add(new object[] { 125, "abe" });
DataTable invoices = new DataTable();
invoices.Columns.Add("InvoiceID", typeof(int));
invoices.Columns.Add("InvoiceProfit", typeof(decimal));
invoices.Columns.Add("RetailerID", typeof(int));
invoices.Rows.Add(new object[] { 100, 200, 123 });
invoices.Rows.Add(new object[] { 101, 201, 123 });
invoices.Rows.Add(new object[] { 102, 202, 123 });
invoices.Rows.Add(new object[] { 103, 203, 123 });
invoices.Rows.Add(new object[] { 104, 204, 124 });
invoices.Rows.Add(new object[] { 105, 205, 124 });
invoices.Rows.Add(new object[] { 106, 206, 124 });
invoices.Rows.Add(new object[] { 107, 207, 125 });
invoices.Rows.Add(new object[] { 108, 208, 125 });
invoices.Rows.Add(new object[] { 109, 209, 125 });
var retailersAndInvoices = (from r in retailers.AsEnumerable()
join i in invoices.AsEnumerable() on r.Field<int>("RetailerID") equals i.Field<int>("RetailerID")
select new { name = r.Field<string>("RetailerName"), profit = i.Field<decimal>("InvoiceProfit") })
.GroupBy(x => x.name)
.Select(x => new { name = x.Key, totalProfit = x.Select(y => y.profit).Sum() }).ToList();
}
}
}
I am pulling some historical data from Firebird database as below:
Product_ID Date Price
1 2001-01-01 10
1 2001-02-01 10
1 2001-03-01 15
1 2001-04-01 10
1 2001-05-01 20
1 2001-06-01 20
What I am trying to do is to extract the first for occurrence every price change.
Example of expected data set:
Product_ID Date Price
1 2001-01-01 10
1 2001-03-01 15
1 2001-04-01 10
1 2001-05-01 20
I know that on MSSQL I could leverage LAG for that. Is it possible to do that with Firebird?
You can try this, but be aware I didn't tested it:
CREATE PROCEDURE SP_Test
RETURNS (
Product_ID INTEGER,
Date DATE,
Price INTEGER
)
AS
DECLARE VARIABLE Last_Product_ID INTEGER;
DECLARE VARIABLE Last_Date DATE;
DECLARE VARIABLE Last_Price INTEGER;
BEGIN
FOR SELECT Product_ID, Date, Price
FROM xxxx
ORDER BY Product_ID, Date
INTO Product_ID, Date, Price
DO BEGIN
IF ((:Last_Product_ID IS NULL) OR
(:Last_Date IS NULL) OR
(:Last_Price IS NULL) OR
(:Product_ID <> :Last_Product_ID) OR
(:Price <> :Last_Price)) THEN
SUSPEND;
Last_Product_ID = :Product_ID;
Last_Date = :Date;
Last_Price = :Price;
END;
END;
in MoreLinq there is a Lag extension method but it is supported only in Linq to Objects...
What you can do, if you are looking for a C# linq answer for that you can:
Basically order your data the correct way and then add a row index for while price (and product_id) is still the same. Then group by it and select the min date.
int groupingIndex = 0;
int previousPrice = 0;
var response = data
.OrderBy(item => item.Product_ID)
.ThenBy(item => item.Date)
.Select(item =>
{
if (item.Price != previousPrice)
{
previousPrice = item.Price;
groupingIndex++;
}
return new { Index = groupingIndex, Item = item };
})
.GroupBy(item => new { item.Index, item.Item.Product_ID, item.Item.Price } )
.Select(group => new Record
{
Product_ID = group.Key.Product_ID,
Price = group.Key.Price,
Date = group.Min(item => item.Item.Date)
}).ToList();
And if you don't mind doing the operation in the C# and not the DB (and using a beta version of the MoreLinq) then:
int index = 0;
var result2 = data
.OrderBy(item => item.Product_ID)
.ThenBy(item => item.Date)
.Lag(1, (current, previous) => new { Index = (current.Price == previous?.Price ? index : ++index), Item = current })
.GroupBy(item => new { item.Index, item.Item.Product_ID, item.Item.Price })
.Select(group => new Record { Product_ID = group.Key.Product_ID, Price = group.Key.Price, Date = group.Min(item => item.Item.Date) })
.ToList();
This is a little complicated but it works
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("Product_ID", typeof(int));
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("Price", typeof(int));
dt.Rows.Add(new object[] {1, DateTime.Parse("2001-01-01"), 10});
dt.Rows.Add(new object[] {1, DateTime.Parse("2001-02-01"), 10});
dt.Rows.Add(new object[] {1, DateTime.Parse("2001-03-01"), 15});
dt.Rows.Add(new object[] {1, DateTime.Parse("2001-04-01"), 10});
dt.Rows.Add(new object[] {1, DateTime.Parse("2001-05-01"), 20});
dt.Rows.Add(new object[] {1, DateTime.Parse("2001-06-01"), 20});
dt.Rows.Add(new object[] { 2, DateTime.Parse("2001-01-01"), 10 });
dt.Rows.Add(new object[] { 2, DateTime.Parse("2001-02-01"), 10 });
dt.Rows.Add(new object[] { 2, DateTime.Parse("2001-03-01"), 15 });
dt.Rows.Add(new object[] { 2, DateTime.Parse("2001-04-01"), 10 });
dt.Rows.Add(new object[] { 2, DateTime.Parse("2001-05-01"), 20 });
dt.Rows.Add(new object[] { 2, DateTime.Parse("2001-06-01"), 20 });
dt = dt.AsEnumerable().OrderBy(x => x.Field<DateTime>("Date")).CopyToDataTable();
List<DataRow> results = dt.AsEnumerable()
.GroupBy(g => g.Field<int>("Product_ID"))
.Select(g1 => g1.Select((x, i) => new { row = x, dup = (i == 0) || ((i > 0) && (g1.Skip(i - 1).FirstOrDefault().Field<int>("Price") != g1.Skip(i).FirstOrDefault().Field<int>("Price"))) ? false : true })
.Where(y => y.dup == false).Select(z => z.row)).SelectMany(m => m).ToList();
}
}
}
My Table1 has some Header and Values:
KundeID KundeName Produkt Comment
1 Michael Jogurt "nichts"
2 Raj "Ich bin cool"
3 Gary Fanta "yahoo"
4 Miky Sprite
I want to change to Table2, make Values from Produkt as Header Columns:
KundeID KundeName Comment Jogurt Fanta Sprite
1 Michael "nichts" x
2 Raj "Ich bin cool"
3 Gary "yahoo" x
4 Miky x
My code for Table1:
DataTable table = new DataTable("Kunde");
table.Columns.Add("KundeID", typeof(Int32));
table.Columns.Add("KundeName", typeof(String));
table.Columns.Add("Produkt", typeof(String));
DataTable comment = new DataTable("Comment");
comment.Columns.Add("KundeName", typeof(String));
comment.Columns.Add("Comment", typeof(String));
DataSet ds = new DataSet("DataSet");
ds.Tables.Add(table);
ds.Tables.Add(comment);
object[] o1 = { 1, "Michael", "Jogurt" };
object[] o2 = { 2, "Raj" };
object[] o3 = { 3, "Gary", "Fanta" };
object[] o4 = { 4, "Miky", "Sprite" };
object[] c1 = { "Raj", "Ich bin cool" };
object[] c2 = { "Gary", "yahoo" };
object[] c3 = { "Michael", "nichts" };
table.Rows.Add(o1);
table.Rows.Add(o2);
table.Rows.Add(o3);
table.Rows.Add(o4);
comment.Rows.Add(c1);
comment.Rows.Add(c2);
comment.Rows.Add(c3);
var results = from table1 in table.AsEnumerable()
join table2 in comment.AsEnumerable()
on table1.Field<string>("KundeName") equals table2.Field<string>("KundeName") into prodGroup
from table4 in prodGroup.DefaultIfEmpty()
select new
{
KundeID = table1.Field<Int32?>("KundeID"),
KundeName = table1.Field<String>("KundeName"),
Produkt = table1.Field<String>("Produkt"),
Comment = table4 != null ? table4.Field<String>("Comment") : null,
};
dataGridView1.DataSource = results.ToList();
How can I take Value from "Produkt" and make it Header? thank you guys for helping
This should do the trick regardless of how many different products come up. It's pretty short and concise.
// build the new data table
var result = new DataTable();
result.Columns.Add("KundeID", typeof(Int32));
result.Columns.Add("KundeName", typeof(String));
result.Columns.Add("Comment", typeof(String));
result.Columns.AddRange(
(from c in
(from r in table.AsEnumerable()
where !r.IsNull("Produkt") && !string.IsNullOrEmpty(r.Field<string>("Produkt"))
select r.Field<string>("Produkt")).Distinct() // added DISTINCT
select new DataColumn(c, typeof(bool))).ToArray()
);
foreach (var r in results)
{
var productIndex = result.Columns.IndexOf(r.Produkt);
var vals = new List<object>() { r.KundeID, r.KundeName, r.Comment };
for (int i = 3; i < result.Columns.Count; i++)
{
if (i == productIndex)
{
vals.Add(true);
}
else
{
vals.Add(false);
}
}
result.LoadDataRow(vals.ToArray(), true);
}
var products = table.AsEnumerable()
.GroupBy(c => c["Produkt"])
.Where(g => !(g.Key is DBNull))
.Select(g => (string)g.Key)
.ToList();
var newtable = table.Copy();
products.ForEach(p=>newtable.Columns.Add(p,typeof(bool)));
foreach (var row in newtable.AsEnumerable())
{
if (!(row["Produkt"] is DBNull)) row[(string)row["Produkt"]] = true;
}
newtable.Columns.Remove("Produkt");
Try following...this may help you....
DataTable table = new DataTable("Kunde");
table.Columns.Add("KundeID", typeof(Int32));
table.Columns.Add("KundeName", typeof(String));
table.Columns.Add("Produkt", typeof(String));
table.Columns.Add("Comment", typeof(String));
object[] o1 = { 1, "Michael", "Jogurt", "nichts" };
object[] o2 = { 2, "Raj","","Ich bin cool" };
object[] o3 = { 3, "Gary", "Fanta","yahoo" };
object[] o4 = { 4, "Miky", "Sprite","" };
table.Rows.Add(o1);
table.Rows.Add(o2);
table.Rows.Add(o3);
table.Rows.Add(o4);
Dictionary<int,string> dictObj=new Dictionary<int, string>();
for (int i = 0; i < table.Rows.Count; i++)
{
dictObj.Add(Convert.ToInt32(table.Rows[i][0].ToString()), table.Rows[i][2].ToString());
}
foreach (var obj in dictObj)
{
if (string.IsNullOrEmpty(obj.Value))
{
table.Columns.Add(obj.Value, typeof(String));
DataRow row = table.Rows[obj.Key];
row[obj.Value] = "X";
}
}