C# linq query data table take method - c#

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...

Related

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?

Concatenating a LINQ (To SQL) Query

I am building a LINQ query, which will have comparisons attached to the 'where' section (the number of these comparisons depends on the user's selections).
In the code-behind, I want something like this:
var builtQuery =
from q in dc.Leads
join sr in dc.SalesReps on q.SalesRepID equals sr.SalesRepID
join co in dc.Companies on q.CompanyID equals co.CompanyID
join or in dc.Origins on q.OriginID equals or.OriginID
join pr in dc.Products on q.ProductID equals pr.ProductID
where
Here, in between the 'from' and 'select' parts, I will add a number of comparisons (depending on the user's selection of checkboxes).
And Finally:
select new { q.Ref, sr.Rep, q.Deposit, q.Sale, q.Title, q.Names, q.Surname, q.HomePhone, q.WorkPhone, q.Mobile, q.Address, q.Suburb, q.County, q.Postcode, co.CompanyName, or.OriginName, pr.ProductName, q.Telemarket, q.Entered };
In PHP (using MySQL) I could simply concatenate a number of strings, which make up the query. But, in c#/LINQ To SQL, the query is not a string and so I have no idea how to do this...There were a couple similar questions on SO, but they're not quite the same thing.
Any ideas??
Thanks!
I would do it in the following way
var intermediateQuery=
from q in dc.Leads
join sr in dc.SalesReps on q.SalesRepID equals sr.SalesRepID
join co in dc.Companies on q.CompanyID equals co.CompanyID
join or in dc.Origins on q.OriginID equals or.OriginID
join pr in dc.Products on q.ProductID equals pr.ProductID
select new { q.Ref, sr.Rep, q.Deposit, q.Sale, q.Title, q.Names, q.Surname, q.HomePhone, q.WorkPhone, q.Mobile, q.Address, q.Suburb, q.County, q.Postcode, co.CompanyName, or.OriginName, pr.ProductName, q.Telemarket, q.Entered };
and then add some filters considering user input
if(SomeUserProductFilter)
{
var result = intermediateQuery.Where(p=>p.ProductName = 'UserProductName');
}
Do not be afraid that this approach will retrieve all data and than filters it in memory. LINQ sends query to database only when you call ToList(), ToArray() or use result in foreach loop

Use Array in Linq query

My question got down voted and put on hold because it is not specific enough. Ill try to specify
Before linq I would do this query
sql="SELECT products.* FROM products INNER JOIN productaccess ON products.id=productaccess.productid"
Now with the entity framework and link I can do this
var products = (from lProducts in db.Products
join lProductAccess in db.ProductAccess on lProducts.ID equals lProductAccess.ProductID
select lProducts).ToList();
But what if I want the flexibilty to get all products or only get the accessible objects
In sql I can do this
sql="SELECT products.* FROM products "
if (useProductAccess) {
sql+=" INNER JOIN productaccess ON products.id=productaccess.productid"
}
In Linq I have to make a separate linq statement.
if (useProductAccess) {
var productsFiltered = (from lProducts in db.Products
join lProductAccess in db.ProductAccess on lProducts.ID equals lProductAccess.ProductID
select lProducts).ToList();
} else {
var productsAll = (from lProducts in db.Products select lProducts).ToList();
}
Now, I could just get all the lProducts and then filter it in an additional linq statement with lProductAccess but then I am using an unnecessary large amount of data.
Is it an option to use:
var productsAccecible = (from lProductAccess in db.ProductAccess where lProductAccess.CustID==custID select lProductAccess).toArray();
var products = (from lProducts in db.Products
where (useProductAccess ?
productsAccessible.Contains(lProducts.ID)
: true)
select lProducts).ToList();
Linq provider will not know how to transform the ternary operator (? and :) in a valid sql, you could try this:
var query = db.Products;
if (useProductAccess)
query = query.Where(p => productsAccessible.Contains(p.ID));
var result = query.ToList();
I used the express profiler to see how the linq statement is translated into sql. It shows that the
productsAccessible.Contains(lProducts.ID)
part gets translated as
products.id in (comma seperated list of values)
My conclusion is it will work fine.
Are there possible drawbacks
Sure - it may produce an inefficient query, or it may not even work.
One thing to note is that your conditional operator won't compile; you can't return a bool and an int from the ternary operator.
Maybe you mean:
var products = (from lProducts in db.Products
where (useProductAccess ?
productsAccessible.Contains(lProducts.ID)
: true)
select lProducts).ToList();
or build your query up using method syntax and only add the where clause if necessary.

Append string to linq-to-sql query

I have a form with some indexes based on a document type.
I want to build my linq-to-sql query based on those index. The user might fill just some indexes or all of then.
I would need somenthing like that
Gedi.Models.OperacoesModel.indexMatrix[] IndexMatrixArr = (from a in context.sistema_Documentos
join b in context.sistema_Indexacao on a.id equals b.idDocumento
join c in context.sistema_Indexes on a.idDocType equals c.id
join d in context.sistema_DocType_Index on c.id equals d.docTypeId
where d.docTypeId == idTipo and "BUILT STRING"
orderby b.idIndice ascending
select new Gedi.Models.OperacoesModel.indexMatrix {
idDocumento = a.id,
idIndice = b.idIndice,
valor = b.valor
}).Distinct().ToArray();
This built string should be buit early in the code something like
field1 == a and field2 == b
Is this possible?
Your goal is to create expression dynamicaly, as far as I can see. And there are no way just to put string in linq query and make it work in simple linq world - that's the bad news. But I also have a good news for you - there are some way exist to create your query dynamicaly:expression tree, dynamic LINQ.

Add Join to this LINQ Query

I'm using the following query and am having trouble figuring out how to add a join into it:
var chi = Lnq.attlnks.Where(a => a.ownerid == emSysid)
.Select(c => new { sysid });
How can I join this to the "attach" table (ON attlnks.sysid = attach.sysid) and select "name" where sysid is the row id?
For joins in Linq the query expression form is typically more readable than lambda syntax - I believe this is what you are asking for:
var chi = from t in Lnq.attach
join a in Lnq.attlnks
on t.sysid equals a.sysid
where a.ownerid == emSysid
select t.name;
If there is only a single entry that should match at most, you can chain a FirstOrDefault() in this case (or other alternatives like SingleOrDefault, Single, First etc.):
var chi = (from t in Lnq.attach
join a in Lnq.attlnks
on t.sysid equals a.sysid
where a.ownerid == emSysid
select t.name).FirstOrDefault();
If I understood your problem, this should work fine:
var query = from a in attlinks
join aa in attach on a.sysid equals aa.sysid into a2
where a2.sysid == a2.ownerid
select a2.Name;

Categories