I have this query and i wanted to only select distinct value from Charges table(Port Name must only display once).
public List<Port> GetPortsByCountryOrigin(int countryId, TransportDirection transdirection, TransportType transtype)
{
using (var ctx = CreateDbContext())
{
return (from item in ctx.Ports
join s in ctx.Charges
on item.PortId equals s.PortId
where (s.TransportDirection == transdirection &&
s.TransportType == transtype
&& item.CountryId == countryId)
select item).ToList();
}
}
Currently, the Ports.Name are repeating values.
Try .Distinct() before your ToList()
Related
I need to create a table in View by this View Model:
public class ApplicationContentViewModel
{
public BPMSPARS.Models.MySql.application application {get; set;}
public BPMSPARS.Models.MySql.content content { get; set; }
public BPMSPARS.Models.MySql.app_delegation app_delegation { get; set; }
}
But the query for creating new Table is very complex.
I use this query in MySQL, and I can get correct results by using it.
SELECT APP_UID, (SELECT CON_VALUE FROM content WHERE CON_CATEGORY = 'PRO_TITLE' AND CON_ID =
(SELECT PRO_UID from app_delegation WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219')) AS TASK_NAME,
(SELECT CON_VALUE FROM content WHERE CON_CATEGORY = 'TAS_TITLE' AND CON_ID =
(SELECT TAS_UID from app_delegation WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219')) AS PROCESS_NAME FROM app_delegation
WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219'
But, I have to convert this query in linq or EF in MVC.
How Can I write This Query in Entity Framework query?
And How Can I display results in View?
Your SQL query seems (very) peculiar to me, as it is quite redundant. I am going to assume the sub-queries return a single value and enforce it with LINQ.
First I pulled out the common sub-query over app_delegation:
var USR_APP_Delegation = from a in app_delegation
where a.del_thread_status == "open" &&
a.USR_UID == "00000000000000000000000000000001" &&
a.APP_UID == "9134216305aaaea1b67c4e2096663219"
select a;
In LINQ it is easy to combine the two UID queries into one query:
var UIDs = (from a in USR_APP_Delegation
select new { a.PRO_UID, a.TAS_UID })
.Single();
Now you can do the name subqueries:
var TASK_NAME = (from c in content
where c.CON_CATEGORY == "PRO_TITLE" &&
c.CON_ID == UIDs.PRO_UID
select c.CON_VALUE)
.Single();
var PROCESS_NAME = (from c in content
where c.CON_CATEGORY == "TAS_TITLE" &&
c.CON_ID == UIDs.TAS_UID
select c.CON_VALUE)
.Single();
Then you can put all the queries together for the final result:
var ans = (from a in USR_APP_Delegation
select new {
a.APP_UID,
TASK_NAME,
PROCESS_NAME
})
.Single();
Again, this makes it obvious that your e.g. returning APP_UID when you know exactly what it is, and you are combining TASK_NAME and PROCESS_NAME into a query for no real advantage.
I would suggest using join against content makes a much more understandable query (even in SQL) and makes it clearer what is being returned:
var names = from a in app_delegation
join cpro in content on new { CON_ID = a.PRO_UID, CON_CATEGORY = "PRO_TITLE" } equals new { cpro.CON_ID, cpro.CON_CATEGORY }
join ctas in content on new { CON_ID = a.PRO_UID, CON_CATEGORY = "TAS_TITLE" } equals new { ctas.CON_ID, ctas.CON_CATEGORY }
where a.del_thread_status == "open" &&
a.USR_UID == "00000000000000000000000000000001" &&
a.APP_UID == "9134216305aaaea1b67c4e2096663219"
select new {
a.APP_UID,
Task_Name = ctas.CON_VALUE,
Process_Name = cpro.CON_VALUE
};
string name = null;
foreach (var dealer in contact)
{
if (name != null)
break;
if (name == null)
{
foreach (var emp in dealer.employees)
{
if (emp.id == primarySalespersonId)
{
if (emp.personFirstName != null)
name = emp.personFirstName;
else
name = "No Name";
break;
}
}
}
There are same multiple tables named contact. And each contact table has multiple dealer tables. I need a method to simplify this search using LINQ or any other better way. Please Help
The first optimisation you can do is to replace the inner loop to look for the employee by id, eg
string name = null;
foreach (var dealer in contact)
{
var emp= dealer.employees.Where(e=>e.Id == primarySalespersonId).FirstOrDefault();
if (emp!= null)
{
if (emp.personFirstName != null)
name = emp.personFirstName;
else
name = "No Name";
}
if (name != null)
break;
}
Going further, requires making some assumptions.
When a table has a column named 'id, then I would assume it means the column is an unique identity column.
If contact represents every dealer (as opposed to a selection of dealers) and if every employee belongs to a dealer, then you should be able to look up the id directly.
var emp = employees.Where(e=>e.Id == primarySalespersonId).SingleOrDefault();
if (emp != null)
{
if (emp.personFirstName != null)
name = emp.personFirstName;
else
name = "No Name";
}
I would like to have a single LINQ to SQL query to count 2 entities from the same table. E.g. Count number of employees and managers from table Personnel.
Example:
var q = from p in db.Personnel
where p.PersonType == 'Manager' || p.PersonType == 'Employee'
select new
{ NoOfPersonnel = p.Count(p => p.PersonType == 'Employee'), //Wrong way
NoOfManagers = p.Count(p => p.PersonType == 'Manager') //Wrong way
}
How can I do it?
Try this:
var list = from employee in db.Personnel
where employee.PersonType == "Manager" || employee.PersonType == "Employee"
group employee by employee.PersonType
into temp
select new { PersonType = temp.Key, Count = temp.Count() };
How to expand this query:
public Dictionary<int, List<TasksInDeal>> FindAllCreatedTasks()
{
return (from taskInDeal in db.TasksInDeals
where taskInDeal.Date > DateTime.Now && taskInDeal.Date < DateTime.Now.AddDays(7)
group taskInDeal by taskInDeal.CreatedByUserID
into groupedDemoClasses
select groupedDemoClasses).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());
}
into something like this:
public Dictionary<int, List<TaskForNotification>> FindAllCreatedTasks()
{
return (from taskInDeal in db.TasksInDeals
join user in db.Users on taskInDeal.CreatedByUserID equals user.UserID
where taskInDeal.Date > DateTime.Now && taskInDeal.Date < DateTime.Now.AddDays(7)
group taskInDeal by taskInDeal.CreatedByUserID
into groupedDemoClasses
select new TaskForNotification
{
Email = user.Email,
TaskInDealField1 = taskInDeal.TaskInDealField1,
TaskInDealField2 = taskInDeal.TaskInDealField2,
TaskInDealField3 = taskInDeal.TaskInDealField3,
...
}
).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());
}
So, to first query I need to join email from other table.
// do the date logic up front, not in the database.
DateTime now = DateTime.Now
DateTime weekFromNow = now.AddDays(7);
// pull the joined rows out of the database.
var rows =
(
from taskInDeal in db.TasksInDeals
where taskInDeal.Date > now && taskInDeal.Date < weekFromNow
join user in db.Users
on taskInDeal.CreatedByUserID equals user.UserID
select new {TaskInDeal = taskInDeal, UserEmail = user.Email}
).ToList();
// shape the rows in memory
Dictionary<int, List<TaskForNotification>> result =
(
from row in rows
let taskForNotification = new TaskForNotification
{
Email = row.UserEmail,
TaskInDealField1 = row.TaskInDeal.TaskInDealField1,
TaskInDealField2 = row.TaskInDeal.TaskInDealField2,
TaskInDealField3 = row.TaskInDeal.TaskInDealField3,
...
}
group taskForNotification by row.TaskInDeal.CreatedByUserID
// without an "into", group by ends the query.
).ToDictionary(g => g.Key, g => g.ToList());
When you group, bear this in mind. Groups in SQL have only keys and aggregates. Groups in LINQ have keys, aggregates and elements! If you ask the database for groups, and then ask for the elements - SQL couldn't provide you with those elements in a single query. You'll wind up automatically repeatedly re-querying using the group's key as a filter.
Is there any way to refactor this code so that it can omit unnecessary WHEREs and JOINs if the values passed into the function are null (this code works just fine right now if all parameters are passed in)? The "SearchItems" and "ItemDistance" functions are table-level functions for performing fulltext search and distance calculations, respectively.
public IQueryable<ItemSearchResult> Search(string keywords, int? category, float? latitude, float? longitude)
{
return from item in _db.Items
join searchItems in _db.SearchItems(keywords)
on item.ItemId equals searchItems.ItemId
join itemDistance in _db.ItemDistance(latitude.Value, longitude.Value)
on item.ItemId equals itemDistance.ItemId
where item.Category == category.Value
select new ItemSearchResult()
{
Item = item,
Distance = itemDistance.Distance
};
}
I'm making the assumption that if either of latitude or longitude is not provided, you don't calculate the distance (I'd probably encapsulate both into a class and pass that instead of passing separately to avoid confusion). If one or the other is not provided, the default Distance is used for the search result.
public IQueryable<ItemSearchResult> Search(string keywords, int? category, float? latitude, float? longitude)
{
IEnumerable<ItemSearchResult> result = null;
var query = _db.Items.AsEnumerable();
if (category.HasValue)
{
query = query.Where( i => i.Category == category.Value );
}
if (!string.IsNullOrEmpty(keywords))
{
query = query.Where( i => _db.SearchItems(keywords)
.Any( s => s.ItemId == i.ItemId ));
}
if (latitude.HasValue && longitude.HasValue)
{
result = from item in query
join distance in _db.ItemDistance( latitude.Value, longitude.Value )
on item.ItemId equals distance.ItemId
select new ItemSearchResult
{
Item = item,
Distance = distance.Distance
};
}
else
{
result = query.Select( i => new ItemSearchResult { Item = i } );
}
return result != null
? result.AsQueryable()
: new List<ItemSearchResult>().AsQueryable();
}
For starters, the only value passed into that function that can be null is keywords, as all others are non-nullable value types. So I'll consider that only (if you need it, others can be treated similarly).
Just don't use joins in the first place:
return from item in _db.Items
where keywords == null || _db.SearchItems(keywords).Select(si => si.ItemId).Contains(item.ItemId) &&
...
where item.Category == category
select new ItemSearchResult()
{
Item = item,
Distance = itemDistance.Distance
};