EF query to fluent nhibernate query - asp.net

I have EF Query:
IEnumerable<Account> accounts
= (
from a in dc.Accounts
join m in dc.GroupMembers on a.AccountID equals m.AccountID
where m.GroupID == GroupID && m.IsApproved
select a)
.Skip((_configuration.NumberOfRecordsInPage * (PageNumber - 1)))
.Take(_configuration.NumberOfRecordsInPage);
How to write it in fluent nhibernate query with Session.CreateCriteria<>?
(My problem is with Join)

There's a good answer by phill here - NHibernate QueryOver with ManytoMany which has an example of join with QueryOver
var result = Session.QueryOver<Product>()
.Right.JoinQueryOver<Category>(x => x.Categories)
.Where(c => c.Id == categoryId)
.List();
He also describes how to use linq with query over:
var users = from u in session.Query<Users>()
where u.UserName == "Abcd"
&& u.Password == "123456"
select u;
So applying the above examples to your query somethign like this might work:
(from a in session.Query<Account>()
join m in session.Query<GroupMember>() on a.AccountID equals m.AccountID
where m.GroupID == GroupID && m.IsApproved
select a).Skip((_configuration.NumberOfRecordsInPage * (PageNumber - 1)))
.Take(_configuration.NumberOfRecordsInPage);
However, to help better understand the issue you are having, could you post what you have attemtpted?

Related

How express SQL left join with IS NULL in LINQ

I'm trying to write a LINQ equivalent of the following SQL:
SELECT i.ItemID, i.ItemName
FROM Items AS i
LEFT JOIN BillOfMaterials AS bom ON bom.ItemID = i.ItemID
WHERE bom.ItemID IS NULL
This returns a set of items where the itemid does not appear in the BillofMaterials.ItemID column.
I've tried the following which (not surprisingly) doesn't work:
from i in ctx.Items
join b in ctx.BillOfMaterials on i.ItemID equals b.ItemID
into joinedTable
from j in joinedTable.DefaultIfEmpty().Where(w => w.ItemID == null)
select new
{
i.ItemID,
i.ItemName
};
Since you don't seem to be interested here in the actual BOM objects, only if they exist or not, I would recommend using an expression with just an existence check:
from i in ctx.Items
where !ctx.BillOfMaterials.Any(b => i.ItemID == b.ItemID)
select new
{
i.ItemID,
i.ItemName
};
It is shorter, and it describes better what you are checking for. Also depending on how smart EF is (or not), it could even be more efficient because the BillOfMaterials data will never be loaded into .NET memory as BillOfMaterial objects.
WHERE bom.ItemID IS NULL in sql corresponds to j == null in Linq.
Where(w => w.ItemID == null) will not work here, because the w was null and an exception was thrown.
The right syntax for the left join Linq is like :
from i in ctx.Items
join b in ctx.BillOfMaterials on i.ItemID equals b.ItemID into joinedTable
from j in joinedTable.DefaultIfEmpty()
where j == null
select new
{
i.ItemID,
i.ItemName
};
I hope you find this helpful.

Select data from multiple table with Entity Framework

I am able to select data from two tables, But I am getting partial result only while retrieving data from three tables.
var items = from orders in nobleappDbContext.JobOrders.Where(m => m.OrderStat == 0)
join users in nobleappDbContext.users on orders.Uid equals users.Uid
join customers in nobleappDbContext.customers on users.Uid equals customers.Uid into customdata
from m in customdata.DefaultIfEmpty()
select new
{
Eid = orders.Eid,
Uid = orders.Uid,
OrderStat = orders.OrderStat,
Name = m.Name,
Contact = (m.Contact == null) ? 0 : m.Contact
};
return Ok(items);
With this code, I am getting only result (common result) from users table and I am looking for something like UNION or OUTER JOIN.
Any help will be highly appreciated
finally I got exactly what I was looking for, here by posting the answer as I might help someone looking for same. LEFT JOIN with Entity Framework is the key
var query = from a in authurs
join b in books on a.Id equals b.AuthorId into auth_books
from left in auth_books.DefaultIfEmpty()
join bs in booksSeries on left.BookSeriesId equals bs.Id into books_bookseries
from left2 in books_bookseries.DefaultIfEmpty()
select new
{
Author = a.Name,
Book = left.Name,
BookSeries = left2.Description
};
var resList2 = query.ToList();
refer this link for further clarification.

Outer joins with where condition x++

I am trying to write a query that retrieves an item based on ItemId or item barcode.
This is using x++, Dynamics AX 2012 R2
select firstOnly * from inventTable
where (inventTable.ItemId == _upc || inventItemBarcode.itemBarCode == _upc)
outer join inventItemBarcode
where inventItemBarcode.itemId == inventTable.ItemId;
When this is translated into sql it comes out as...
FROM INVENTTABLE T1 LEFT
OUTER
JOIN INVENTITEMBARCODE T2 ON (((T2.PARTITION=?)
AND (T2.DATAAREAID=?))
AND (T1.ITEMID=T2.ITEMID))
WHERE (((T1.PARTITION=?)
AND (T1.DATAAREAID=?))
AND (T1.ITEMID=?))
You can see that is is totally omitting the OR condition in the last line.
I tried writing the query like this
select firstOnly * from inventTable
outer join inventItemBarcode
where
//join
inventItemBarcode.itemId == inventTable.ItemId
//ilc
&& (inventTable.ItemId == _upc
|| inventItemBarcode.itemBarCode == _upc);
But it puts the OR condition in the outer join ON and then returns me the first row in the InventTable.
Does anyone know how to make this work in X++?
If using AX 2012 you will have to use Query and QueryRun instead, then add your or-expression as a query expression using addQueryFilter.
static void Job117(Args _args)
{
str search = "5705050765989";
QueryRun qr = new QueryRun(new Query());
QueryBuildDataSource ds1 = qr.query().addDataSource(tableNum(InventTable));
QueryBuildDataSource ds2 = ds1.addDataSource(tableNum(InventItemBarcode));
str qstr1 = '((%1.%2 == "%5") || (%3.%4 == "%5"))';
str qstr2 = strFmt(qstr1, ds1.name(), fieldStr(InventTable,ItemId),
ds2.name(), fieldStr(InventItemBarcode,ItemBarCode),
queryValue(search));
qr.query().addQueryFilter(ds1, fieldStr(InventTable,ItemId)).value(qstr2);
ds2.joinMode(JoinMode::OuterJoin);
ds2.relations(true);
info(qstr2);
info(ds1.toString());
while (qr.next())
info(strFmt("%1", qr.getNo(1).RecId));
}
In prior AX versions you can make a view, then query the view using a query expressions by using the addRange method.

Unable to create a constant value of type 'X.Models.Game'. Only primitive types or enumeration types are supported in this context

I've got a complex query written in SQL which works.
SELECT Instruments.Id as [Id], Instruments.ShareCode as [Share Code], Instruments.Name AS [Short Name], Instruments.Description as [Share Name],
InstrumentGames.Instrument_Id,
InstrumentGames.Game_Id, Games.Name AS [Game Name],
Entries.Name AS [Entry Name], AspNetUsers.UserName, AspNetUsers.Id as [User_Id],
Sectors.Name AS Sector_Id, Sectors.ShortName AS Sector
FROM AspNetUsers INNER JOIN
Entries ON AspNetUsers.Id = Entries.User_Id INNER JOIN
Games ON Entries.Game_Id = Games.Id INNER JOIN
InstrumentGames ON Games.Id = InstrumentGames.Game_Id INNER JOIN
Instruments ON InstrumentGames.Instrument_Id = Instruments.Id INNER JOIN
Sectors ON Instruments.Sector_Id = Sectors.Id
WHERE Instruments.Listed = 'true' and InstrumentGames.Game_Id = 2 and Entries.User_Id = 'd28d6552-7d98-476c-82cb-063e7ef45cb6'
I'm using Entity code first models and trying to convert what I have in SQL to a linq query.
I've come up with:
public static Models.Instrument GetShare(string shareSearchCriteria,
Models.Game selectedGame,
string userId)
{
var _db = new JSEChallenge.Models.ApplicationDbContext();
var records = (from instru in _db.Instruments
from e in _db.Entries
where (instru.ShareCode.Contains(shareSearchCriteria) ||
instru.Name.Contains(shareSearchCriteria) ||
instru.Description.Contains(shareSearchCriteria))
where (instru.Listed == true &&
instru.Games.Contains(selectedGame) &&
e.User_Id == userId)
select instru).ToList();
return records.FirstOrDefault();
}
But I keep getting this error:
Unable to create a constant value of type 'X.Models.Game'. Only primitive types or enumeration types are supported in this context.
I think the issue is the m2m table InstrumentGames. In my SQL query I can join it easily but in my C# I cannot. The way I usually find m2m records is syntax like instru.Games.Contains(selectedGame)
Unfortunately I still cannot get this to work.
How do I implement this kind of query in Linq?
Not sure if it will work, but try instru.Games.Any(q => q.Id == selectedGame.Id) instead of instru.Games.Contains(selectedGame).
Hope this helps!

LINQ - EF join difficulty

I have two tables:
Phase :
long ID
string Name
and another Activity :
long ID
string Name
long PhaseID
I already know the name of the phases and I want to get the activity for those particular phases. Do i add PhaseName to the activity table or do I do it through join in LINQ?
Maybe something like this?
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
... and here im not sure how to finish this query..
Thanks for your help!
The code that you've provided will use an Inner Join to find all Activities where the Phase with Name "Preplanning" exists.
To finish your query you need to add a select clause.
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
select a.Name
will return IEnumerable<string> of all activity names.
Just select activity, as you want:
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
select a;
Here is how query expression should look like:
A query expression must begin with a from clause and must end with a select or group clause. Between the first from clause and the last select or group clause, it can contain one or more of these optional clauses: where, orderby, join, let and even additional from clauses. You can also use the into keyword to enable the result of a join or group clause to serve as the source for additional query clauses in the same query expression.
Same as puzzling image:
With method syntax you don't need to end query with something special:
var query = entities.Phases
.Where(p => p.Name == "Preplanning")
.Join(entities.Activities, p => p.Id, a => a.PhaseId, (p,a) => a);
No need to do a join if you only need data from one of the tables. You can apply a filter instead:
var q = entities.Activities.Where(a =>
entities.Phases.Any(p => a.PhaseId == p.Id && p.Name == "Preplanning"));

Resources