GridView and Linq Query sorting - c#

I'm using a Linq Query to populate a GridView.
Then I set it to the Datasource.
In the sorting event, I'd like to retrieve the the anonymous type that the query generates and find the members name.
Is it possible to do so ?
Here's an exemple of the query
var q = from inboundCall in dc.GetTable<InboundCall>()
join employee in dc.GetTable<Employee>() on inboundCall.EmployeeID equals employee.ID
join code in dc.GetTable<Code>() on inboundCall.CodeID equals code.ID
join site in dc.GetTable<Site>() on inboundCall.SiteID equals site.ID
where inboundCall.IsSuccess == true
select new
{
EmployeeNumber = employee.Number,
EmployeeName = employee.Name,
CallerID = inboundCall.CallerID,
SiteName = site.Name,
CallDate = inboundCall.CallDate,
CodeName = code.Name
};
And then
gridData.DataSource = q;
What can I do in the sorting event to retieve the Anonymous type and do something like that
employeeList.Sort((x, y) => ((Int32)x.GetType().GetProperty(e.SortExpression).GetValue(x, null)).CompareTo((Int32)y.GetType().GetProperty(e.SortExpression).GetValue(y, null)) * sortValue);

You could do this with reflection, or you could use the dynamic LINQ library to add the OrderBy clause.
Or, a better option may be to create an actual class / struct that represents the data you will be retrieving.

Related

How do I change SQL Left Join to Lambda expression in C#?

I have three tables and one input value. As a first step, based on the #Input, I need to fetch DSType from DSTypes table. Now again I need to compare DSType of DSTypes with RTInput table's IType column value. If RTInput table has matching records then need to fetch the ID column value alone otherwise NULL should be assigned.
I achieved this logic in SQL but unable to achieve the same in Lambda expression.
I tried some code from google but that is not returning correct value.
DECLARE #ID
#ID = SELECT ID FROM DSMaster Where DSTId = #Input
SELECT RTI.ID FROM DSTypes(NOLOCK) DST
LEFT JOIN RTInput(NOLOCK) RTI
ON RTRIM(LTRIM(DST.DSType)) = RTRIM(LTRIM(RTI.IType))
WHERE DST.ID = #ID
Lambda expression which I tried:
using (BEContext beContext = new BEContext())
{
var mData = beContext.DSMaster.Where(r => r.DSTId = inputvalue);
var Id = beContext.RTInput.Join(beContext.DSTypes.Where(dst => dst.ID == mData.Id )).Select(z => z.ID).FirstOrDefault();
}
I think this may help.
using {BEContext beContext = new BEContext()){
var mData = (from p in beContext.DSMaster.Where(r=>r.DSTId == inputvalue)
join pr in beContext.RTInput on p.Id equals dst.ID
select new {
//select what you want
}).FirstOrDefault();

C# LINQ list select columns dynamically from a joined dataset

I'm using LINQ to join 2 datatables:
var JoinResult = (from p in WZdt.AsEnumerable()
join t in WZIdt.AsEnumerable()
on p.Field<string>("ID") equals t.Field<string>("ID")
select new
{
p,
t
}).ToList();
WZdt and WZIdt are DataTables. Normally, when wanted to specify columns I would write something like this:
var JoinResult = (from p in WZdt.AsEnumerable()
join t in WZIdt.AsEnumerable()
on p.Field<string>("ID") equals t.Field<string>("ID")
select new
{
FileNo = p.Field<string>("FileNo"),
Title = p.Field<string>("Title"),
M1 = t.Field<int?>("M1"),
RecCount = t.Field<int?>("RecCount")
}).ToList();
But those source datatables are created dynamically based on some logic, so they can differ when it comes to Columns they have. I would like to apply similiar logic to the select part of LINQ, but I don't know how. Can I construct array of columns somehow, like [p.FileNo, p.Title, t.M1, t.RecCount] ?
Or any other way?

unable to create a constant value of type anonymous type only primitive types

Using Entity Framework Version=6.0.0.0 to get to get common id and orderid as shown below.
var dt1 = from p in dt.AsEnumerable()
select new
{
Id = p.Field<int>("Id"),
OrderId = p.Field<int>("OrderId")
};
var dt2 = (from order in db.Orders
select new
{
order.Id,
order.OrderId
}).ToList();
var intersect = dt1.Intersect(dt2);
Based on the list of values in intersect. I need to select all the values from Orders Table.
Trying to used code getting error "unable to create a constant value of type anonymous type only primitive types"
var result= (from a in sync.Orders
where intersect.Any(b => a.Id == b.Id && a.OrderId == b.OrderId)
select a).ToList();
You are trying to "join" an EF query with an in-memory data set, which does not work because there's not a way to embed the list and the lookup in SQL. One option is to pull the entire table into memory with AsEnumerable:
var result= (from a in sync.Orders.AsEnumberable
where intersect.Any(b => a.Id == b.Id && a.OrderId == b.OrderId)
select a).ToList();
Another option is to concatenate the Id and OrderId into one value and use Contains since that can be translated to an IN clause in SQL:
var lookup = intersect.Select(i => i.Id + "-" + i.OrderId).ToList();
var result= (from a in sync.Orders
where lookup.Contains(a.Id + "-" + a.OrderId)
select a).ToList();

C# linq query data table take method

I'm not able to call take method from below linq query
var data = from tb in table.AsEnumerable()
join ch in channelTable.AsEnumerable() on syskey equals (DateTime)ch["syskey"]
orderby Convert.ToDouble(tb[(string.Format("Channel{0}_data",Convert.ToInt32(ch["Channel_No"])))]) descending
select new
{
Channel_No = ch["Channel_No"],
Channel_data = tb[string.Format("Channel{0}_data", Convert.ToInt32(ch["Channel_No"]))],
};
How can I add Take(5) from above linq query?
As simply as:
var top5 = data.Take(5);
You can do it in the same statement, too, but it's a bit ugly:
var data = (from tb in table.AsEnumerable()
join ch in channelTable.AsEnumerable() on syskey equals (DateTime)ch["syskey"]
orderby Convert.ToDouble(tb[(string.Format("Channel{0}_data",Convert.ToInt32(ch["Channel_No"])))]) descending
select new
{
Channel_No = ch["Channel_No"],
Channel_data = tb[string.Format("Channel{0}_data", Convert.ToInt32(ch["Channel_No"]))],
}).Take(5);
Note that ordering by a string here probably doesn't do what you want, unless your values are all single digit - would you really want channel3, channel2, channel10, channel1?
It's a pretty odd query though - especially as your join doesn't use anything from the first table...

How to sort an IEnumerable<AnonymousType> or sort a two datatable join using LINQ?

I am joining two datatables and selecting using LINQ. I am getting an error in the 'orderby' line. "The name 'contact' does not exist in the current context". If I order by columns from the 'customer' variable it works, but not using columns from the 'contact' variable.
Then I removed the orderby line and tried to order it using lambda expression like:
orders.OrderBy(o => (string) o["ContactName"];
and I got an error "Cannot apply indexing with [] to an expression of type 'AnonymousType#1'. I don't want to create a new class just for sorting.
Any ideas how to do this kind of sorting. I will be doing a sort using multiple columns from both tables.
CODE:
var orders = (from customer in Customers.AsEnumerable()
join contact in Contacts.AsEnumerable()
on (int) customer["CustomerID"] equals (int) contact["CustomerID"] into outer
from contact in outer.DefaultIfEmpty()
orderby contact["ContactName"]
select new
{
ContactID = (int) contact["ContactID"]),
Name = (string) contact["ContactName"]),
City = (string) contact["City"])
});
There are some syntax problems(too many paranthesis, f.e. contact["ContactID"])), this should work:
var orders = from customer in Customers.AsEnumerable()
join contact in Contacts.AsEnumerable()
on customer.Field<int>("CustomerID") equals contact.Field<int>("CustomerID") into outer
from contact in outer.DefaultIfEmpty()
orderby contact["ContactName"]
select new
{
ContactID = contact.Field<int>("ContactID"),
Name = contact.Field<String>("ContactName"),
City = contact.Field<String>("City")
};
Sidenote: i would use the strong type Field extension method.

Categories