I have a Compilations table which have the details of employees and their compliances, I am getting the Employees whose ComplaianceStateId is either 6 or 9.
I have to get the employee FullName of these employees from the master tblEmployee table.
Table Name is tblEmployee and Column Name is FullName
EmployeeID is the Common key between these 2 tables tblEmployee and tblEmployeeCompliation
List<Int> employeeIds = new List<int>();
List<string> employeeNames = new List<string>();
employeeIds = EMPDB.tblEmployeeCompliations.Where( e=> e.IsActive == true && (e.ComplianceStateId == 6 || e.ComplianceStateId == 9)).Select( e => e.EmployeeID).Distinct().ToList();
employeeNames = //**//
I have to get the employee FullName of these employees from the master
tblEmployee table
From your requirement, you should select FullName instead of EmployeeID
var result = EMPDB.tblEmployeeCompliations
.Where(e => e.IsActive && (e.ComplianceStateId == 6 || e.ComplianceStateId == 9))
.Select(e => e.FullName).Distinct().ToList();
You need to join tblEmployeeCompliation and tblEmployee based on EmployeeID.
Example:
var employeeNames = EMPDB.tblEmployeeCompliations.Join( EMPDB.tblEmployee,
comp => comp.EmployeeID,
cus => cus.EmployeeID,
(comp, cus) => new { comp, cus })
.Where(e => e.comp.IsActive && (e.comp.ComplianceStateId == 6 || e.comp.ComplianceStateId == 9))
.GroupBy(g=>g.cus.FullName)
.Select(x=>x.Key);
OR
var employeeNames = from comp in EMPDB.tblEmployeeCompliations
join cus in EMPDB.tblEmployee on comp.EmployeeID equals cus.EmployeeID
where comp.IsActive=true && (comp.ComplianceStateId == 6 || comp.ComplianceStateId == 9)
group new { cus, comp } by new { cus.FullName } into g
select g.Key.FullName;
Please read this article: LINQ: Distinct() does not work as expected
Related
My linq query is:
var query1 = (from grp in ctnx.tblGroupDatas
group grp by grp.MeterID_FK into g
let maxId = g.Max(gId => gId.GroupDataID)
select new { metId = g.Key, maxId });
query2 = (from met in ctnx.tblMet
from mod in ctnx.tblMod.Where(mo => mo.ModID == met.Mod_FK).DefaultIfEmpty()
from grp in ctnx.tblGroupDatas.Where(gr => gr.Met_FK == met.MetID)
from group1 in db.tblMetRelateGroups.Where(x => x.Met_FK == met.MetID)
from q1 in query1.Where(q => q.metId == met.MetID && grp.GroupDataID == q.maxId)
where (group1.GroupMetID_FK == groupID)
select new
{
met.MetID,
mod.ModSerial,
met.MetSerial,
met.MetWaterSharingNo,
met.MetPowerSharingNo,
grp.GroupDate,
grp.GroupDataID
});
var gridobisdata = query2.OrderByDescending(m => m.GroupDate);
but this show error:
The specified LINQ expression contains references to queries that are
associated with different contexts.
I have been scouting the internet for the past 2 days to find a solution to grouping the below linq query on BookId to no avail. The query works but I want to reoganise it so that It can group on BookId or BookTitle.
models
Book(BookId, Title, Author, ISBN, Location, BookTypeId, StockLogValue)
Booktype(BookTypeId, BookTypeName)
Stock(StockId, bookId, quantity, date_added)
Transact (transactionId, TransactionTypeId, BookId, Quantity, TransactDate)
TransactionType( TransactionTypeId, TransactionTypeName)
Controller
public ActionResult Report(int? year, int? month, int? BkId)
{
var query = ReportYrMn( year, month, BkId);
return View(query);
}
public IEnumerable ReportYrMn(int? year, int? month, int? BkId)
{
var query =
(from bk in db.Books
join tr in db.Transacts.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale") on bk.BookId equals tr.BookId into trs
from x in trs.DefaultIfEmpty()
join tr2 in db.Transacts.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift") on bk.BookId equals tr2.BookId into trs2
from x2 in trs2.DefaultIfEmpty()
select new ReportViewModel { BookTitle = bk.BookTitle ,BookId = bk.BookId, StockLogValue=bksty.StockLogValue, SaleTotal = trs.Sum(c => c.TransactQty), GiftTotal = trs2.Sum(c => c.TransactQty), SalesCount = trs.Count(), GiftCount = trs2.Count() });
return query.AsEnumerable();
}
Thanks for any help
The immediate solution to your problem is to remove the from a in b.DefaultIfEmpty() lines. A join - into is the same as GroupJoin, which creates collections related to the left item, i.e. collections Transacs belonging to a book. That's exactly what you want here.
A subsequent from is equivalent to a SelectMany, which flattens these collections again, leaving you with a flat list of book-transact rows.
So this will do what you want:
var query =
(from bk in db.Books
join tr in db.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale")
on bk.BookId equals tr.BookId into trs
join tr2 in db.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift")
on bk.BookId equals tr2.BookId into trs2
select new ReportViewModel
{
BookTitle = bk.BookTitle,
BookId = bk.BookId,
StockLogValue=bksty.StockLogValue,
SaleTotal = trs.Sum(c => c.TransactQty),
GiftTotal = trs2.Sum(c => c.TransactQty),
SalesCount = trs.Count(),
GiftCount = trs2.Count()
});
I asked about navigation properties, because nearly always they make queries easier to write, since you don't need the cluncky joins. In your case the difference isn't that big though. If Book would have a navigation property Transacts the query could look like:
var query =
(from bk in db.Books
let sales = bk.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale")
let gifts = bk.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift")
select new ReportViewModel
{
BookTitle = bk.BookTitle,
BookId = bk.BookId,
StockLogValue=bksty.StockLogValue,
SaleTotal = sales.Sum(c => c.TransactQty),
GiftTotal = gifts.Sum(c => c.TransactQty),
SalesCount = sales.Count(),
GiftCount = gifts.Count()
});
I want select grouped rows to a new model list.this is my code:
List<Model_Bulk> q = (from a in db.Advertises
join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
where a.AdvertiseActive == true
&& a.AdvertiseExpireDate.HasValue
&& a.AdvertiseExpireDate.Value > DateTime.Now
&& (a.AdvertiseObjectType == 1
|| a.AdvertiseObjectType == 2)
select c)
.GroupBy(a => a.CompanyID).Select(a => new Model_Bulk
{
CompanyEmail = a.CompanyContactInfo.Email,
CompanyID = a.CompanyID,
CompanyName = a.CompanyName,
Mobile = a.CompanyContactInfo.Cell,
UserEmail = a.User1.Email,
categories = a.ComapnyCategories
}).ToList();
After group by, i can not use Select and naturally this syntax error raised:
System.Linq.IGrouping' does not contain a definition for 'CompanyContactInfo' and no extension method 'CompanyContactInfo' accepting a first argument of type
System.Linq.IGrouping' could be found (are you missing a using directive or an assembly reference?)
If i try with SelectMany() method.but the result will repeated and groupby method not work properly:
List<Model_Bulk> q = (from a in db.Advertises
join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
where a.AdvertiseActive == true
&& a.AdvertiseExpireDate.HasValue
&& a.AdvertiseExpireDate.Value > DateTime.Now
&& (a.AdvertiseObjectType == 1
|| a.AdvertiseObjectType == 2)
select c)
.GroupBy(a => a.CompanyID).SelectMany(a => a).Select(a => new Model_Bulk
{
CompanyEmail = a.CompanyContactInfo.Email,
CompanyID = a.CompanyID,
CompanyName = a.CompanyName,
Mobile = a.CompanyContactInfo.Cell,
UserEmail = a.User1.Email,
categories = a.ComapnyCategories
}).ToList();
Instead of .SelectMany(a => a) you can use .Select(g => g.First()).That will give you the first item of each group.
(from a in db.Advertises
join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
where a.AdvertiseActive == true && a.AdvertiseExpireDate.HasValue && a.AdvertiseExpireDate.Value > DateTime.Now && (a.AdvertiseObjectType == 1 || a.AdvertiseObjectType == 2)
select c)
.GroupBy(a => a.CompanyID)
.Select(g => g.First())
.Select(a => new Model_Bulk
{
CompanyEmail = a.CompanyContactInfo.Email,
CompanyID = a.CompanyID,
CompanyName = a.CompanyName,
Mobile = a.CompanyContactInfo.Cell,
UserEmail = a.User1.Email,
categories = a.ComapnyCategories
}).ToList();
Note that this might not be supported, if that is the case add an AsEnumerable call before .Select(g => g.First())
You should understand that after you do GroupBy() in your LinQ expresstion you work with a group so in your example it will be good to write like this:
List<Model_Bulk> q =
(from a in db.Advertises join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
where a.AdvertiseActive == true
&& a.AdvertiseExpireDate.HasValue
&& a.AdvertiseExpireDate.Value > DateTime.Now
&& (a.AdvertiseObjectType == 1 || a.AdvertiseObjectType == 2)
select c)
.GroupBy(a => a.CompanyID)
.Select(a => new Model_Bulk
{
CompanyEmail = a.First().CompanyContactInfo.Email,
CompanyID = a.Key, //Note this line, it's can be happened becouse of GroupBy()
CompanyName = a.First().CompanyName,
Mobile = a.First().CompanyContactInfo.Cell,
UserEmail = a.First().User1.Email,
categories = a.First().ComapnyCategories
}).ToList();
Instead you could try something like this, instead of mixing query expressions and methods... (using FirstOrDefault() in the where / select as necessary)
(from a in db.Advertises
join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
group a by new { a.CompanyId } into resultsSet
where resultsSet.AdvertiseActive == true && resultsSet.AdvertiseExpireDate.HasValue && resultsSet.AdvertiseExpireDate.Value > DateTime.Now && (resultsSet.AdvertiseObjectType == 1 || resultsSet.AdvertiseObjectType == 2)
select new Model_Bulk
{
CompanyEmail = resultsSet.CompanyContactInfo.Email,
CompanyID = resultsSet.CompanyID,
CompanyName = resultsSet.CompanyName,
Mobile = resultsSet.CompanyContactInfo.Cell,
UserEmail = resultsSet.User1.Email,
categories = resultsSet.ComapnyCategories
}).ToList();
I am trying to take the SQL code below and turn turn it into an EF select statement. I pretty much have it finished except I am stuck on how to do a NOT IN in entity framerwork.
MS SQL SELECT
SELECT * from friends as f
WHERE (f.id NOT IN (Select friendid from users_friends where userid = 1))
AND (f.lastname LIKE '%b%' OR f.firstname LIKE '%b%' OR f.alias LIKE '%b%')
My EF select without the NOT IN part
var friends =
(from f in db.Friends
select new FriendModel()
{
Id = f.Id,
Alias = f.Alias,
CarrierId = f.CarrierId,
CreatedOn = f.CreatedOn,
FirstName = f.FirstName,
LastName = f.LastName,
Locked = f.Locked,
PhoneNumber = f.PhoneNumber,
SteamId = f.SteamId,
Carrier = new CarrierModel()
{
CarrierName = f.Carrier.CarrierName,
CarrierEmail = f.Carrier.CarrierEmail
}
}).Where(
f => (f.Alias.Contains(query) || f.FirstName.Contains(query) || f.LastName.Contains(query)))
.OrderBy(f => f.Alias)
.ToList();
I guess this is what you want:
var friendIds = db.users_friends.Where(f => f.userid == 1).Select(f => f.friendid);
var friends = db.Friends.Where(f => !friendIds.Contains(f.Id) &&
(f.Alias.Contains(query) ||
f.FirstName.Contains(query) ||
f.LastName.Contains(query)))
.Select(f => new FriendModel() { ... })
.OrderBy(f => f.Alias)
.ToList();
Assuming User entity has a collection of Friend entity.
.Where(f => (f.Alias.Contains(query) || f.FirstName.Contains(query) || f.LastName.Contains(query))
&& !context.Users.FirstOrDefault(u=>u.UserId == 1)
.Friends.Any(uf=>uf.FriendId == f.FriendId))
If not, query the UserFriend table directly
.Where(f => (f.Alias.Contains(query) || f.FirstName.Contains(query) || f.LastName.Contains(query))
&& !context.UserFriends.Any(uf=>uf.UserId == 1 && uf.FriendId == f.FriendId)
I am getting data from multiple tables by joining and i want to group data on particular column value but after group by statement i can access my aliases and their properties. What mistake i am making?
public List<PatientHistory> GetPatientHistory(long prid)
{
using(var db = new bc_limsEntities())
{
List<PatientHistory> result =
(from r in db.dc_tresult
join t in db.dc_tp_test on r.testid equals t.TestId into x
from t in x.DefaultIfEmpty()
join a in db.dc_tp_attributes on r.attributeid equals a.AttributeId into y
from a in y.DefaultIfEmpty()
where r.prid == prid
group new {r,t,a} by new {r.testid} into g
select new PatientHistory
{
resultid = r.resultid,
bookingid = r.bookingid,
testid = r.testid,
prid = r.prid,
attributeid = r.attributeid,
result = r.result,
Test_Name = t.Test_Name,
Attribute_Name = a.Attribute_Name,
enteredon = r.enteredon,
Attribute_Type = a.Attribute_Type
}).ToList();
return result;
}
}
You're doing this wrong way. As been said by Jon after grouping the sequences with aliases r,t,a doesn't exist. After grouping you receive the sequence g with sequances of r,t,a in each element of g. If you want get one object from each group (for example most recent) you should try this:
List<PatientHistory> result =
(from r in db.dc_tresult
join t in db.dc_tp_test on r.testid equals t.TestId into x
from t in x.DefaultIfEmpty()
join a in db.dc_tp_attributes on r.attributeid equals a.AttributeId into y
from a in y.DefaultIfEmpty()
where r.prid == prid
group new {r,t,a} by new {r.testid} into g
select new PatientHistory
{
resultid = g.Select(x => x.r.resultid).Last(), // if you expect single value get it with Single()
// .... here add the rest properties
Attribute_Type = g.Select(x => x.a.Attribute_Type).Last()
}).ToList();
I appreciated this question so I thought I would add another potential usage case. I would like feedback on what the cleanest approach is to getting table information through a group operation so that I can project later in the select operation. I ended up combining what the OP did which is to pass objects into his group clause and then used the g.Select approach suggested by YD1m to get table information out later. I have a LEFT JOIN so I'm defending against nulls :
// SQL Query
//DECLARE #idCamp as Integer = 1
//
//select *,
//(select
//count(idActivityMaster)
//FROM tbActivityMasters
//WHERE dftidActivityCategory = A.idActivityCategory) as masterCount
//FROM tbactivitycategories A
//WHERE idcamp = #idCamp
//ORDER BY CategoryName
int idCamp = 1;
var desiredResult =
(from c in tbActivityCategories
.Where(w => w.idCamp == idCamp)
from m in tbActivityMasters
.Where(m => m.dftidActivityCategory == c.idActivityCategory)
.DefaultIfEmpty() // LEFT OUTER JOIN
where c.idCamp == idCamp
group new {c, m} by new { m.dftidActivityCategory } into g
select new
{
idActivityCategory = g.Select(x => x.m == null ? 0 : x.m.dftidActivityCategory).First(),
idCamp = g.Select(x => x.c.idCamp).First(),
CategoryName = g.Select(x => x.c.CategoryName).First(),
CategoryDescription = g.Select(x => x.c.CategoryDescription).First(),
masterCount = g.Count(x => x.m != null)
}).OrderBy(o=> o.idActivityCategory);
desiredResult.Dump("desiredResult");
If I just use a basic group approach I get the results but not the extra column information. At least I can't find it once I group.
var simpleGroup = (from c in tbActivityCategories
.Where(w => w.idCamp == idCamp)
.OrderBy(o => o.CategoryName)
from m in tbActivityMasters
.Where(m => m.dftidActivityCategory == c.idActivityCategory)
.DefaultIfEmpty() // LEFT OUTER JOIN
where c.idCamp == idCamp
group m by m == null ? 0 : m.dftidActivityCategory into g
select new
{
// How do I best get the extra desired column information from other tables that I had before grouping
// but still have the benefit of the grouping?
// idActivityCategory = g.Select(x => x.m == null ? 0 : x.m.dftidActivityCategory).First(),
// idCamp = g.Select(x => x.c.idCamp).First(),
// CategoryName = g.Select(x => x.c.CategoryName).First(),
// CategoryDescription = g.Select(x => x.c.CategoryDescription).First(),
// masterCount = g.Count(x => x.m != null)
idActivityCategory = g.Key,
masterCount = g.Count(x => x != null)
});
simpleGroup.Dump("simpleGroup");
Please tear this up. I'm trying to learn and it just seems like I'm missing the big picture here. Thanks.
UPDATE : Cleaned up by moving the work into the group and making the select more straight forward. If I had known this yesterday then this would have been my original answer to the OP question.
int idCamp = 1;
var desiredResult =
(from c in tbActivityCategories
.Where(w => w.idCamp == idCamp)
from m in tbActivityMasters
.Where(m => m.dftidActivityCategory == c.idActivityCategory)
.DefaultIfEmpty() // LEFT OUTER JOIN
where c.idCamp == idCamp
group new { c, m } by new
{ idActivityCategory = m == null ? 0 : m.dftidActivityCategory,
idCamp = c.idCamp,
CateGoryName = c.CategoryName,
CategoryDescription = c.CategoryDescription
} into g
select new
{
idActivityCategory = g.Key.idActivityCategory,
idCamp = g.Key.idCamp,
CategoryName = g.Key.CateGoryName,
CategoryDescription = g.Key.CategoryDescription,
masterCount = g.Count(x => x.m != null)
}).OrderBy(o => o.idActivityCategory);
desiredResult.Dump("desiredResult");