get the value of a query to be part of another query - c#

I'm trying to use the value of signerID to be part of the where clause in another query, but getting red underline with error: "delegate does not take 1 argument". Basically I want to use the value of signerID query (value = 15) in the where clause of the query allDepartments. Here's the code:
using (dbPSREntities10 myEntities = new dbPSREntities10())
{
int theStatus = Convert.ToInt32(ddlChangeStatus.SelectedValue);
string userName = HttpContext.Current.User.Identity.Name;
var signerID = (from refAuthSigner in myEntities.refAuthSigners.Where(x => x.NetworkUsername == userName)
select new
{
refAuthSignerID = refAuthSigner.refAuthSignerID
}); <---- here I should have the value 15
var allDepartments = (from tbProject in myEntities.tbProjects.Where(x => x.refAuthSignerID == signerID)<-- and I want to use the value of signerID (15) here
Is this way off? I can hardcode 15 in place of signerID in the where clasue and everything works fine. Thanks in advance!

I suggest you to join tables on singer id:
var allDepartments =
from p in myEntities.tbProjects
join s in myEntities.refAuthSigners
on p.refAuthSignerID equals s.refAuthSignerID
where s.NetworkUsername == userName
select p;
This query will select only those project which have singer id equal to id of singer with provided name.
Of course, you can do all in two queries - get id by first query, and them use id in second query:
int singerId = myEntities.refAuthSigners
.Where(s => s.NetworkUsername == userName)
.Select(s => s.refAuthSignerID)
.FirstOrDefault(); // execute first query
if (singerId == 0)
return; // singer not found
// build second query
var allDepartments = myEntities.tbProjects
.Where(p => p.refAuthSignerID == signerID);

Related

How can I get build a query based on array of IDs using EF

I'm trying to build a query selecting all records containing IDs which are stored in the list using that code:
var assistsIds = _context.Assistances.Where(c => c.IdUser == user.IdUser)
.Select(x => x.Owner.IdOwner).ToList();
Then I'm going through all the list elements to get a query:
var query = _context.Accounts.Where(_ => _.IsDeleted != 1);
foreach(var assist in assistsIds)
{
query = query.Where(_ => _.IdOwner == assist);
}
The result is that I'm getting something like this:
SELECT * FROM Accounts WHERE IdOwner = 1 AND IdOwner = 2 ...etc
Instead of:
SELECT * FROM Accounts WHERE IdOwner = 1 OR IdOwner = 2 ... etc
Is there a way to apply OR operator, or maybe there is some other way to achieve that?
You could use Contains:
var query = _context.Accounts
.Where(_ => _.IsDeleted != 1 && assistsIds.Contains(_.IdOwner));
This will return all records which match an Id in the assistsIds list.

C# query only when textbox is edited

I have a query that work on a great data table. The code for the query is:
var getExtInv = snd.external_invoices.OrderByDescending(x => x.date).ToList();
var query = (from c in getExtInv
join o in snd.invoices on c.idexternal_invoices equals o.id_external_invoice
select new {c.idexternal_invoices,
c.businessname,
o.number,
c.message,
c.price,
c.date,
c.tipologiaPagamento,
c.esitoPagamento,
c.iduser
}).ToList();
I need to filter this query with a number of textbox value that can be empty. An example for one search filter is:
if (txtIdUser.Text != "")
{
int idUserSel = Convert.ToInt32(txtIdUser.Text);
query = query.Where(x => x.iduser == idUserSel).ToList();
}
the problem is that with this approach initially load a very high number of data which then filter based on the presence or absence of textfield filled. In doing so the initial loading time is very long. How can I speed up the process?
Thanks to all
As mentioned, don't use .ToList, .ToArray, .Count, etc. before you are ready to use the results.
int i = 0;
var query = from c in snd.external_invoices.OrderByDescending(x => x.date)
join o in snd.invoices on c.idexternal_invoices equals o.id_external_invoice
select new {c.idexternal_invoices, c.businessname, o.number, c.message,
c.price, c.date, c.tipologiaPagamento, c.esitoPagamento, c.iduser };
if(int.TryParse(txtIdUser.Text, out i) // this will check if text is not empty and valid int
query = query.Where(x => x.iduser == i);
and at the end when you are ready to use the results:
var results = query.ToList();

LINQ group by with multiple counts

I am having trouble doing multiple counts on a single table in a LINQ query. I am using NHibernate, LINQ to NHibernate and C#.
query is a populated list. I have a table that has a boolean called FullRef. I want to do a LINQ query to give a count of occurances of FullRef = false and FullRef = true on each TrackId. TrackId gets a new row for each time he gets a track.Source == "UserRef".
In the following query I get the correct number count (from the FullRefTrueCount) of FullRef = true, but it gives an unknown wrong number on the FullRefFalseCount.
var query2 = from track in query
where track.Source == "UserRef"
group track by new { TrackId = track.TrackId, FullRef = track.FullRef } into d
select new FullReferrer
{
Customer = d.Key.TrackId,
FullRefFalseCount = d.Where(x => x.FullRef == false).Count(),
FullRefTrueCount = d.Where(x => x.FullRef == true).Count()
};
Anyone have any idea on how to fix it? I am pretty certain the .Where() clause is ignored and the "group by" is screwing me over.
If I could somehow
group track by new { TrackId = track.TrackId, FullRefTrue = track.FullRef, FullRefFalse = !track.FullRef }"
it would work. Is there some way to do this?
you should group by trackId only, if you want results by trackId...
var query2 = query
.Where(m => m.Source == "UserRef")
.GroupBy(m => m.TrackId)
.Select(g => new FullReferrer {
Customer = g.Key,
FullRefFalseCount = g.Count(x => !x.FullRef),
FullRefTrueCount = g.Count(x => x.FullRef)
});

Get item index (rownum)

I have table with 10 000 elements.
IQuerable<IEntity> query = dataRep.Get<IEntity>()
.Query();
I need to get the index(rownum) of selected obj without getting all table items
var obj = query.Where( x => x.Name == "testName")
.FirstOrDefault();
The simple sql work fine :
select name, id, r from
(
select name, id, rownum r from collections order by id
) where name = 'testName';
How do this in Linq to NHibernate ?
Edit:
I tried add to IEntity class property RowNumber and mapping this on hbm as
<property name="RowNumber" formula="rownum" />
But after
var index = query.Where( x => x.Name == "testName")
.Select( x => x.RowNumber)
.FirstOrDefault();
Get always 1 value
Can you not just filter the query directly?
IQuerable<IEntity> query = dataRep.Get<IEntity>()
.Query()
.FirstOrDefault(x => x.Name == "testName");
Edit:
To get the item you can project into an anonymous type:
var query = (from data in dataRep.Get<IEntity>().Query()
where Name == "testName"
select new
{
id = data.id,
rowNumber = data.rowNumber
}).FirstOrDefault();

LINQ Using Max() to select a single row

I'm using LINQ on an IQueryable returned from NHibernate and I need to select the row with the maximum value(s) in a couple of fields.
I've simplified the bit that I'm sticking on. I need to select the one row from my table with the maximum value in one field.
var table = new Table { new Row(id: 1, status: 10), new Row(id: 2, status: 20) }
from u in table
group u by 1 into g
where u.Status == g.Max(u => u.Status)
select u
This is incorrect but I can't work out the right form.
BTW, what I'm actually trying to achieve is approximately this:
var clientAddress = this.repository.GetAll()
.GroupBy(a => a)
.SelectMany(
g =>
g.Where(
a =>
a.Reference == clientReference &&
a.Status == ClientStatus.Live &&
a.AddressReference == g.Max(x => x.AddressReference) &&
a.StartDate == g.Max(x => x.StartDate)))
.SingleOrDefault();
I started with the above lambda but I've been using LINQPad to try and work out the syntax for selecting the Max().
UPDATE
Removing the GroupBy was key.
var all = this.repository.GetAll();
var address = all
.Where(
a =>
a.Reference == clientReference &&
a.Status == ClientStatus.Live &&
a.StartDate == all.Max(x => x.StartDate) &&
a.AddressReference == all.Max(x => x.AddressReference))
.SingleOrDefault();
I don't see why you are grouping here.
Try this:
var maxValue = table.Max(x => x.Status)
var result = table.First(x => x.Status == maxValue);
An alternate approach that would iterate table only once would be this:
var result = table.OrderByDescending(x => x.Status).First();
This is helpful if table is an IEnumerable<T> that is not present in memory or that is calculated on the fly.
You can also do:
(from u in table
orderby u.Status descending
select u).Take(1);
You can group by status and select a row from the largest group:
table.GroupBy(r => r.Status).OrderByDescending(g => g.Key).First().First();
The first First() gets the first group (the set of rows with the largest status); the second First() gets the first row in that group.
If the status is always unqiue, you can replace the second First() with Single().
Addressing the first question, if you need to take several rows grouped by certain criteria with the other column with max value you can do something like this:
var query =
from u1 in table
join u2 in (
from u in table
group u by u.GroupId into g
select new { GroupId = g.Key, MaxStatus = g.Max(x => x.Status) }
) on new { u1.GroupId, u1.Status } equals new { u2.GroupId, Status = u2.MaxStatus}
select u1;
What about using Aggregate?
It's better than
Select max
Select by max value
since it only scans the array once.
var maxRow = table.Aggregate(
(a, b) => a.Status > b.Status ? a : b // whatever you need to compare
);
More one example:
Follow:
qryAux = (from q in qryAux where
q.OrdSeq == (from pp in Sessao.Query<NameTable>() where pp.FieldPk
== q.FieldPk select pp.OrdSeq).Max() select q);
Equals:
select t.* from nametable t where t.OrdSeq =
(select max(t2.OrdSeq) from nametable t2 where t2.FieldPk= t.FieldPk)
Simply in one line:
var result = table.First(x => x.Status == table.Max(y => y.Status));
Notice that there are two action.
the inner action is for finding the max value,
the outer action is for get the desired object.

Categories