How to write a Linq statement in SQL? - sql

I'm fairly new to using Linq in C# and I just want to know how a normal SQL statement will look like when compared to a Linq query?
I have this statement:
var query =
from b in db.Employee.Include(o => o.Position)
where b.Position.Position_Desc == "Junior" && b.Employee_ID == 5
select b;
So my actual question is how will this statement look if I were to write it in SQL?

query.ToString() should return the SQL.
Or you can use LinqPad

If there is a relation between Employees and Positions tables with foreign key say Employees.PositionId -> Positions.Id. Then you can use LEFT JOIN to write a similar SQL query:
SELECT Employees.*,
Positions.*
FROM Employees
LEFT JOIN Positions ON Employees.PositionId = Positions.Id
WHERE Positions.Position_Desc = 'Junior'
AND Employees.Employee_ID = 5

You can check your query in debug mode (see attach image)

Related

Arel UpdateManager with Join creates invalid SQL - how to rephrase?

Apparently there is an issue in Arel core, where Arel::UpdateManager, when performing a column update on a join, does not generate the table name for the update column. It results in invalid SQL.
I ran into this in a Rails 5.2 app, where I had an SQL literal UPDATE statement that I was trying to rephrase in Arel.
UPDATE observations o, names n
SET o.lifeform = n.lifeform
WHERE o.name_id = n.id
AND o.lifeform != n.lifeform
In Arel, i wrote this:
names = Name.arel_table
obs = Observation.arel_table
join_source = Arel::Nodes::JoinSource.new(
obs, [obs.create_join(names)]
)
Arel::UpdateManager.new.
table(join_source).
where(obs[:id].eq(names[:id]).
and(obs[:lifeform].not_eq(names[:lifeform]))).
set([[obs[:lifeform], names[:lifeform]]])
This returns:
Mysql2::Error: Column 'lifeform' in field list is ambiguous:
The problem is at the end. The SQL generated from this does not specify the table where the column is to be set.
UPDATE `observations`
INNER JOIN `names`
SET `lifeform` = `names`.`lifeform`
WHERE (`observations`.`id` = `names`.`id`)
AND (`observations`.`lifeform` != `names`.`lifeform`)
Elsewhere, Arel-generated SQL usually qualifies columns with table names to avoid ambiguity. But the source code for update_manager.rb definitely uses Nodes::UnqualifiedColumn.new(column). (I have added my description to the Arel issue on GitHub.)
For now I'd maybe like to rephrase my Arel some other way. Is there a way to force Arel to quote the table name, similar to connection.quote_table_name?
Or would using a CTE be appropriate?
I guess one way to do this is with ActiveRecord's connection.update_all.
names = Arel::Table.new(:names)
Observation.joins(:name).
 where(names[:correct_spelling_id].not_eq(nil)).
  update_all("`observations`.`name_id` = `names`.`correct_spelling_id`")
This generates the desired SQL:
UPDATE `observations`
INNER JOIN `names`
ON (`observations`.`name_id` = `names`.`correct_spelling_id`)
AND (`names`.`correct_spelling_id` IS NOT NULL)
SET `observations`.`name_id` = `names`.`correct_spelling_id`
I think this is the way to go.

Need help to Convert SQL to LINQ

i need help, i need to convert the following query from SQL to LINQ.
and use it in my mvc view
select b.ID from LibraryTable a
left join User b on a.UserNumber=b.UserNumber
From msdn: Left Outer Joins
var query = from t in LibraryTable
join u in User on t.UserNumber equals u.UserNumber into tu
from d in tu.DefaultIfEmpty()
select new { Id = u == null ? 0 : u.ID };
However, you say you want a left join, but only select something from the right table. This example will just return 0 for anything in LibraryTable that does not have a User record. You may want to consider also selecting something from the left table. To do that, add a new property in the anonymous type in the select.

HQL: Is it possible to perform an INNER JOIN on a subquery?

The diagram above is a simplified version of the database structure that I use to log item locations through time. I wrote the following SQL query which returns the current item inventory of each location:
select *
from ItemLocationLog l
inner join
(select g.idItemLocationLog, max(g.dateTime) as latest
from ItemLocationLog g
group by g.idItem)
as i
on l.idItem = i.idItem and l.dateTime = i.latest
The problem I'm having is that I want to convert that to HQL, but I haven't found the syntax to perform an INNER JOIN on a subquery, and it seems like this is not supported. Is there a way to convert the above to HQL (or a Criteria) or will I have to use a standard SQL query in this case? Thanks.
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html#queryhql-subqueries
Note that HQL subqueries can occur only in the select or where clauses.
You can rewrite the query so that the subquery is part of the where clause instead. Referencing the l.idItem in the subquery

Complex QueryOver

Hi I have to translate folowing sql to QueryOver
Will it be possible ? my actual query may more complex. But I have stuck in this stage.
SELECT InnerQuery.USERID,
InnerQuery.TRAFFICZONEID,
InnerQuery.StatusCategory,
COUNT(*) AS LineCount
FROM (
SELECT MissionID,
UserId,
TRAFFICZONEID,
CASE
WHEN status BETWEEN 1
AND 5
THEN 1
WHEN status BETWEEN 6
AND 8
THEN 2
WHEN status BETWEEN 9
AND 17
THEN 3
ELSE 0
END AS [StatusCategory]
FROM mission
) AS InnerQuery
LEFT OUTER JOIN trafficzone t ON InnerQuery.TRAFFICZONEID = t.Trafficzoneid
GROUP BY InnerQuery.USERID,
InnerQuery.TRAFFICZONEID,
InnerQuery.StatusCategory
Is it possible to do that kind of uery in QueryOver ? Or else what is the best way to do it with NHibernate ?
Thank you,
DineshNS
I suggest you use HQL for this.
From all the query methods supported by NHibernate, it's the one that works best with free-form queries.
The only thing it does NOT support directly is an outer join to a subquery. You can fake that using an implicit join with the subquery (from A, (subquery) B where A.X = B.X) and a UNION for items that don't have matching elements in the subquery.
For a complex query, you could create a view in database and use that from NHibernate.

How write hibernate criteria for specific SQL?

i need write similar SQL by ICriteria:
Tables:
1Lvl -- 2Lvl -- 3Lvl
SQL:
SELECT * FROM 2Lvl
WHERE 2Lvl.1LvlFK in
(
SELECT 1Lvl.Id
FROM 3Lvl
JOIN 2Lvl ON 3Lvl.2LvlFK = 2Lvl.Id
JOIN 1Lvl ON 2Lvl.1LvlFK = 1Lvl.Id
WHERE 3Lvl.Id = 123
)
I'm sorry for so specific question, but I inherited project with Hibernate from exemployee and I can't still understand hibernate-criteria.
var subQuery = DetachedCriteria.For<Lvl3>("lvl3")
.CreateAlias("Lvl2", "sublvl2", JoinType.InnerJoin)
.CreateAlias("Lvl1", "lvl1", JoinType.InnerJoin)
.Add(Restrictions.EqProperty("sublvl2.Id", "lvl2.Id")
.Add(Restrictions.Eq("lvl3.Id", 123)
.SetProjection(Projections.Property("lvl1.Id"));
Session.CreateCriteria<Lvl2>("lvl2")
.Add(Subqueries.PropertyIn("Lvl1.Id", subQuery));
Should do the trick. I've made assumptions about what your entities are called since 1Lvl, etc.. are not valid C# identifiers. I've also assumed the primary key column of each table was Id. Also a note that this won't produce the exact SQL you're looking for, but it will get you the same result.