Table 1: Lookups
LookUpID
LookUpName
Desc
DisplayOrder
Table 2: BillingRates
BillingRateID
BillingRate
ClientID
LookupID
I want the lookup name to be displayed (sort by Bill rate)
DataContext DataContext1 = new DataContext1(AppSettings.ConnectionString);
return ( from Lookups in DataContext1.Lookups
join BillingRates in DataContext1.BillingRates
on Lookups.LookupID equals BillingRates.LookupID
orderby BillingRates.BillingRate
select new
{
Lookups.LookupID,
Lookups.LookupName,
Lookups.Desc
}).Distinct();
It gave me all the row, so I used Distinct(); The lookup Name is still not based on billing rate.
I am new to LINQ. Any pointers would be appreciated.
Why not just do the OrderBy at the end?
return (from Lookups in DataContext1.Lookups
join BillingRates in DataContext1.BillingRates
on Lookups.LookupID equals BillingRates.LookupID
select new
{
Lookups.LookupID,
Lookups.LookupName,
Lookups.Desc,
BillingRates.BillingRate
})
.GroupBy(x => x.LookupID)
.Select(y => y.OrderByDescending(x => x.BillingRate).First())
.OrderByDescending(x => x.BillingRate);
EDIT: I am kind of confused but try the following and let me know if that helps.
First of all, if you have a foreign key relationship set up, LINQ will create the join for you automatically, so it would be just:
DataContext1.Lookups.Max(LkUp => LkUp.BillingRate.BillingRate)
Otherwise, (with the explicit join)
return ( from Lookups in DataContext1.Lookups
join BillingRates in DataContext1.BillingRates
on Lookups.LookupID equals BillingRates.LookupID
orderby BillingRates.BillingRate desc
select new
{
Lookups.LookupID,
Lookups.LookupName,
Lookups.Desc,
BillingRates.BillingRate
}).First();
Related
I have a linq query which gave me the warning but it still works. I want to get rid of the warning.
uses First/FirstOrDefault/Last/LastOrDefault operation without OrderBy and filter which may lead to unpredictable results.
The linq query is
var list = (from u in _db.user
join r in _db.resource on u.userId equals r.userId
join t in _db.team on u.bossId equals t.bossId
where r.pid == pid
select new MyDto
{
pid = pid,
userId = u.userId,
teamId = t.teamId,
name = t.name
}).GroupBy(d => d.userId).Select(x => x.First()).OrderBy(y => y.userId).ToList();
I use EntityFramework Core 2.1
UPDATE:
I changed the code by the comments.
var list = (from u in _db.user
join r in _db.resource on u.userId equals r.userId
join t in _db.team on u.bossId equals t.bossId
where r.pid == pid
select new MyDto
{
pid = pid,
userId = u.userId,
teamId = t.teamId,
name = t.name
})
.GroupBy(d => d.userId)
.Select(x => x.OrderBy(y => y.userId)
.First())
.ToList();
Then there is a different warning.
The LINQ expression 'GroupBy([user].userId, new MyDto() {pid =
Convert(_8_locals1_pid_2, Int16), userId = [user].UserId, .....) could
not be translated and will be evaluated locally.
We have this expression
.Select(x => x.First())
Which record will be first for that expression? There's no way to know, because at this point the OrderBy() clause which follows hasn't processed yet. You could get different results each time you run the same query on the same data, depending on what order the records were returned from the database. The results are not predictable, exactly as the error message said.
But surely the database will return them in the same order each time? No, you can't assume that. The order of results in an SQL query is not defined unless there is an ORDER BY clause with the query. Most of the time you'll get primary key ordering (which does not have to match insert order!), but there are lots of things that can change this: matching a different index, JOIN to a table with a different order or different index, parallel execution with another query on the same table + round robin index walking, and much more.
To fix this, you must call OrderBy() before you can call First().
Looking a little deeper, this is not even part of the SQL. This work is happening on your client. That's not good, because any indexes on the table are no longer available. It should be possible to do all this work on the database server, but selecting the first record of a group may mean you need a lateral join/APPLY or row_number() windowing function, which are hard to reproduce with EF. To completely remove all warnings, you may have to write a raw SQL statement:
select userId, teamId, name, pid
from (
select u.userId, t.teamId, t.name, r.pid, row_number() over (order by u.userId) rn
from User u
inner join resource r on r.userId = u.userId
inner join team t on t.bossId = u.bossId
where r.pid = #pid
) d
where d.rn = 1
Looking around, it is possible to use row_number() in EF, but at this point I personally find the SQL much easier to work with. My view is ORMs don't help for these more complicated queries, because you still have to know the SQL you want, and you also have to know the intricacies of the ORM in order to build it. In other words, the tool that was supposed to make your job easier made it harder instead.
Actually,I'm using 2 tables like GREETING_TRANSACTIONS and COUNTRIES.
In the COUNTRIES table I'm maintaining list of CountryShortCode and CountryFullName.
While sending the Greetings,I'm saving CountryCodes in , separated way in GREETING_TRANSACTIONS.For Example : IN,MY,CN for India, Malaysia and China.
Now what I'm doing is : First I'm getting the list of GREETING_TRANSACTIONS using this query
var Messages =
(
from u in obj.GREETING_TRANSACTIONS
orderby u.SENT_DATE descending
select new
{
u.ID,
u.COUNTRIES,
u.TITLE,
u.MESSAGE,
u.SENT_DATE,
u.GREETING_TYPE,
u.CATEGORY_NAME
}
).ToList();
and later getting each item and splitting the COUNTRIES column and getting the related CountryFullName using CountryShortCode and preparing a DataTable and binding to the GridView.
is it possible to do everything in a single query using Joins?
may be something like :
var Messages1 =
(
from u in obj.GREETING_TRANSACTIONS
join c in obj.COUNTRY_MASTER
on u.COUNTRIES.Split(',') equals c.COUNTRY_SHORTNAME
orderby u.SENT_DATE descending
select new
{
u.ID,
u.COUNTRIES,
u.TITLE,
u.MESSAGE,
u.SENT_DATE,
u.GREETING_TYPE,
u.CATEGORY_NAME,
c.COUNTRY_FULLNAME
}
).ToList();
I'm new to Linq and found this very difficult.
is it possible to query data by taking comma separated ShortCodes and generating Fullnames?
do I need to use sub queries?
The problem you have is that you can't do a join query on a split. You need to make a SelectMany out of it.
So, given that the list of countries would be really quite small then the easy way is to create a look-up.
Keep your Messages query an then do this:
var lookup = obj.COUNTRY_MASTER
.ToDictionary(x => x.COUNTRY_SHORTNAME, x => x.COUNTRY_FULLNAME);
var Messages1 =
(
from m in Messages
from c in m.COUNTRIES.Split(',')
where lookup.ContainsKey(c)
orderby m.SENT_DATE descending
select new
{
m.ID,
m.COUNTRIES,
m.TITLE,
m.MESSAGE,
m.SENT_DATE,
m.GREETING_TYPE,
m.CATEGORY_NAME,
COUNTRY_FULLNAME = lookup[c],
}
).ToList();
As per the comment below:
var Messages1 =
(
from m in Messages
orderby m.SENT_DATE descending
select new
{
m.ID,
m.COUNTRIES,
m.TITLE,
m.MESSAGE,
m.SENT_DATE,
m.GREETING_TYPE,
m.CATEGORY_NAME,
COUNTRY_FULLNAME = String.Join(
", ",
m.COUNTRIES
.Split(',')
.Where(x => lookup.ContainsKey(x))
.Select(x => lookup[x])),
}
).ToList();
Using a comma separated list as a data field is not a good idea. You need an extra many-to-many table linking GREETING_TRANSACTIONS and COUNTRIES.
I'm having trouble using LINQ method calls with multiple joins. I'm trying to do something like this:
if (!isDepSelect)
{
query = (from Items in db.DEPARTMENTs
select Items);
}
else
{
query = (from Items in db.DEPARTMENTs
from gDept in db.DEPT_PROFILE
from wAccess in db.WEB_ACCESS
where Items.DEPT_CODE == gDept.DEPT_CODE && gDept.USER_ID == wAccess.USER_ID && wAccess.EMP_ID == id
select Items);
}
I had done this:
IQueryable<DEPARTMENT> query = db.DEPARTMENTs;
if (isDepSelect)
{
query = query.Join(db.DEPT_PROFILE,depts => depts.DEPT_CODE,prof => prof.DEPT_CODE,(depts, prof) => depts);
}
But now I don't know how to add the JOIN of DEPT_PROFILE table with the WEB_ACCESS table and the condition of the EMP_ID = id.
The reason I'm doing this is that the isDepSelect boolean is not the only condition that this query will change its relations and I need someway to add this relations without repeating my LINQ for each of my conditions.
Thank you for your time.
Try with,
List<DEPARTMENTs> list = db.DEPARTMENTs.Join(db.DEPT_PROFILE, dept => dept.DEPT_CODE, prof => prof.DEPT_CODE, (dept,prof) => new {dept, prof})
.Join(Wdb.WEB_ACCESS, depts => depts.prof.USER_ID,web => web.USER_ID,(depts,web) => new { depts, web})
.Where(result => result.web.EMP_ID== id).Select(s => s.depts.dept).ToList<DEPARTMENTs>();
If you have your associations setup, you can do this without any joins in your code at all:
query = db.DEPARTMENTs
.Any(item => item.DEPT_PROFILEs
.Any(gDept => gDept.WEB_ACCESSs
.Any(wAccess => wAccess.EMP_ID == id)));
Of course this is assuming a 1-m relationship between each of the objects in the graph. You can eliminate some of the Any methods if there are 1-0..1 relationships in the graph as necessary.
you should use the equals operator...
query = from Items in db.DEPARTMENTs
from gDept in db.DEPT_PROFILE
join wAccess in db.WEB_ACCESS on
gDept.DEPT_CODE equals Items.DEPT_CODE
select Items;
thats just a snippet of your example query, but you can see how i am using the join operator to introduce a 2nd table and the equals operator to declare the joining columns.
This should work:
query = (from Items in db.DEPARTMENTs
join gDept in db.DEPT_PROFILE
on Items.DEPT_CODE equals gDept.DEPT_CODE
join wAccess in db.WEB_ACCESS
on gDept.USER_ID equals wAccess.USER_ID
where wAccess.EMP_ID == id
select Items);
am stuck with this linq query, all i need is to optimize the last price calculation, cause i get about a 1000 article, & a lot of sales so its getting slow ...
var result = from article in db.Entities.Articles
select new{
article.ID_ART,
article.Designation,
article.BuyPrice,
article.SellPrice,
LastPrice = (from sale in article.Sales where sale.Date == article.Sales.Max(X => X.Date) select sale.Price).FirstOrDefault()==0?
article.BuyPrice: (from sale in article.Sales where sale.Date == article.Sales.Max(X => X.Date) select sale.Price).FirstOrDefault()
}
var result = from article in db.Entities.Articles
let lastPrice = (from sale in article.Sales
orderby sale.Date descending
select sale.Price).FirstOrDefault()
select new
{
article.ID_ART,
article.Designation,
article.BuyPrice,
article.SellPrice,
LastPrice = lastPrice ==0 ? article.BuyPrice : lastPrice
}
You should either join or Include Sales. I assume since it's a navigation property on article that it's an FK table.
Simply use from article in db.Entities.Articles.Include("Sales")... instead.
That will load sales for reference and prevent it from running a subquery when initializing the anonymous type.
Here is situation I have been trying to solve
Lets take a Employee table
Create Table Employee
(
Employeeid int primary key,
EMPname varchar(50),
ManagerEmplId int reference key Employee (EmployeeID)
TreeLevel int,
....
)
Here i need to find all leaf level employees.
Leaf Level Employees - All employees who have manager but they do not have anybody reporting to them. I have a little help from db which has TreeLevel column where I can specify pick anybody at level 3 but I need a UNIONclause which will get me all employees at treelevel 2 that do not have any employees reporting.
I have only 3 levels of tree if that helps in creating linq query.
return ((from b in _db.Employees
&& b.TreeLevel==3 && b.DeletedDate== null
select b)
.Union
(from b in _db.Employees
select b)
)
.ToDictionary(k => k.EmployeeID, v => v.EMPname);
UPDATE:
The real query:
(from fi in firm
join bra in _db.Branches on fi.BranchID equals bra.ParentBranchID into g
from sc in g.DefaultIfEmpty()
where fi.DeletedDate == null && g == null
select fi)
.ToList()
.ToDictionary(k => k.BranchID, v => v.BranchName);
Error:
Cannot compare elements of type 'System.Collections.Generic.IEnumerable`1'.
Only primitive types (such as Int32, String, and Guid) and entity types are supported.
You can try the right outer join and make sure that the left side is empty.
In this post How to do a full outer join in Linq? you can find a good example of how to do it in linq.
from b in _db.Employees
from c in _db.Employees.Where(o=> o.ManagerEmplId == b.Id).DefaultIfEmpty()
where c == null
This query should do the trick, regardless of tree depth:
var leafEmps =
(from emp in _db.Employees
where !_db.Employees.Any(e => e.ManagerEmplId == emp.EmployeeId)
select emp);
var managersids = _db.Employees.Select(emp => emp.ManagerEmplId ).Distinct();
var leafemps = _db.Employees.where(emp => !managersids.contains(emp.Employeeid));
To do this simple, get all the managers and then search the people who arn't a manager
var leafemps = from emp in _db.Employees
let managersids = _db.Employees.Select(emp => emp.ManagerEmplId ).Distinct()
where !managersids.contains(emp.Employeeid)
select emp