im working with xml and linq.
I have 2 xml files both contain "ID" and "LANGUAGE"
I want to do a join based on where the both the ID and LANGUAGE are equal in both files
I have something like this:
var data=
from details in h_details.Descendants("ROW")
join inst in instance.XPathSelectElements("//Row")
on details.Element("ID").Value
equals inst.XPathSelectElement("Field[#Name=\'h_id\']").Value
and on details.Element("LANGUAGE").Value
equals inst.XPathSelectElement("Field[#Name=\'h_lang\']").Value
basically the "and" statement wont work, so how do i join based on 2 conditions?
Anonymous types to the rescue.
var data=
from details in h_details.Descendants("ROW")
join inst in instance.XPathSelectElements("//Row")
on new {
x = details.Element("ID").Value,
y = details.Element("LANGUAGE").Value
} equals new {
x = inst.XPathSelectElement("Field[#Name=\'h_id\']").Value,
y = inst.XPathSelectElement("Field[#Name=\'h_lang\']").Value
}
select ... ;
try union to get the both lists and join them
Related
I want to have join query from a table with a dictionary based on a common field, my query is:
var query = from c in db.Exp
join d in lstUniprotDic on c.UniID equals d.Key
select new
{
c.UniID,
IdentityPercent=d.Value.ToString(),
c.PrId,
c.SpotNo
}
but i got the following error
Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator.
That pretty much says it all. You can't use the dictionary in your LINQ to SQL query except when using Contains.
Solution:
(from c in db.Exp where lstUniprotDic.Keys.Contains(c.UniID) select c).AsEnumerable()
join d in lstUniprotDic on c.UniID equals d.Key
select new
{
c.UniID,
IdentityPercent=d.Value.ToString(),
c.PrId,
c.SpotNo
}
I am not sure if the usage of lstUniprotDic.Keys in the LINQ to SQL query is actually working.
If not, try using this code instead:
var ids = lstUniprotDic.Keys.ToArray();
(from c in db.Exp where ids.Contains(c.UniID) select c).AsEnumerable()
join d in lstUniprotDic on c.UniID equals d.Key
select new
{
c.UniID,
IdentityPercent=d.Value.ToString(),
c.PrId,
c.SpotNo
}
How would you convert this trans-sql to LINQ?
I've tried it with the DefaultIfEmpty() but it seems to not be working for me.
Any help is appreciated.
SELECT s.Status
FROM EducationModule M
LEFT JOIN EducationModuleStatus S ON M.CourseID = S.CourseID
AND M.ModuleID = S.ModuleID
AND S.StudentID = '1506'
WHERE M.courseid = 2
Thanks in advance.
Joining on multiple columns in Linq to SQL is a little different.
You have to take advantage of anonymous types and compose a type for the multiple columns you wish to compare against, and under the sheet this will generate the type of join you are looking for.
var abcd = from tl in db.EducationModule
join s in db.EducationModuleStatus
on new { t1.CourseID, t1.ModuleID } equals new {s.CourseID, s.ModuleID}
into tl_s
where tl.CourseID == 2 AND s.StudentID == '1506'
from s in tl_s.DefaultIfEmpty()
select new
{
Status = s.Status
};
How can I write this HQL in Linq:
select a from A a
join a.childrenList b
where b = 1
childrenList is a list of enums which is not mapped to database by type but
rather is saved with its integer value.
This HQL works fine but I want to write it in Linq.
I cannot write something that can be compiled.
I think you can do
var results =
from a in db.Query<A>()
where a.childrenList.Any(b => b == (B)1)
select a;
or, using chained methods:
var results = db.Query<A>().Where(a => a.childrenList.Any(b => b == (B)1));
Regarding our comments above, I think you can drop the from A a in ... select a statements, because they are redundant.
I am trying to create a left join with a condition in my C# code. I can write it in SQL Server, but I am having problems writing it as a lambda expression. Here is a rough part of my SQL Code:
Select x.RequestId, aud.DepartmentId
From Requests x
Left Join UserDepartment ud on x.AssignedToTeam = ud.DepartmentId and ud.User = 'Joe'
I know how to write the Left Join but am unfamiliar with how or if it is possible to add the condition.
I suspect you want something like this:
var query = from request in db.Requests
join department in db.UserDepartments
.Where(dep => dep.User == "Joe")
on request.AssignedToTeam equals department.DepartmentId
into departments
from dep in departments.DefaultIfEmpty()
select new { request.RequestId,
DepartmentId = dep == null ? null : (int?) dep.DepartmentId
};
(Obviously change how you want to handle the absence of a department ID if necessary.)
Check out the MSDN article: How to: Perform Left Outer Joins (C# Programming Guide)
var request = db.View.Join(
db.UserDepartment.Where(w=>w.User=="Joe"),
a=>a.AssignedToTeam,
b=>b.DepartmentId,
(a,b)=> new {View = a, UserDepartment = b});
I'm trying to write some LINQ To SQL code that would generate SQL like
SELECT t.Name, g.Name
FROM Theme t
INNER JOIN (
SELECT TOP 5 * FROM [Group] ORDER BY TotalMembers
) as g ON t.K = g.ThemeK
So far I have
var q = from t in dc.Themes
join g in dc.Groups on t.K equals g.ThemeK into groups
select new {
t.Name, Groups = (from z in groups orderby z.TotalMembers select z.Name )
};
but I need to do a top/take on the ordered groups subquery. According to http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx in VB I could just add TAKE 5 on the end, but I can't get this syntax to work in c#. How do you use the take syntax in c#?
edit: PS adding .Take(5) at the end causes it to run loads of individual queries
edit 2: I made a slight mistake with the intent of the SQL above, but the question still stands. The problem is that if you use extension methods in the query like .Take(5), LinqToSql runs lots of SQL queries instead of a single query.
Second answer, now I've reread the original question.
Are you sure the SQL you've shown is actually correct? It won't give the top 5 groups within each theme - it'll match each theme just against the top 5 groups overall.
In short, I suspect you'll get your original SQL if you use:
var q = from t in dc.Themes
join g in dc.Groups.OrderBy(z => z.TotalMembers).Take(5)
on t.K equals g.ThemeK into groups
select new { t.Name, Groups = groups };
But I don't think that's what you actually want...
Just bracket your query expression and call Take on it:
var q = from t in dc.Themes
join g in dc.Groups on t.K equals g.ThemeK into groups
select new { t.Name, Groups =
(from z in groups orderby z.TotalMembers select z.Name).Take(5) };
In fact, the query expression isn't really making things any simpler for you - you might as well call OrderBy directly:
var q = from t in dc.Themes
join g in dc.Groups on t.K equals g.ThemeK into groups
select new { t.Name, Groups = groups.OrderBy(z => z.TotalMembers).Take(5) };
Here's a faithful translation of the original query. This should not generate repeated roundtrips.
var subquery =
dc.Groups
.OrderBy(g => g.TotalMembers)
.Take(5);
var query =
dc.Themes
.Join(subquery, t => t.K, g => g.ThemeK, (t, g) => new
{
ThemeName = t.Name, GroupName = g.Name
}
);
The roundtrips in the question are caused by the groupjoin (join into). Groups in LINQ have a heirarchical shape. Groups in SQL have a row/column shape (grouped keys + aggregates). In order for LinqToSql to fill its hierarchy from row/column results, it must query the child nodes seperately using the group's keys. It only does this if the children are used outside of an aggregate.