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.
Related
Consider the following PL/SQL query:
SELECT department_id, LISTAGG(last_name, '; ')
WITHIN GROUP (ORDER BY last_name) "Emp_list"
FROM employees
GROUP BY department_id;
Would would be LINQ equivalent of the above?
Thank you!
EDIT: Since you want other columns and want to group, you can't use the method I originally proposed as-is. Here's a new solution, though the generated SQL isn't exactly great:
from employee in employees
group employee by employee.department_id into grpEmployee
select new {
DepartmentId = grpEmployee.Key,
LastNames = string.Join(", ", employees.Where(e => e.department_id == grpEmployee.Key)
.OrderBy(e => e.last_name).Select(e => e.last_name))
}
Note that this method combines both the query-like and lambda syntax.
This should do the trick. We select all of the last names and then join them into a single string as the final result.
string.Join("; ", (from employee in employees
where employee.department_id == 30
orderby employee.last_name
select employee.last_name))
I'm working through this MVC3 tutorial and have entered the genre of a film as a comma separated string.
In part 6 we take the genres from the table to populate a drop down list.
I'd like to populate the drop down list with a distinct collection of single genres but I just can't get it to work.
This is what the tutorial suggest as a start point
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
GenreLst.AddRange(GenreQry.Distinct());
... and this is where I'd got to
var GenreLst = new List<string>();
var GenreQry = (from d in db.Movies
orderby d.Genre
select d.Genre ).Select(s=>s.Split(','))
.Distinct();
GenreLst.AddRange( GenreQry );
Linq2Sql doesn't know s.Split(',') method, so it should throw an exception, you can do this:
var GenreQry = (from d in db.Movies
orderby d.Genre
select d.Genre ).Distinct().ToList();
GenreLst.AddRange( GenreQry.SelectMany(x=>x.Split(',')).Distinct());
about above code:
When calling ToList() in the end of query, your data will be fetched and your query in fact is list,
in second part, SelectMany flats separated strings as a IEnumberable of strings.
Edit: Also in first part you can call .AsEnumerable() instead of .ToList() for fetching data, it seems better way.
In case you find the SelectMany syntax a bit confusing, consider the following (which compiles into a select many method call under the covers but I find easier to read):
var GenreQry = (from d in db.Movies.AsEnumerable()
from s in d.Split(',')
select s)
.Distinct()
.OrderBy(s => s);
How can I do this SQL query with Entity Framework?
SELECT DISTINCT NAME FROM TestAddresses
Using lambda expression..
var result = EFContext.TestAddresses.Select(m => m.Name).Distinct();
Another variation using where,
var result = EFContext.TestAddresses
.Where(a => a.age > 10)//if you have any condition
.Select(m => m.name).Distinct();
Another variation using sql like syntax
var result = (from recordset
in EFContext.TestAddresses
.where(a => a.city = 'NY')//if you have any condition
.select new
{
recordset.name
}).Distinct();
Try this:
var results = (from ta in context.TestAddresses
select ta.Name).Distinct();
This will give you an IEnumerable<string> - you can call .ToList() on it to get a List<string>.
The way that #alliswell showed is completely valid, and there's another way! :)
var result = EFContext.TestAddresses
.GroupBy(ta => ta.Name)
.Select(ta => ta.Key);
I hope it'll be useful to someone.
DBContext.TestAddresses.Select(m => m.NAME).Distinct();
if you have multiple column do like this:
DBContext.TestAddresses.Select(m => new {m.NAME, m.ID}).Distinct();
In this example no duplicate CategoryId and no CategoryName i hope this will help you
Entity-Framework Select Distinct Name:
Suppose if you are using Views in which you are using multiple tables and you want to apply distinct in that case first you have to store value in variable & then you can apply Distinct on that variable like this one....
public List<Item_Img_Sal_VIEW> GetItemDescription(int ItemNo)
{
var Result= db.Item_Img_Sal_VIEW.Where(p => p.ItemID == ItemNo).ToList();
return Result.Distinct().ToList();
}
Or you can try this Simple Example
Public Function GetUniqueLocation() As List(Of Integer)
Return db.LoginUsers.Select(Function(p) p.LocID).Distinct().ToList()
End Function
use Select().Distinct()
for example
DBContext db = new DBContext();
var data= db.User_Food_UserIntakeFood .Select( ).Distinct();
In order to avoid ORDER BY items must appear in the select list if SELECT DISTINCT error, the best should be
var results = (
from ta in DBContext.TestAddresses
select ta.Name
)
.Distinct()
.OrderBy( x => 1);
Entity-Framework Select Distinct Name:
Suppose if you are want every first data of particular column of each group ;
var data = objDb.TableName.GroupBy(dt => dt.ColumnName).Select(dt => new { dt.Key }).ToList();
foreach (var item in data)
{
var data2= objDb.TableName.Where(dt=>dt.ColumnName==item.Key).Select(dt=>new {dt.SelectYourColumn}).Distinct().FirstOrDefault();
//Eg.
{
ListBox1.Items.Add(data2.ColumnName);
}
}
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();
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.