Convert SQL query to Nhibernate Criteria - nhibernate

My SQL query:
select [CompanyId]
from dbo.Bussiness_Company
where [BussinessId] in (11,12,13)
group by [CompanyId]
having COUNT(distinct [BussinessId])=3
Explain:
I have a table Bussiness_Company table :
Bussiness_Company
Id*
BussinessId
CompanyId
My data:
Id---------BussinessId------------CompanyId
1----------10---------------------100
2----------11---------------------100
3----------12---------------------100
Resaul query
CompanyId
100
Thank for any hepl!
Sloved:
This is my code:
DetachedCriteria detachedCriteria = DetachedCriteria.For<BussinessCompany>();
detachedCriteria.SetProjection(Projections.Property("Company"));
detachedCriteria.SetProjection(Projections.GroupProperty("Company"));
Disjunction disjunction = Restrictions.Disjunction();
foreach (Bussiness bussiness in list)
{
disjunction.Add(Restrictions.Eq("Bussiness", bussiness ));
} detachedCriteria.Add(disjunction).Add(Restrictions.Eq(Projections.CountDistinct<BussinessCompany>(m => m.Bussiness), list.Count));
IList<Sonomi.Core.BusinessObjects.Bussiness> bussiness =
bussinessUnitManager.CreateCriteria().Add(Subqueries.PropertyIn("Id", detachedCriteria)).List
<Sonomi.Core.BusinessObjects.BussinessUnit>();
dgrCer.DataSource = bussiness;
dgrCer.DataBind();

You can try a such QueryOver code:
var bussinessIdCount = 3;
var bussinessIds = new[] { 11, 12, 13 };
Bussiness_Company bussinessCompany = null;
session.QueryOver(() => bussinessCompany)
.WhereRestrictionOn(() => bussinessCompany.BussinessId).IsIn(bussinessIds)
.Select(Projections.Group(Projections.Property(() => bussinessCompany.CompanyId)))
.Where(Restrictions.Gt(Projections.CountDistinct(() => bussinessCompany.BussinessId), bussinessIdCount));

Related

Entity Framework Linq to SQL expression containing LEFT JOIN

I'm attempting to translate some T-SQL to an Entity Framework Core lambda expression. It involves an inner join and a left joing with a where clause.
Here is the working SQL query:
SELECT
AspNetUsers.*, Exclusions.*
FROM
AspNetUsers
JOIN Exclusions ON
AspNetUsers.FirstName = Exclusions.FirstName
AND AspNetUsers.LastName = Exclusions.LastName
LEFT JOIN ExclusionsMatches ON
ExclusionsMatches.RowHash = Exclusions.RowHash
WHERE
ExclusionsMatches.MatchIgnoredByUserId IS NULL
Which I have thus far translated into LINQ lambda as such:
var result = _db.Users
.Join(_db.Exclusions, usr => new { usr.FirstName, usr.LastName }, Exc => new { Exc.FirstName, Exc.LastName }, (usr, Exc) => new { usr, Exc })
.GroupJoin(_db.ExclusionsMatches, i => i.Exc.RowHash, x => x.RowHash, (i, ExcMatch) => new { User = i.usr, Exc = i.Exc, ExcMatch = ExcMatch })
.SelectMany(temp => temp.ExcMatch.DefaultIfEmpty(), (temp, p) => new { User = temp.User, Exc = temp.Exc, ExcMatch = temp.ExcMatch})
This seems to give me the desired query output, but I can't seem to figure out how to get the WHERE ExclusionsMatches.MatchIgnoredByUserId IS NULL clause translated.
Any thoughts on how the WHERE might be achieved? I'm also open to changing from lambda expression to linq query expression.
Thanks!
I believe using LINQ is more readable so I can provide an answer using LINQ as below.
from user in _db.Users
join excl in _db.Exclusions on new { usr.FirstName , usr.LastName} equals {excl.FirstName , excl.LastName}
join exclMtch in _db.ExclusionsMatches on excl.RowHash equals exclMtch.RowHash into grp
from itm in grp.DefaultIfEmpty()
where itm.MatchIgnoredByUserId == null
select new {
user,
excl
}
Otherwise, if you insist on using Lambda, first you have to select the field in your final selects and then add the needed where in the end of query.
var result = _db.Users
.Join(_db.Exclusions, usr => new { usr.FirstName, usr.LastName }, Exc => new { Exc.FirstName, Exc.LastName }, (usr, Exc) => new { usr, Exc })
.GroupJoin(_db.ExclusionsMatches, i => i.Exc.RowHash, x => x.RowHash, (i, ExcMatch) => new { User = i.usr, Exc = i.Exc, ExcMatch = ExcMatch MatchIgnoredByUserId = i.MatchIgnoredByUserId })
.SelectMany(temp => temp.ExcMatch.DefaultIfEmpty(), (temp, p) => new { User = temp.User, Exc = temp.Exc, ExcMatch = temp.ExcMatch, MatchIgnoredByUserId= temp.MatchIgnoredByUserId })
.Where(q => q.MatchIgnoredByUserId == null )
Do not forget to track your query in SQL Profiler :)

Nhibernate SQLQuery as Subquery

How Can use a native sqlquery (session.CreateSqlQuery) as filtering subquery in another QueryOver:
// Get ids
var idsq = _session.CreateSQLQuery(
"select Id from [dbo].[SomeFunction](:parameter)")
.AddEntity(typeof(long)).
SetParameter("parameter", folderId);
// get entities by filtering where in (subquery)
MyEntity entityAlias = null;
var listOfEntities = await _session.QueryOver(() => entityAlias).
Where(x=>x.Id).IsIn(idsq).
OrderBy(x => x.Name).Asc.
ListAsync(cancelToken).ConfigureAwait(false);
You can't easily mix various styles of NHibernate... What you can do:
var crit = new SQLCriterion(SqlString.Parse("{alias}.Id IN (select Id from [dbo].[SomeFunction](?))"),
new object[] { folderId },
new IType[] { NHibernateUtil.Int64 });
and then:
var listOfEntities = await _session.QueryOver(() => entityAlias)
.Where(crit)
.OrderBy(x => x.Name).Asc
Note how I changed the text query adding {alias}.Id IN (...)

translating sql statement to linq

I have a working sql statement and want it as linq statement or linq methode chain.
My statement is:
SELECT T1.*
FROM (SELECT Col1, MAX(InsertDate) as Data
FROM Zugbewegungsdaten
GROUP BY Loknummer) as temp JOIN T1
ON (T1.Col1= temp.Col1
AND Zugbewegungsdaten.InsertDate= temp.Date)
WHERE Col3=1
ORDER BY Loknummer
Can anybody help me to translate it?
Edit after comment:
Ok, my result for the inner select:
var maxResult = (from data in context.T1
group data by data.Col1
into groups
select new
{
Train = groups.Key,
InsertDate= groups.Max( arg => arg.InsertDate)
}) ;
I tried the join like this:
var joinedResult = from data in context.T1
join gdata in maxResult on new
{
data.Col1,
data.InsertDate
}
equals new
{
gdata.Col1,
gdata.InsertDate
}
select data;
But i get a compiler error by the join that the typeargument are invalid.
In the case that the join works i whould use a where to filter the joinedResult.
var result = from data in joinedResult
where data.Col3 == true
select data;
After much more "try and error", I got this version it looks like it works.
var joinedResult = ( ( from data in context.T1
group data by data.Col1
into g
select new
{
Key= g.Key,
Date = g.Max( p => p.InsertDate)
} ) ).Join( context.T1,
temp => new
{
Key = temp.Key,
InsertDate = temp.Date
},
data => new
{
Key = data.Col1,
InsertDate = data.InsertDate
},
( temp,
data ) => new
{
temp,
data
} )
.Where( arg => arg.data.Col3)
.OrderBy( arg => arg.data.Col1)
.Select( arg => arg.data );
Could it be that i have to set the same property names (Key, InsertDate) by joins over multi columns?

How to create list of anonymous types in select clause?

Here is one of queries I am using in my project:
var carQuery = from cars in context.Cars
.Where(c => c.CarID==3)
from stockTypes in context.StockTypes
.Where(st => cars.StockTypeId == st.StockTypeID).DefaultIfEmpty()
from carUnit in context.Car_Units
.Where(cu => cu.CarId == cars.CarID).DefaultIfEmpty()
from carAttributes in context.Car_Attributes
.Where(ca => ca.CarId == cars.CarID).DefaultIfEmpty()
from attribute in context.Attributes
.Where(attr => attr.AttributeId==carAttributes.AttributeId).DefaultIfEmpty()
select new
{
CarID = cars.CarID,
CarName = cars.CarName,
CarDescription = cars.CarDescription,
StockType = (stockTypes == null) ? null : new
{
StockTypeID = stockTypes.StockTypeID,
StockName = stockTypes.StockName
},
IsActive = cars.IsActive,
IsCab = cars.IsCab,
Unit = (carUnit == null) ? null : new
{
Id = carUnit.UnitId,
Name = carUnit.Unit.UnitName
},
Attributes = attribute
};
If the context.Attributes returns multiple rows, the whole resultset also returning multiple rows.
Is there any possibility to return a single car type with multiple attributes as a list of attributes to the car??
Please help.
Thanks,
Mahesh
You just need to move the attribute query inside the result set:
var carQuery = from cars in context.Cars
.Where(c => c.CarID==3)
from stockTypes in context.StockTypes
.Where(st => cars.StockTypeId == st.StockTypeID).DefaultIfEmpty()
from carUnit in context.Car_Units
.Where(cu => cu.CarId == cars.CarID).DefaultIfEmpty()
from carAttributes in context.Car_Attributes
.Where(ca => ca.CarId == cars.CarID).DefaultIfEmpty()
select new
{
CarID = cars.CarID,
CarName = cars.CarName,
CarDescription = cars.CarDescription,
StockType = (stockTypes == null) ? null : new
{
StockTypeID = stockTypes.StockTypeID,
StockName = stockTypes.StockName
},
IsActive = cars.IsActive,
IsCab = cars.IsCab,
Unit = (carUnit == null) ? null : new
{
Id = carUnit.UnitId,
Name = carUnit.Unit.UnitName
},
Attributes =
from attribute in context.Attributes
.Where(attr => attr.AttributeId==carAttributes.AttributeId).DefaultIfEmpty()
.GroupBy(at => at.AttributeId)
select attribute
};

LINQ to SQL query using "NOT IN"

Can LINQ to SQL query using NOT IN?
e.g., SELECT au_lname, state FROM authors WHERE state NOT IN ('CA', 'IN', 'MD')
List<string> states = new List<string> { "CA", "IN", "MD" };
var q = from a in authors
where !states.Contains(a.state)
select new { a.au_lname, a.state };
or
var q = authors.Where( a => !states.Contains( a.state ) )
.Select( a => new { a.au_lname, a.state } );
You can do it with Contains:
var states = new[] {"CA", "IN", "MD"};
var query = db.Authors.Where(x => !states.Contains(x.state));
here's an example:
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where !(from o in dc.Orders
select o.CustomerID)
.Contains(c.CustomerID)
select c;
foreach (var c in query) Console.WriteLine( c );
Yes!
Here's an example from code we already had written:
List<long> badUserIDs = new List { 10039309, 38300590, 500170561 };
BTDataContext dc = new BTDataContext();
var items = from u in dc.Users
where !badUserIDs.Contains(u.FbUserID)
select u;
The generated SQL turns out to be:
{SELECT [t0].[UserID], [t0].[FbUserID], [t0].[FbNetworkID], [t0].[Name],
FROM [dbo].[Users] AS [t0]
WHERE NOT ([t0].[FbUserID] IN (#p0, #p1, #p2))
}