LinqtoSQL filter and order by syntax - linq

My Techie Bretheren (and Sisteren, of course!),
I have a LinqToSql data model that has the following entities:
data model http://danimal.acsysinteractive.com/images/advisor.jpg
I need to retrieve all advisors for a specific office, ordered by their sequence within the office. I've got the first part working with a join:
public static List<Advisor>GetOfficeEmployees(int OfficeID)
{
List<Advisor> lstAdvisors = null;
using (AdvisorDataModelDataContext _context = new AdvisorDataModelDataContext())
{
var advisors = from adv in _context.Advisors
join advisoroffice in _context.OfficeAdvisors
on adv.AdvisorId equals advisoroffice.AdvisorId
where advisoroffice.OfficeId == OfficeID
select adv;
lstAdvisors = advisors.ToList();
}
return lstAdvisors;
}
However, I can't seem to wrap my weary brain around the order by clause. Can anyone give some suggestions?

from adv in _context.Advisors
where adv.OfficeAdvisor.Any(off => off.OfficeId == officeID)
order adv by adv.OfficeAdvisor.First(off => off.OfficeId = officeID).Sequence
select adv;

public static List<Advisor>GetOfficeEmployees(int OfficeID)
{
List<Advisor> lstAdvisors = null;
using (AdvisorDataModelDataContext _context = new AdvisorDataModelDataContext())
{
var advisors = from adv in _context.Advisors
join advisoroffice in _context.OfficeAdvisors
on adv.AdvisorId equals advisoroffice.AdvisorId
where advisoroffice.OfficeId == OfficeID
group adv by adv.OfficeId into g
order by g.Sequence
select g;
lstAdvisors = advisors.ToList();
}
return lstAdvisors;
}
Note: I am not able to currently test this on Visual Studio but should work.

You can add an order by clause like this:
var advisors = from adv in _context.Advisors
join advisoroffice in _context.OfficeAdvisors
on adv.AdvisorId equals advisoroffice.AdvisorId
where advisoroffice.OfficeId == OfficeID
orderby advisoroffice.Sequence // < -----
select adv;

Related

How to update a particular field of a particular object in Generic list in c#.net using LINQ

I am creating a Generic List of objects of Employee class.
List<Employee> EmployeeList = new List<Employee>
{
new Employee { ecode=1, ename="Rohit", salary=20000, mgrid="3" },
new Employee { ecode=2, ename="Sangeeta", salary=12000, mgrid="5"},
new Employee { ecode=3, ename="Sanjay", salary=10000, mgrid="5"},
new Employee { ecode=4, ename="Arun", salary=25000, mgrid="3"},
new Employee { ecode=5, ename="Zaheer", salary=30000, mgrid=null}
};
'mgrid' is the Employee ID of the Manager. I want just increment the salary of the Managers.
I tried doing it using the following approach, but salaries of all the employees are getting incremented.
var mgrsal = from e1 in emplst
join e2 in emplst
on e1.ecode.ToString() equals e2.mgrid into empdata
select new Employee
{
ecode = e1.ecode,
ename=e1.ename,
salary=e1.salary*1.1,
mgrid = e1.mgrid
};
I am coding in C#.net in Visual Studio IDE and I also tried to use Contains() and Any() methods, but I am unable to use.
LINQ is all about querying, not updating. You can use LINQ to get all managers from the list,
var managers = from e in emplst
where emplst.Any(x => x.mgrid == e.ecode.ToString())
select e;
or using JOIN (it would require implementing Equals and GetHashCode methods on Employee class to make Distinct work:
var managers = (from e in emplst
join e2 in emplst on e.ecode.ToString() equals e2.mgrid
select e).Distinct();
and then iterate over and change the salary:
foreach(var manager in managers)
manager.salary *= 1.1;

How to write this LINQ with foreach in a better way

I was doing project in MVC3 with Entity framework. I have a LINQ query with foreach. Everything is fine. But when the data size goes up, i was facing performance issues. I dont have much experience with LINQ. So I couldn't fix my issue. Pls have a look at my code and provide a better suggestion for me.
Code
List<int> RouteIds = db.Cap.Where(asd => asd.Type == 3).Select(asd => asd.UserId).ToList();
var UsersWithRoutingId = (from route in db.RoutingListMembers
where RouteIds.Contains(route.RoutingListId.Value) && route.User.UserDeptId == Id
select
new RoutingWithUser
{
UserId = route.UserId,
RoutingId = route.RoutingListId
});
var ListRouteValue = (from cap in db.CareAllocationPercents
where cap.Type == 3
select new UserWithDeptId
{
Year = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Year).FirstOrDefault(),
UserId = cap.UserId,
UserDeptId = (from userdept in db.Users where userdept.Id == cap.UserId select userdept.UserDeptId).FirstOrDefault(),
});
List<UserWithDeptId> NewRouteList = new List<UserWithDeptId>();
ListRouteValue = ListRouteValue.Where(asd => asd.Year == Year);
foreach (var listdept in ListRouteValue)
{
foreach (var users in UsersWithRoutingId)
{
if (users.RoutingId == listdept.UserId)
{
UserWithDeptId UserwithRouteObj = new UserWithDeptId();
UserwithRouteObj.UserId = users.UserId;
UserwithRouteObj.Year = listdept.Year;
UserwithRouteObj.UserDeptId = db.Users.Where(asd => asd.Id == users.UserId).Select(asd => asd.UserDeptId).FirstOrDefault();
NewRouteList.Add(UserwithRouteObj);
}
}
}
NewRouteList = NewRouteList.Where(asd => asd.UserDeptId == Id).ToList();
Thanks,
You have to use join in first statement. Examples of how to do this are for example here: Joins in LINQ to SQL
I have some idea for you:
First:
Take care to complete your where close into your linq query to get just what you need to.
With Linq on collection, you can remove one foreach loop. I don't know the finality but, i've tryied to write something for you:
var UsersWithRoutingId = (from route in db.RoutingListMembers
where RouteIds.Contains(route.RoutingListId.Value) && route.User.UserDeptId == Id
select
new RoutingWithUser
{
UserId = route.UserId,
RoutingId = route.RoutingListId
});
var ListRouteValue = (from cap in db.CareAllocationPercents
where cap.Type == 3
select new UserWithDeptId
{
Year = (from amt in db.CareAllocations
where amt.CareItemId == cap.CareItemId && amt.Year == Year
select amt.Year).FirstOrDefault(),
UserId = cap.UserId,
UserDeptId = (from userdept in db.Users
where userdept.Id == cap.UserId && userdept.UserDeptId == Id
select userdept.UserDeptId).FirstOrDefault(),
});
List<UserWithDeptId> NewRouteList = new List<UserWithDeptId>();
foreach (var listdept in ListRouteValue)
{
var user = UsersWithRoutingId.Where(uwri => uwri.RoutingId == listdept.UserId).FirstOrDefault();
if (user != null)
{
NewRouteList.Add(new UserWithDeptId { UserId=user.UserId, Year=listdept.Year, UserDeptId=listdept.UserDeptId });
}
}
return NewRouteList
Is that right for you ?
(i don't poll the db.user table do get the UserDeptId for the NewRouteList assuming that the one in the listdept is the good one)
Second:
Take care of entity data loading, if you have tables with foreign key, take care to remove the lazy loading if you don't need the children of your table to be loaded at same time. Imagine the gain for multiple table with foreign key pointing to others.
Edit:
Here is a link that explain it:
http://msdn.microsoft.com/en-us/library/vstudio/dd456846%28v=vs.100%29.aspx

LINQ - join with OR condition

I've got two entities, Users and Friendships which look like:
public class User
{
public int UserId { get; set; }
(...)
}
public class Friendship
{
public int SenderId { get; set; }
public int ReceiverId { get; set; }
(...)
}
And I would like to create simple query which in SQL would look like:
SELECT * FROM Users as U
INNER JOIN Friendships as F ON U.UserId = F.ReceiverId OR U.UserId = F.SenderId
Where U.Nick != VARIABLE
In other words I would like to select all friends of the user.
And I can't accomplish that. I've found solution where one creates two separate join queries with union and it works - but it's not efficient to create such query to db.
Joins in LINQ are always equijoins. Basically you need multiple from clauses and a where clause:
var query = from u in db.Users
where u.Nick != variable
from f in db.Friendships
where u.UserId == f.ReceiveId || u.UserId == f.SenderId
select ...;
Now in LINQ to Objects there are probably more efficient ways of doing this - but I'd expect a SQL-based LINQ provider to generate a query which has a good enough execution plan. It may not actually create a JOIN in the SQL, but I'd expect it to be the same execution plan as the join you've shown.
Simply write:
from U in db.Users
from F in Friendships.Where(x => U.UserId == F.ReceiverId || U.UserId == F.SenderId)
where U.Nick != VARIABLE
select new {u, f};

Linq distinct problem

I am new to using LINQ, right now i have a query in sql with multiple inner joins and it works fine. I am trying to change this to a equivalent LINQ code, i could able to implement LINQ except for the Distinct fact i am using in my query...
my query
select DT.[Name], count(distinct([FeatureControlID])) as [Value], DT.[Weight]
from [DocumentTypes] DT inner join
[DocumentTypesSchema] DTS on
DT.[ID] = DTS.[DocumentTypeID] inner join
ProductsFeaturesControlsDocumentValues [PFCDV] on
DTS.[ID] = PFCDV.[SchemaID]
where [PFCDV].[ProductID] = 72
group by DT.[Name], DT.[Weight], [DT].[ID]
order by [DT].[ID]
and my LINQ without the Distinct condition is as below
from dt in db.DocumentTypes
join dts in db.DocumentTypesSchemas on new { ID = dt.ID } equals new { ID = dts.DocumentTypeID }
join pfcdv in db.ProductsFeaturesControlsDocumentValues on new { ID = dts.ID } equals new { ID = pfcdv.SchemaID }
where
pfcdv.ProductID == 72
group new {dt, pfcdv} by new {
dt.Name,
dt.Weight,
dt.ID
} into g
orderby
g.Key.ID
select new {
g.Key.Name,
Value = (Int64?)g.Count(p => p.pfcdv.FeatureControlID != null),
Weight = (System.Decimal?)g.Key.Weight
}
can anyone give me a hand on this? actually the linq code executes without the Distinct feature i used in the code.
Have you tried something like this?
...
select new {
g.Key.Name,
Value = (Int64?)g.Select(p => p.pfcdv.FeatureControlID)
.Where(id => id != null)
.Distinct().Count()
Weight = (System.Decimal?)g.Key.Weight
}

Linq one to many insert when many already exists

So I'm new to linq so be warned what I'm doing may be completely stupid!
I've got a table of caseStudies and a table of Services with a many to many relasionship
the case studies already exist and I'm trying to insert a service whilst linking some case studies that already exist to it. I was presuming something like this would work?
Service service = new Service()
{
CreateDate = DateTime.Now,
CreatedBy = (from u in db.Users
where u.Id == userId
select u).Take(1).First(),
Description = description,
Title = title,
CaseStudies = (from c in db.CaseStudies
where c.Name == caseStudy
select c),
Icon = iconFile,
FeatureImageGroupId = imgGroupId,
UpdateDate = DateTime.Now,
UpdatedBy = (from u in db.Users
where u.Id == userId
select u).Take(1).First()
};
But This isn't correct as it complains about
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Objects.DataClasses.EntityCollection'
Can somebody please show me the correct way.
Thanks in advance
Yo have to add the query result to the case studies collection instead of trying to replace it.
var service = new Service { ... };
foreach (var caseStudy in db.CaseStudies.Where(s => s.Name == caseStudyName)
{
service.CaseStudies.Add(caseStudy);
}
You can wrap this in an extension method and get a nice syntax.
public static class ExtensionMethods
{
public static void AddRange<T>(this EntityCollection<T> entityCollection,
IEnumerable<T> entities)
{
// Add sanity checks here.
foreach (T entity in entities)
{
entityCollection.Add(entity);
}
}
}
And now you get the following.
var service = new Service { ... };
service.CaseStudies.AddRange(db.CaseStudies.Where(s => s.Name == caseStudyName));

Resources