I have a problem with one of my queries using linq 2 entites. I'm trying to view the query before it is generated to the db but without any success. I tried using ToTraceString() but couldn't cause the query could not be cast to ObjectQuery.
this is my query:
var movies = (from m in watchedRepo.GetAll().Where(c => c.iUserId == userId).ToList()
join f in moviePageViewsRepository.GetAll() on m.iMovieId equals f.iMovieId
group f by new JoinClass { MovieId = f.iMovieId, Points = m.iPoints }
into g
orderby g.Key.Points descending , g.Sum(d => d.iScore) descending
select new JoinClass { MovieId = g.Key.MovieId, Points = g.Key.Points, PageViews = g.Sum(d => d.iScore) }).Skip(skip).Take(take);
if I try to execute it from linq I get an out of memory exception.
any ideas please?
The problem is with your ToList() in the first line of your query. This will immediately fetch all rows from wachtedRepo with the specified UserId.
Because your query will then become a hybrid Linq to Entities / Linq to Objects, you can't cast to an ObjectQuery. Is your query still working when you remove ToList()?
If you want to see what's really happening in your Sql Server, I would suggest using the Sql Server Profiler tools to view your queries.
Assuming watchedRepo is the Linq to SQL object representing the database connection
watchedRepo.Log = Console.Error;
All SQL queries will be printed to standard error.
Related
I have a SQL query that basically joins the MyWords table to the MyTranslations table on two keys. Here are my tables for better understanding.
MyWords table:
Id
WordString
LangType
MyTranslations table:
Id
WordColumnAId
WordColumnBId
Please note that WordColumnAIdand WordColumnBId columns are FKs that represents the MyWords.Id.
My SQL query:
SELECT MyTranslations.Id
,WordColumnAId
,WordColumnBId
,MyWords.WordString
,MyWords.LangType
FROM MyTranslations
join MyWords on (MyTranslations.WordColumnAId = MyWords.Id or MyTranslations.WordColumnBId = MyWords.Id)
where MyWords.LangType !=#currentLangType
I know it doesn't make sense to use join on with multiple keys at first glance but I'm trying to a cross-query that would join two tables whether the key is on WordColumnAId or WordColumnBId.
Problem
I'm trying to adapt the above T-SQL query into a LinQ query. The problem is that I can't find my way around LinQ to use two keys in a single join query.
Here's what I've got so far:
from translation in queryableTranslation
join word in _myWordRepository on translation.WordColumnAId equals word.Id // This is where I want to add `or translation.WordColumnBId equals word.Id` but get errors.
where word.LangType != currentLangType
select new QueryResultDto {
MyTranslationId = translation.Id,
WordString = word.WordString,
LanguageType = word.LangType,
WordColumnAId = translation.WordColumnAId,
WordColumnbId=translation.WordColumnbId,
};
I'm very new to the LinQ and trying to learn.
So my question: is there a way to achieve this in LinQ or am I trying the impossible? I'm also open to better approaches.
EF and other LINQ providers should translate query to INNER JOIN when using this syntax:
var query =
from translation in queryableTranslation
from word in _myWordRepository.Where(word => translation.WordColumnAId == word.Id
|| translation.WordColumnBId = word.Id)
where word.LangType != currentLangType
select new QueryResultDto
{
MyTranslationId = translation.Id,
WordString = word.WordString,
LanguageType = word.LangType,
WordColumnAId = translation.WordColumnAId,
WordColumnbId=translation.WordColumnbId,
};
I want convert following LINQ query to SQL query.
var ACTIVITY_ROYALITY_MONTH = from m in db.MiningPermit
join pm in db.Permit_Mineral on m.MINING_PERMIT_ID equals pm.MINING_PERMIT_ID
join r in db.Royality on pm.Permit_Minerals_ID equals r.Permit_Minerals_ID
where r.ORDER_ID == 0 // NULL in server
orderby r.YEAR, r.MONTH
group r by new { m.MINING_PERMIT_ID , r.YEAR, r.MONTH } into mpmr
select mpmr.ToList();
Use Linqpad and recreate the linq (even by bringing in your assemblies) in a C# query. Run the query. Then in the output, there is a selection button of SQL which will show the sql code.
In LINQ, I am trying to inner join custom function written for full-text search and an Iqueryable result.
However, I get the following error when I try to to_ret.select(--something--).ToList()
Nested query does not have appropriate key
LINQ Code:
var sql_query = db.search(st);
var to_ret = from ts in sql_query
from t in table
where t.Id == ts.Value select t;
to_ret = to_ret.Include(x => x.table1)
.Include(x=> x.table2.Select(y=> y.table2Col));
to_ret.select(-something-).toList();
SQL Code:
create function [dbo].[search]
(#keywords nvarchar(4000))
returns table
as
return (
select [key] from containstable(tb,(Name,Description),#keywords)
)
Code that works in place of above LINQ Code :
var ids = (from t in table join ts in db.search(st) on t.Id equals ts.Value select t.Id).ToList();
to_ret = to_ret.Where(x => ids.Contains(x.Id));
However, the code that works isn't efficient enough as it eagerly loads all the ids for comparison
Do not join the table using LINQ, it is not effective.
You need to include all the joined functions into [dbo].[search] table valued function (like a view). Then do just call the [dbo].[search] from EF and filter it.
I have mentioned joined Fulltext table valued function here.
Note that fulltext and filtering together in one query could take time, because it is not easy job for query optimizer. Query optimizer selects to perform first fulltext on entire table(s) and then filtering or the opposite way.
I am using NHibernate and LINQ to SQL and I want to convert the following SQL query:
select min(T."CustomerName") from public."Jobs" as T group by lower(T."CustomerName");
I want to convert it in LINQ to SQL and add it in a DAO.
Please help.
At last I have found the answer.
Here it is:
return HibernateTemplate.Execute(session => (from r in session.Query<Job>()
group r by r.CustomerName.ToLower()
into g
let c = g.Min(l => l.CustomerName)
orderby c
select c)).ToList();
Thank you people.
Dim query = (From p in Parent _
select _
p.ID, _
Tags = String.Join("|", p.Child.Select(Function(c) c.Tag.TagName).ToArray)).Take(100)
In the above query, when using Take to limit the rows returned, a separate SQL query is executed for each row to return the 'Tags' field. If I remove Take(100), a single query to sent to Sql Server.
So, how do I limit the number of rows returned, while preventing a new sub query being executed for each row?
edit2
When working with nested types, so doing new { r, r.childrenCollection }, LINQ translates this to (SELECT TOP 100 FROM r), deleting the join information. When doing a join by yourself this doesn't happen. So something like:
var thingyWithChilds
= (from p in dc.RightCategories
join r in dc.Rights on p.Id equals r.CategoryId
select new { p.Id, r });
var bla = thingyWithChilds.Take(100);
will not cause the same problem.
other stuff that might apply
You're doing ToArray() which causes the query to execute as it isn't a IQueryable. Just do ToArray() after you do Take().
edit According to this SO topic: Is there a LINQ equivalent of string.Join(string, string[]), it is neither possible to use String.Join if you want to do everything on the server, as there is no SQL command available to do that in TSQL.