Entity framework join with a subquery via linq syntax - sql

I'm trying to translate a sql query in linq sintax, but I'm having big trouble
This is my query in SQL
select * FROM dbo.ITEM item inner join
(
select SUM([QTA_PRIMARY]) QtaTotale,
TRADE_NUM,
ORDER_NUM,
ITEM_NUM
from [dbo].[LOTTI]
where FLAG_ATTIVO=1
group by [TRADE_NUM],[ORDER_NUM],[ITEM_NUM]
)
TotQtaLottiGroupByToi
on item.TRADE_NUM = TotQtaLottiGroupByToi.TRADE_NUM
and item.ORDER_NUM = TotQtaLottiGroupByToi.ORDER_NUM
and item.ITEM_NUM = TotQtaLottiGroupByToi.ITEM_NUM
where item.PRIMARY_QTA > TotQtaLottiGroupByToi.QtaTotale
and item.FLAG_ATTIVO=1
How can I translate into linq sintax?
This approach doesn't work
var res= from i in context.ITEM
join d in
(
from l in context.LOTTI
group l by new { l.TRADE_NUM, l.ORDER_NUM, l.ITEM_NUM } into g
select new TotQtaByTOI()
{
TradeNum = g.Key.TRADE_NUM,
OrderNum = g.Key.ORDER_NUM,
ItemNum = g.Key.ITEM_NUM,
QtaTotale = g.Sum(oi => oi.QTA_PRIMARY)
}
)
on new { i.TRADE_NUM, i.ORDER_NUM, i.ITEM_NUM} equals new { d.TradeNum, d.OrderNum, d.ItemNum }
I get this error
The type of one of the expressions in the join cluase is incorrect. Type inference failed in the call to 'Join'
Can you help me with this query?
Thank you!

The problem is Anonymous Type comparison. You need to specify matching property names for your two anonymous type's properties (e.g. first, second, third)
I tried it out, here's an example: http://pastebin.com/hRj0CMzs

Related

Jpa Specification ORA-01791: not a SELECTed expression

I have a problem with Jpa Specification.
My specification looks like this:
public static Specification<PersonView> getByFilter(PersonViewFilter filter) {
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
SetJoin<PersonView, PersonDetailsView> personDetailsJoin =
root.join(PersonView_.personDetails);
Path<String> namePath = personDetailsJoin.get(PersonDetailsView_.name);
Path<String> surnamePath = personDetailsJoin.get(PersonDetailsView_.surname);
predicates.add(namePredicate(personDetailsJoin, criteriaBuilder, filter.getName()));
predicates.add(surnamePredicate(personDetailsJoin, criteriaBuilder, filter.getSurname()));
predicates.add(peselPredicate(personDetailsJoin, criteriaBuilder, filter.getPesel()));
predicates.removeAll(Collections.singleton(EMPTY_PREDICATE));
query.orderBy(List.of(criteriaBuilder.asc(namePath), criteriaBuilder.asc(surnamePath))).distinct(true);
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
};
}
When I try search results I can see an error:
ORA-01791: not a SELECTed expression
The problem is related to generated sql by JpaSpecificationExecutor.
It looks like this:
select
*
from
( select distinct pv.person_id
from
personview pv
inner join
persondetailsview pdv on pv.person_id=pdv.person_id
where
1=1
order by
pdv.name asc,
pdv.surname asc )
where
rownum <= ?
In Select clausule should be added name and surname then it would work, but I don't know how to do this in Specification. Without distinct query works, but i don't have duplicates.
Please for help.
From the error ORA-01791: not a SELECTed expression, you want to add the field to the select or remove the distinct with this :
query.distinct(false);
If you want to keep the distinct, have a look there :
https://stackoverflow.com/a/53549880/2641426

LINQ Lambda where in subquery

I´m trying do something like this :
Select * from A where id in (Select id_a from B)
But in LINQ
db.A().Join(db.B(), a => a.id, b => b.id_a, (a , b) => new { a, b}).....
I can do a JOIN. Is the best way? Or i have another options?.
I´m using Entity Framework
Thanks
From my SQL to LINQ recipe:
For translating SQL to LINQ query comprehension:
Translate subselects as separately declared variables.
Translate IN to .Contains() and NOT IN to !...Contains(), using literal arrays or array variables for constant lists.
SELECT * must be replaced with select range_variable or for joins, an anonymous object containing all the range variables.
So, for your SQL,
var id_aInB = from b in db.B select b.id_a;
var ans = from a in db.A where id_aInB.Contains(a.id) select a;
Using subquery in LINQ lambda
var q = db.A.Where(a=> db.B.Select(b=>b.id_a).toList().Contains(a.Id)).Select(a=>a);
In Linq there are many ways to express that. That SQL can also be expressed in different ways and probably the best is to use an EXISTS query instead, like:
Select * from A
where EXISTS (Select * from B where A.id = B.id_a)
That could be written in Linq as:
db.A.Where( a => db.B.Any( b => a.Id == b.Id_a ) );
Maybe you need this:
var result=db.A.Select(c=>new {c,listId=db.B.Select(s=>s.id_a)}).Where(w=>w.listId.Contains( w.c.id)).Select(c=>c.c);
Or you can use LINQ like this
from a in db.A
let listId = from b in db.B
select b.id_a
where listId.Contains(a.id)
select a
By the way, use LINQPad,you can get the right lamda by LINQ search

Linq Query in VB

Good Day,
I am querying my database using Linq and I have run into a problem, the query searched a column for a search phrase and based on if the column has the phrase, it then returns the results, The query is below,
Dim pdb = New ProductDataContext()
Dim query =
From a In pdb.tblUSSeries
Join b In pdb.tblSizes_ On a.Series Equals b.Series
Where
a.Series.ToString().Equals(searchString) Or
b.Description.Contains(searchString) Or Not b.Description.Contains(Nothing)
Order By b.Series, b.OrderCode Ascending
Select New CustomSearch With
{
.Series = a.Series,
.SeriesDescription= a.Description,
.Coolant = a.Coolant,
.Material = a.Material,
.Standard = a.Standard,
.Surface = a.Surface,
.Type = a.Type,
.PointAngle = a.PointAngle,
.DiaRange = a.DiaRange,
.Shank = b.Shank,
.Flutes = b.Flutes,
.EDPNum = b.EDPNum,
.SizesDescription = b.Description,
.OrderCode = b.OrderCode
}
Return query
I think the problem is that, in the table certain rows are NULL, so when it is checking the column for the phrase and it encounters a row that is null it, breaks and returns this error,
The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
I have ran this query against another column that has all the rows populated with data and it returns the results ok.
So my question is how can I write it in VB to query the db with the supplied searchstring and return the results, when some of the rows in the columns have null values.
Any help would be great.
The exception occurs when you make the projection (i.e. select new CustomSearch)
And yes your trying to assign Null to some int property
(Not sure which one of your properties that is)
one of 2 choices :
1) Use nullalbe types for your properties (or just that one property).
2) project with an inline If ( ?? in C#) , I don't know VB so don't catch me on the syntax.
Taking Series just as an example i don't know if it's an int or if that's the problematic property
Select New CustomSearch With
{
.Series = If(a.Series Is Nothing,0, CInt(a.Series))
}
In C#
Select new CustomSearch
{
Series = a.Series ?? 0;
}

Inserting a variable in a raw sql query Laravel

I am inside a function in a controller.
So from the Form, I get a value for a variable, say:
$x = "whatever";
Then I need to embed that variable (so, its value), in the WHERE statement. If I hardcode the value, it brings a correct result, but I have tried in all ways to insert that variable without success. Well, supposing that I manage to use that variable, then I will have to look into binding to avoid sql injection, but so far, I would say, see if that variable can get used in the query.
I have tried, double quotes, concatenation . $vx . , curly braces {$x}, the variable plain like this $variable, but either gives syntax errors in some cases, (concatenation), or if I just embed the variable like this where author = $x, it tells me that it can't find the column named $x
$x = "whatever";
$results = DB::select(DB::raw('SELECT
t.id, t.AvgStyle, r.RateDesc
FROM (
SELECT
p.id, ROUND(AVG(s.Value)) AS AvgStyle
FROM posts p
INNER JOIN styles s
ON s.post_id = p.id
WHERE author = $x
GROUP BY p.id
) t
INNER JOIN rates r
ON r.digit = t.AvgStyle'
));
This appears to be a simple PHP variable interpolation issue.
DB::raw() wants literally raw SQL. So there are a couple of issues that need to be fixed in the SQL string you are passing.
PHP Variable interpolation (injecting variables into a string) only happens if you use double quotes around the string. With single quotes it becomes a string constant.
If Author is a char/varchar, then SQL syntax requires quotes around the string in your raw SQL statement. Query builders typically take care of these issues for you, but you are going around them.
So the "fixed" version of this would be:
$x = "whatever";
$results = DB::select(DB::raw("SELECT
t.id, t.AvgStyle, r.RateDesc
FROM (
SELECT
p.id, ROUND(AVG(s.Value)) AS AvgStyle
FROM posts p
INNER JOIN styles s
ON s.post_id = p.id
WHERE author = '$x'
GROUP BY p.id
) t
INNER JOIN rates r
ON r.digit = t.AvgStyle"
));
Like all interpolation, this opens you up to the possibility of SQL injection if the variable being interpolated comes from user input. From the original question it is unclear whether this is a problem.
DB::select() has an option that allows you to pass an array of parameters that is inherently safe from SQL injection. In that case the solution would be:
$x = "whatever";
$results = DB::select(DB::raw("SELECT
t.id, t.AvgStyle, r.RateDesc
FROM (
SELECT
p.id, ROUND(AVG(s.Value)) AS AvgStyle
FROM posts p
INNER JOIN styles s
ON s.post_id = p.id
WHERE author = :author
GROUP BY p.id
) t
INNER JOIN rates r
ON r.digit = t.AvgStyle"
),
array('author' => $x)
);
Regarding this tutorial
$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"), array(
'somevariable' => $someVariable,
));
This is one example for you to insert variable in a raw sql laravel
$query_result = Event::select(
DB::raw('(CASE WHEN status = "draft" THEN "draft"
WHEN events.end_time <= \''.$now.'\' THEN "closed"
ELSE "available"
END) AS status'))
->orderBy('status')
->get();

How to get the latest/last record with a group by clause with NHibernate Linq provider

I have used too much time (days) on this and I really hope someone can help me out.
I found a good article on describing my problem in a generic way so let's stick to it.
I am trying to build this query but NHibernate fails to build the correct sql and returns a sql query exception.
Column vSagsAendring.Id is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. It could not execute the following query:
select
viewsagsae0_.Id as Id155_,
viewsagsae0_.SagId as SagId155_,
viewsagsae0_.JournalNr as JournalNr155_,
viewsagsae0_.LbfNr as LbfNr155_,
viewsagsae0_.OrgNr as OrgNr155_,
viewsagsae0_.OrgNavn as OrgNavn155_,
viewsagsae0_.AfdNavn as AfdNavn155_,
viewsagsae0_.SagsType as SagsType155_,
viewsagsae0_.Status as Status155_,
viewsagsae0_.SagsbehandlerInit as Sagsbeh10_155_,
viewsagsae0_.Dato as Dato155_,
viewsagsae0_.JournalAktionType as Journal12_155_,
viewsagsae0_.Beskrivelse as Beskriv13_155_,
viewsagsae0_.Ekstern as Ekstern155_
from vSagsAendring viewsagsae0_
group by viewsagsae0_.SagId
var query = from p in _session.Query<ViewSagsAendring>()
group p by p.SagId
into grp
select grp.OrderByDescending(g => g.Dato).First();
This is another version also took from the article:
var query = from p in _session.Query<ViewSagsAendring>()
group p by p.SagId
into grp
let maxDato = grp.Max(g => g.Dato)
from p in grp
where p.Dato == maxDato
select p;
It's have been a long journey, but now it's over. I hope that I can help someone else in the same situation by answering my own question.
var aendring = from sagsAendring in _session.Query<ViewSagsAendring>()
where sagsAendring.Dato ==
(
from innersagsAendring in _session.Query<ViewSagsAendring>()
where innersagsAendring.SagId == sagsAendring.SagId
select innersagsAendring.Dato
).Max()
select sagsAendring;
var result = aendring.ToList();
And because you can chain linq statements you can build a linq filter like this
if(Filters.VisInterneAendringer == false)
query = query.Where(x => x.Ekstern == true);
if (Filters.VisKunNyesteAendringer)
{
query = query.Where(sagsAendring => sagsAendring.Dato ==
(
from innerSagsAendring in Session.Query<ViewSagsAendring>() where innerSagsAendring.SagId == sagsAendring.SagId
select innerSagsAendring.Dato
).Max());
}
return query;
Your queries seem legit for LINQ in EntityFramework.
I'm not sure about hibernate, you might try to use QueryOver API instead of Query
http://nhibernate.info/blog/2009/12/17/queryover-in-nh-3-0.html