sql to linq with left join - linq

i have create a request in SQL and put them in dataset. apparently it hang when the data very huge. so i use an Entity.
my original sql is like this:
SELECT NO_ORDRE,ORDRE.CODE_DEST as CODE_DEST,REF_EXPED,ORDRE.MODAL_MODE,RS_NOM,ADRESSE,TEL,VILLE,
ORDRE.NBR_COLIS,ORDRE.POID,DATE_CREE,DATE_CLOTUR,STATUT_ORDRE,ORDRE.TRANSPORTEUR,ORDRE.LIB_TOURNE,
ORDRE.DATE_CLOTUR_REEL,ORDRE.OBS,AUTRE_REF,
ORDRE.CODE_CLIENT+'_'+CAST(NOID as VARCHAR(50))+'_'+SUBSTRING(NO_ORDRE_CUMMUL, 0, CHARINDEX('_', NO_ORDRE_CUMMUL + '_')) as NOLV
FROM ORDRE
LEFT OUTER JOIN LETTRE_VOIT_FINAL
ON charindex('_'+cast(ORDRE.NO_ORDRE as varchar(255))+'_', '_'+LETTRE_VOIT_FINAL.NO_ORDRE_CUMMUL+'_') > 0
WHERE DATE_CREE BETWEEN #DATE_CREE_DEB AND #DATE_CREE_FIN
ORDER BY NO_ORDRE DESC
and i try my linq like this:
public IQueryable<ORDRE> Get_OrdreEntity(DateTime datedeb, DateTime datefin)
{
try
{
IQueryable<ORDRE> LesListe;
Soft8Exp_ClientEntities oEntite_T = new Soft8Exp_ClientEntities();
var query = from o in oEntite_T.ORDRE
where o.DATE_CREE >= datedeb && o.DATE_CREE <= datefin
select o;
LesListe = query;
return LesListe;
}
catch (Exception excThrown)
{
throw new Exception("Err_02", excThrown);
}
}
it works well but i don't know how to make a join from this sql:
LEFT OUTER JOIN LETTRE_VOIT_FINAL
ON charindex('_'+cast(ORDRE.NO_ORDRE as varchar(255))+'_', '_'+LETTRE_VOIT_FINAL.NO_ORDRE_CUMMUL+'_') > 0
and how can i translate it to linq from this sql:
ORDRE.CODE_CLIENT+'_'+CAST(NOID as VARCHAR(50))+'_'+SUBSTRING(NO_ORDRE_CUMMUL, 0, CHARINDEX('_', NO_ORDRE_CUMMUL + '_')) as NOLV

I can't see any reason to have exception handling in the Get_OrdreEntity function. It should be coded in way it just work. Debug it. In any way you do nothing in catch.
I you query and filter data in this function and want to get results it is a good idea to return collection instead of query in the result of this function to eliminate performance and side effect isssues. I.e. return IEnumerable, ICollection, IList wherether you want.
It is easy to find a ton of Linq join examples, just use Google. Here is all you need.

Related

C# Linq orderby only works for fields returned?

I want to do a Linq query that joins three tables, but only returns data from two of them (the third is only joined for ordering purposes). I'm trying to order by columns that aren't in the output of the produced query, but they seem to be ignored:
var records = from q in _pdxContext.Qualifier
join aql in _pdxContext.ApplicationQualifierLink on q.Id equals aql.QualifierId
join qt in _pdxContext.QualifierType on q.QualifierTypeId equals qt.Id
where SOME_LIST.Contains(aql.ApplicationId)
orderby aql.Sequence
select new Qualifier
{
Id = q.Id,
QualifierType = new QualifierType
{
Id = qt.Id, Value = qt.Value
}
};
return records.Distinct().ToList();
The output SQL from this does NOT have an ORDER BY clause.
If I change the orderby to read like so:
orderby q.Id
... then the output SQL has the order by clause.
Does Linq ignore orderby statements when the mentioned columns aren't used in the output (as appears to be the case here)? If so, how do I order by columns not in the output?
It seems this is an SQL limitation. The error from the SQL Server engine:
"ORDER BY items must appear in the select list if SELECT DISTINCT is specified."
So, as written, I can't do what I want to do.
I ended up using:
using (var cnn = new SqlConnection(_connectionString))
{
string sql = #"select
min(q.Id) Id, q.QualifierTypeId, q.QualifierTypeId, min(q.AcaId) AcaId,
q.QualifierTypeId Id, qt.Value
from
qdb.Qualifier q
inner join qdb.QualifierType qt on qt.Id = q.QualifierTypeId
inner join ApplicationQualifierLink l on l.QualifierId = q.id
where l.ApplicationId in (" + string.Join(",", applicationIds) + #")
group by q.Text, q.QualifierTypeId, qt.Value";
qualifiers = cnn.Query<Qualifier, QualifierType, Qualifier>(sql,
(qualifier, type) =>
{
qualifier.QualifierType = type; return qualifier;
}
).ToList();
}
Note: When you attempt to use order by and distinct as in my original clause, no error is given, entity framework silently discards the order by without any error.

Linq Left Outer Join Two Tables on Two Fields

How do I left outer join two tables on two fields in linq?
I have a sql:
select a.*, b.* from courselist as a
left outer join Summary as b
on a.subject = b.Subject and a.catalog =
b.Catalogno
where a.degree_id = 1
order by a.sequenceNo
Below is my linq query, but there is error underline "join", failed in the call to "Groupjoin". I don't know how to correct that.
var searchResults = (from a in db.courselist
join b in db.Summary on
new { a.subject,a.catalog } equals
new { b.Subject, b.Catalogno } into ab
where a.degree_id == 1
orderby a.degree_sequenceNo
from b in ab.DefaultIfEmpty()
select new
{
Courselist = a,
Summary = b
}
).ToList();
Thanks.
I've checked your code again,
I found it's fault
you just need to specify join parameters name like this:
new { suject = a.subject, catalog = a.catalog } equals
new { suject = b.subject, catalog = b.Catalogno } into ab
It seems you are missing the reference, the query doesn't have an error
try to use this:
using System.Linq;
The main issue when people start using LINQ is that they keep thinking in the SQL way, they design the SQL query first and then translate it to LINQ. You need to learn how to think in the LINQ way and your LINQ query will become neater and simpler. For instance, in your LINQ you don't need joins. You should use Associations/Navigation Properties instead. Check this post for more details.
There should be a relationship between courselist and Summary, in which case, you can access Summary through courselist like this:
var searchResults = (from a in db.courselist
where a.degree_id == 1
orderby a.degree_sequenceNo
select new {
Courselist = a,
Summary = a.Summary
}).ToList();
If there is no relationship between the two, then you should reconsider your design.

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<AnonymousType#1>' to 'System.Linq.IQueryable'

I want to define a function containing a Linq query as bellow:
public IQueryable GetBasket(Guid userId)
{
DabbaghanDataContext db = new DabbaghanDataContext();
int rowNo = 0;
var query = (from c in db.Carts
join co in db.CartOrders on c.Id equals co.Cart_Id
join p in db.Products on co.Product_Id equals p.Id
where c.UserId == userId && c.Issued == false
select new
{
co.Quantity,
co.TotalPrice,
p.Code,
p.Price,
p.Thumbnail
}).AsEnumerable().Select(r => new
{
RowNumber = ++rowNo,
Quantity = r.Quantity,
TotalPrice = r.TotalPrice,
Code = r.Code,
Price = r.Price,
Thumbnail = r.Thumbnail
});
return query;
}
I get error
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Linq.IQueryable'.
on the return query line.
What is the problem? How can I solve this problem? Please help.
Your problem is the call to AsEnumerable- It converts the IQueryable to a IEnumerable; and therefore, you cannot return it as an IQueryable.
Correct me if I am wrong, but the second select seems to only add the row number to the result. You might as well want to do that together with the initial select, and skip the call to AsEnumerable().
Possible solutions: Rewrite the query to not use AsEnumerable (if you want an IQueryable returned), or you could change the return type to be IEnumerable, if that is a better fit for your problem.
In return query; change that to return query.AsQueryable();
And also try to change the method signature to use IQueryable instead of the nongeneric one

LINQ to NHibernate (3.0) : GroupBy and Sum in subquery gives NoTImplemented

I have a Linq query using NHibernate 3.0. But it keeps returning an error.
threw exception: System.NotImplementedException: The method or operation is not implemented..
I tried the same in LINQ 2 SQL and it works perfectly.
What might be wrong here? Here is part of my select, it's a subquery with a Groupby and Sum.
Amount = (System.Double)
((from m0 in _session.Query<Statement>()
where m0.Code== c.Code
group m0 by new
{
m0.Code
}
into g
select new
{
Expr1 = (System.Double)g.Sum(p => p.Amount)
}).First().Expr1)
};
I have the latest CSR1 installed of NHibernate but it just doesn't seem to work with my query.
The LINQ provider in NH3 is currently in a beta state. There are certain constructs that are not yet supported. (The team plans to address this after the NH3 release.) The parts causing problems in your query are the "new {}" anonymous type in the group by clause and the First() in the context of a group by. Both are not currently implemented. The following query executes properly and should give the same results:
var query = from m0 in session.Query<Statement>()
where m0.Code == c.Code
group m0 by m0.Code into g
select new {Expr1 = g.Sum(p => p.Amount)};
var result = query.ToList().First().Expr1;
First note that the "new {}" in the group by clause is not required. The other change was adding "ToList()". This forces the results to be queried from the database and then we use LINQ-to-Objects to get the First() result. The SQL generated for this query is:
select cast(sum(statement0_.Amount) as DOUBLE PRECISION) as col_0_0_
from Statement statement0_
where (statement0_.Code is null)
and ('FOO' /* #p0 */ is null)
or statement0_.Code = 'FOO' /* #p0 */
group by statement0_.Code

Getting Last rows from the result of Linq to Sql statement

I couldn't get last articles of every writers in this statement.
List<Editor> lstEditors = dataContext.GetTable<Editor>().Where(t => t.M_Active).Select(t => t).ToList();
var lstArticles = from article in DAO.context.GetTable<Article>().ToList()
join editor in lstEditors on article.RefEditorId equals editor.EditorId
select
new
{
article.M_ArticleId,
article.M_Subject,
article.M_Text,
editor.M_EditorId,
editor.M_Member.M_EditorPicture,
M_NameSurname = editor.M_Member.M_Fname + " " + editor.M_Member.M_Lname
};
Be careful, your query is fetching all the contents of both the Editor and the Yazi tables and then performs Linq-to-Objects on it.
I'm not sure what you ask exactly either, do you want to obtain the list of all writers (editors) along with the last article of each one of these writers?
Do you want to get the writers that did not write any articles yet also?
Edit:
explanation of methods causing an immediate query
Any time you call one of the methods listed below on an IQueryable object (tables or other queries), it performs the actual query to SQL server:
ToList(), ToArray(), ToLookup(), ToDictionay()
Count(), Sum(), Avg(), Aggregate(), Min(), Max()
First(), FirstOrDefault(), Last(), LastOrDefault()
getting last article written by each writer
//create a subquery that returns an editor and its last article date
var editorLastArticleDates =
from article in DAO.context.GetTable<Article>()
group article by article.RefEditor into g
let lastArticleDate= g.Max(x => x.Date)
select new
{
Editor = g.Key,
LastArticleDate = lastArticleDate,
};
//Note: We did not do a ToList() here so the query is not executed
// The editorLastArticleDates object is a IQueryable<>
var query =
from article in DAO.context.GetTable<Article>()
join editorLastArticleDate in editorLastArticleDates
on new { article.Editor, article.Date } // 1
equals new { editorLastArticleDate.Editor, // 2
Date = editorLastArticleDate.LastArticleDate } // 3
select new
{
article.M_ArticleId,
article.M_Subject,
article.M_Text,
article.RefEditor.M_EditorId,
article.RefEditor.M_Member.M_EditorPicture,
M_NameSurname = article.RefEditor.M_Member.M_Fname + " "
+ article.RefEditor.M_Member.M_Lname,
};
//Note: We did not do a ToList() yet so the query is not executed
// The query object is a IQueryable<>
Console.WriteLine(query.ToString()); //Displays SQL query on the console
var results = query.ToList(); // SQL query is executed on this line.
In the code above, I left some remarks on things I had problems with:
When using join, the section between new and equals access only variables declared before the join keyword while the section after the equals keyword has access to the variable defined between join and in.
When writing your join condition, make sure you use equals and not ==.
When using new { XXX, YYY } syntax in your join condition, you declare anonymous types. If the property names are not identical on both sides, it will not compile. In order to have identical property names in this sample, I added the Date = before my value.
By the way, you should use LinqPad to test your queries, it is really a nice tool.

Resources