Linq query where conditions not evaluating - linq

Not all filtering in where contions. The first pass to check if items are active or discontinued evaluates then the second portion of the were evaluates to check what type of item. The last portion of the where checking for quantity values is not evaluating and with variables passed.
query:
from i in items
join idt in itemDetails on i.Id equals idt.ItemId
join ip in itemPrice on i.Id equals ip.ItemId
join s in supplier on i.SupplierID equals s.Id
join so in salesOrderItems on i.Id equals so.ItemId into salesTable
from x in salesTable.DefaultIfEmpty()
where (i.ItemStatus == "ACT" || i.ItemStatus == "DISC" && i.StoreID == null)
&& (i.ItemType == stock || i.ItemType == part || i.ItemType == specialOrder)
&& (idt.ReorderQty >= sales || idt.WarrantyQty >= warranty || idt.NextOrderQty >= next || idt.ReorderPoint > reorderPoint || x.SalesOrderItemStatus == requests)

Related

Subtract two dates with 'let' variable then average()?

Attempting to subtract two dates from one another to figure out the number of days, then execute .Average() on the 'let' variable avgConversion.
I encounter the following error; LINQ to Entities does not recognize the method 'System.TimeSpan Subtract(System.DateTime)' method, and this method cannot be translated into a store expression.
var averageConversion =
(
from r in db.Registrations
where
(bu == "All" || r.BusinessUnit.Equals(bu)) &&
(region == "All" || r.Region.Equals(region)) &&
(startDate == null || r.StartDate >= startDate) &&
(endDate == null || r.EndDate <= endDate) &&
!r.RegistrationStatus.Equals("Cancelled") &&
!r.Status.Equals("Cancelled")
let avgConversion = r.StartDate.Value.Subtract(r.RegistrationDate.Value).Days
select avgConversion
).Average();
Thanks to Enigma, this is what ended up solving the problem.
var dates = (from r in db.Registrations
where
(bu == "All" || r.BusinessUnit.Equals(bu)) &&
(region == "All" || r.Region.Equals(region)) &&
(startDate == null || r.StartDate >= startDate) &&
(endDate == null || r.EndDate <= endDate) &&
!r.RegistrationStatus.Equals("Cancelled") &&
!r.Status.Equals("Cancelled")
select new
{
r.RegistrationDate,
r.StartDate
}).ToList();
var avgConversion = (from d in dates
let AvgConversion = d.StartDate.Value.Subtract(d.RegistrationDate.Value).Days
select AvgConversion).Average();
Remember that Entity Framework translates a subset of all possible LINQ statements into SQL. If you use methods or functions that can't be translated the you get the "method cannot be translated into a store expression" error.
Instead you should pull your data into memory before doing the calculation so that you can run the full LINQ expression.
Like this:
var averageConversion =
(
from r in db.Registrations
where
(bu == "All" || r.BusinessUnit.Equals(bu)) &&
(region == "All" || r.Region.Equals(region)) &&
(startDate == null || r.StartDate >= startDate) &&
(endDate == null || r.EndDate <= endDate) &&
!r.RegistrationStatus.Equals("Cancelled") &&
!r.Status.Equals("Cancelled")
select new
{
r.StartDate,
r.RegistrationDate
}
)
.ToArray()
.Select(r => r.StartDate.Value.Subtract(r.RegistrationDate.Value).Days)
.Average();

Any vs Where clause in LINQ

I always thought LINQ to SQL equivalent for an exists query is to use Any(). But i recently wrote a query in LINQ , which basically is trying to find if duplicate records exists in single table.
Anycontext.Contacts.Any(c => ((c.FirstName == contact.FirstName && c.LastName == contact.LastName && c.AddressLine1 == contact.AddressLine1 && c.Zip == contact.Zip)||
(!String.IsNullOrEmpty(contact.Email) && c.Email == contact.Email)))
matching criteria is simple to find contacts with same FirstName, LastName and AddressLine1 or same Email. This query times out in 30 sec(default), there are just 500K rows in this table.
Wherecontext.Contacts.Where(c => ((c.FirstName == contact.FirstName && c.LastName == contact.LastName && c.AddressLine1 == contact.AddressLine1 && c.Zip == contact.Zip)||
(!String.IsNullOrEmpty(contact.Email) && c.Email == contact.Email))).Count()>0
I was forced to use Where clause and then do count greater than 0 to find if any duplicate exists in the set. What i can not understand is, why LINQ to SQL on simple Any clause timing out.
Any explanation will be really great here.
EDIT
SQL From from LINQ Pad
ANY
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
FROM [Accounts].[Contacts] AS [t0]
WHERE ([t0].[CompanyID] = #p0) AND ((([t0].[FirstName] = #p1) AND ([t0].[LastName] = #p2) AND ([t0].[AddressLine1] = #p3) AND ([t0].[Zip] = #p4)) OR (([t0].[FirstName] = #p5) AND ([t0].[LastName] = #p6) AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM [Accounts].[PhoneNumbers] AS [t1]
WHERE ([t1].[ContactNumber] = #p7) AND ([t1].[ContactID] = [t0].[ContactID])
))))
) THEN 1
ELSE 0
END) AS [value]
Where
SELECT [t0].[ContactID]
,[t0].[CompanyID]
,[t0].[CompanyTitle]
,[t0].[FirstName]
,[t0].[LastName]
,[t0].[AddressLine1]
,[t0].[AddressLine2]
,[t0].[City]
,[t0].[State]
,[t0].[Zip]
,[t0].[Email]
,[t0].[Salutation]
,[t0].[IsActive]
FROM [Accounts].[Contacts] AS [t0]
WHERE ([t0].[CompanyID] = #p0)
AND (
(
([t0].[FirstName] = #p1)
AND ([t0].[LastName] = #p2)
AND ([t0].[AddressLine1] = #p3)
AND ([t0].[Zip] = #p4)
)
OR (
([t0].[FirstName] = #p5)
AND ([t0].[LastName] = #p6)
AND (
EXISTS (
SELECT NULL AS [EMPTY]
FROM [Accounts].[PhoneNumbers] AS [t1]
WHERE ([t1].[ContactNumber] = #p7)
AND ([t1].[ContactID] = [t0].[ContactID])
)
)
)
)
Not completely sure if this is what you want, but you could compare, I'm guessing you wont run the test often, as it would be better to test for existence before you input the data to the DB.
If you want to find the duplicates then
var queryA = from a in db.someTable
select a.value;
foreach(var row in queryA){
Console.Write(queryA.Where(b => b == row).Count() > 1 ? row: "");
}
If you just want to test if it exist then.
var queryA = from a in db.someTable
select a.value;
var queryB = queryA;
queryB.Distinct();
Console.Write(queryB.Count() != queryA.Count() ? "Yes" : "No");

Subselect with LINQ

I want to do a subselect with LINQ
What I have, but incorrect
var diretores = from item in db.San_PropostaConversa
join sc in db.San_Credenciada
on (item.Credenciada_Id) equals sc.Credenciada_Id
join sp in db.San_Proposta
on (item.Proposta_Id) equals sp.Proposta_Id
join si in db.San_Imovel
on (sp.Imovel_Id) equals si.Imovel_Id
join su in db.San_Usuario
on (item.Usuario_Id) equals su.Usuario_Id
where item.Proposta_Id == proposta
orderby item.DataHora descending
select new
{
sc.Apelido,
su.NomeCompleto,
su.DescricaoCargo1,
item.Comentario,
item.DataHora,
sp.Imovel_Id,
CredenciadaCaptadora_Id = si.Credenciada_Id,
item.Credenciada_Id,
(from item2 in db.San_Usuario
where item2.Cargo_Id == 9
&& item2.Excluido == 0
&& item2.Credenciada_Id == item.Credenciada_Id
select item2.Email)
};
In my SELECT statement, I want to recover an email column following some conditions that are specified in my WHERE clause.
Error
Invalid anonymous type member declarator. Anonymous type members must
be declared with a member assignment, simple name or member access
You have 2 problems in your linq expression:
You need to assign the result of the subquery to a member of the new anonymous type.
I think you only want to select 1 email with your subquery, so you need to use Single()/SingleOrDefault() or First()/FirstOrDefault().
Try this:
var diretores = from item in db.San_PropostaConversa
join sc in db.San_Credenciada
on item.Credenciada_Id equals sc.Credenciada_Id
join sp in db.San_Proposta
on (item.Proposta_Id) equals sp.Proposta_Id
join si in db.San_Imovel
on sp.Imovel_Id equals si.Imovel_Id
join su in db.San_Usuario
on item.Usuario_Id equals su.Usuario_Id
where item.Proposta_Id == proposta
orderby item.DataHora descending
select new
{
Apelido = sc.Apelido,
NomeCompleto = su.NomeCompleto,
DescricaoCargo1 = su.DescricaoCargo1,
Comentario = item.Comentario,
DataHora = item.DataHora,
Imovel_Id = sp.Imovel_Id,
CredenciadaCaptadora_Id = si.Credenciada_Id,
Credenciada_Id = item.Credenciada_Id,
Email = (from item2 in db.San_Usuario
where item2.Cargo_Id == 9
&& item2.Excluido == 0
&& item2.Credenciada_Id == item.Credenciada_Id
select item2.Email).FirstOrDefault()
};
Mostly this error occurring for unavailable assigning variable,
please try this
it will help you
var diretores = from item in db.San_PropostaConversa
join sc in db.San_Credenciada
on (item.Credenciada_Id) equals sc.Credenciada_Id
join sp in db.San_Proposta
on (item.Proposta_Id) equals sp.Proposta_Id
join si in db.San_Imovel
on (sp.Imovel_Id) equals si.Imovel_Id
join su in db.San_Usuario
on (item.Usuario_Id) equals su.Usuario_Id
where item.Proposta_Id == proposta
orderby item.DataHora descending
select new
{
Apelido=sc.Apelido,
NomeCompleto=su.NomeCompleto,
DescricaoCargo1=su.DescricaoCargo1,
Comentario=item.Comentario,
DataHora=item.DataHora,
Imovel_Id=sp.Imovel_Id,
CredenciadaCaptadora_Id = si.Credenciada_Id,
Credenciada_Id= item.Credenciada_Id,
result= (from item2 in db.San_Usuario
where item2.Cargo_Id == 9
&& item2.Excluido == 0
&& item2.Credenciada_Id == item.Credenciada_Id
select item2.Email)
};

Sql to linq convention

i have a problem to build my linq query and i need you help , the following code is what i have got so far
, it does has some errors as expected, so, this is my sql query :
*im new to linq and did searched over google.
select CAST(h.changedate as date) as 'RegDate' ,count (cast(h.changedate as date)) as 'Amount' from T_TalmidStatusHistory h
join T_talmid t on h.talmidid = t.talmidid
where t.talmidStatusID=16 and h.[statusid] != 16
and h.id =
(
select max(id) from T_TalmidStatusHistory
where T_TalmidStatusHistory.talmidid=h.talmidid and T_TalmidStatusHistory.[statusid] != 16
)
group by CAST(h.changedate as date)
and this is what i have right now in linq:
var res = from r in db.T_TalmidStatusHistories
from m in db.T_TalmidStatusHistories
join t in db.T_Talmids on r.TalmidID equals t.TalmidID
where t.TalmidStatusID == 16 && r.StatusID != 16
&& r.id == from l in db.T_TalmidStatusHistories
where m.TalmidID == r.TalmidID && m.StatusID != 16
select new{db.T_TalmidStatusHistories.OrderByDescending(tp => tp.id).FirstOrDefault().id }
group h by h.changedate as date
select new { h.changedate as date, count (cast(h.changedate as date))};
Edit:
i'm expecting to get the number of students that sign up on each date,
my error is :
Operator '==' cannot be applied to operands of type 'int' and 'System.Linq.IQueryable'
at line : r.id == from l in db.T_TalmidStatusHistories
ty.
The whole part
from l in db.T_TalmidStatusHistories ... count (cast(h.changedate as date))}
is one query which is compared to r.id by the == operator.
Change it to
...
r.id == (db.T_TalmidStatusHistories
.Where(m.TalmidID == r.TalmidID && m.StatusID != 16)
.OrderByDescending(tp => tp.id).FirstOrDefault().id)
group h by h.changedate as date
select new { h.changedate as date, count (cast(h.changedate as date))};

Convert this SQL query to Linq (Not Exists + sub query)

I would like this SQL to be converted to LINQ. (it shouldl select rows from input which do not exist in table production based on 3 columns. If a column in both tables contains NULL, it should be considered as having the same value)
SELECT i.* FROM INPUT AS i
WHERE NOT EXISTS
(SELECT p.Agent FROM Production AS p
WHERE ISNULL(i.CustID,'') <> ISNULL(p.CustID,'')
AND ISNULL(i.CustName,'') <> ISNULL(p.CustName,'')
AND ISNULL(i.household,'') <> ISNULL(p.Household,''))
First of all - this is not a good SQL query. Every column is wrapped in a non-sargable function which means that the engine won't be able to take advantage of any indexes on any of those columns (assuming you have any).
Let's start by rewriting this as a semi-decent SQL query:
SELECT i.*
FROM Input i
LEFT JOIN Production p
ON (p.CustID = i.CustID OR (p.CustID IS NULL AND i.CustID IS NULL))
AND (p.CustName = i.CustName OR (p.CustName IS NULL AND i.CustName IS NULL))
AND (p.Household = i.Household OR
(p.Household IS NULL AND i.Household IS NULL))
WHERE p.CustID IS NULL
Now having said this, LEFT JOIN / IS NULL is not great for efficiency either, but we don't have much choice here because we're comparing on multiple columns. Based on your column names, I'm starting to wonder if the schema is properly normalized. A CustID should most likely be associated with one and only one CustName - the fact that you have to compare both of these seems a bit odd. And Household - I'm not sure what that is, but if it's a varchar(x)/nvarchar(x) column then I wonder if it might also have a 1:1 relationship with the customer.
If I'm speculating too much here then feel free to dismiss this paragraph; but just in case, I want to say that if this data isn't properly normalized, normalizing it would make it much easier and faster to query on:
SELECT *
FROM Input
WHERE CustID NOT IN (SELECT CustID FROM Production)
Anyway, going back to the first query, since that's what we have to work with for now. Unfortunately it's impossible to create a join on those specific conditions in Linq, so we need to rewrite the SQL query as something slightly worse (because we now have to read from Input twice):
SELECT *
FROM Input
WHERE <Primary Key> NOT IN
(
SELECT i.<Primary Key>
FROM Input i
INNER JOIN Production p
ON (p.CustID = i.CustID OR (p.CustID IS NULL AND i.CustID IS NULL))
AND (p.CustName = i.CustName OR (p.CustName IS NULL AND i.CustName IS NULL))
AND (p.Household = i.Household OR
(p.Household IS NULL AND i.Household IS NULL))
)
Now we have something we can finally translate to Linq syntax. We still can't do the join explicitly, which would be best, but we go old-school, start from the cartesian join and toss the join conditions into the WHERE segment, and the server will still be able to sort it out:
var excluded =
from i in input
from p in production
where
((p.CustID == i.CustID) || ((p.CustID == null) && (i.CustID == null))) &&
((p.CustName == i.CustName) ||
((p.CustName == null) && (i.CustName == null))) &&
((p.Household == i.Household) ||
((p.Household == null) && (i.Household == null)));
select i.PrimaryKey;
var results =
from i in input
where !excluded.Contains(i.PrimaryKey)
select i;
I'm assuming here that you have some sort of primary key on the table. If you don't, you've got other problems, but you can get around this particular problem using EXCEPT:
var excluded =
from i in input
from p in production
where
((p.CustID == i.CustID) || ((p.CustID == null) && (i.CustID == null))) &&
((p.CustName == i.CustName) ||
((p.CustName == null) && (i.CustName == null))) &&
((p.Household == i.Household) ||
((p.Household == null) && (i.Household == null)));
select i;
var results = input.Except(excluded);

Resources