Select with NOT IN with entity framework - c#

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)

Related

Aggregate of string on anonymous type

I want to concat multiple string value into single string with comma separated,i tried using aggregate function but it shows cannot convert string to how to fix this issue,
I tried below code
var res = (from e in WYNKContext.SurgeryAssigned.Where(x => x.CmpID == cmpid && x.IsCancelled == false)
select new
{
ID = e.SAID,
UIN = e.UIN,
SurgeryDate = e.SurgeryDate,
SurgeryID = e.SurgeryID,
Surgery = ((from st in WYNKContext.SurgeryTran.
Where(x => x.SurgeryID == e.SurgeryID)
select new
{
desc = icdmaster
.Where(x => x.ID ==
st.IcdSpecialityCode).Select(x =>
x.SpecialityDescription).FirstOrDefault(),
}).ToList()).Aggregate((a, b) => a.desc + "," + b.desc),
}).ToList();
I want Output like inside surgery property like = string1,string 2 ,etc....
without using aggregate i am getting as count in Surgery Property
var res = (from e in WYNKContext.SurgeryAssigned.Where(x => x.CmpID == cmpid && x.IsCancelled == false)
select new
{
ID = e.SAID,
UIN = e.UIN,
SurgeryDate = e.SurgeryDate,
SurgeryID = e.SurgeryID,
Surgery = (from st in WYNKContext.SurgeryTran.Where(x => x.SurgeryID == e.SurgeryID)
select new
{
icd = icdmaster.Where(x => x.ID == st.IcdSpecialityCode).Select(x => x.SpecialityDescription).FirstOrDefault(),
}).ToList(),
}).ToList();
also tried string join :
Surgery = string.Join(",", (from st in WYNKContext.SurgeryTran.Where(x => x.SurgeryID == e.SurgeryID)
select new
{
icd = icdmaster.Where(x => x.ID == st.IcdSpecialityCode).Select(x => x.SpecialityDescription).FirstOrDefault(),
}).ToList()),
but in output i am getting like this
Surgery ={ icd = CORNEA },{ icd = CATARACT/IOL }
can some one tell what i did wrong in string.join.....
The string class has a static method named Join, which takes in a collection of items and a string to join them with, which should work for you here.
If I'm reading your code correctly, it would look something like this:
Surgery = string.Join(",", WYNKContext.SurgeryTran
.Where(surgTran => surgTran.SurgeryID == e.SurgeryID)
.Select(surgTran => icdmaster
.Where(icd => icd.ID == surgTran.IcdSpecialityCode)
.Select(icd => icd.SpecialityDescription)
.FirstOrDefault())),

Linq - Join resultset of 1 query with another table

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

Convert Sql to LINQ complex C# function to readable sql server string

I read a lot about getting a readable sql server query string from a c# linq to sql function, but could not figure out how to actually do so, maybe because the project i am working on is really complicated.
I'm pasting a pice of a code that i want to convert to sql (select * from bonds join etc.)
public List<EntBondPortfolio> GetBondsForPortfolio(List<int> groups, List<int> ratings,
List<int> collaterals, List<int> companies, List<int> countries, List<int> fields,
List<int> currencies, DateTime? fromExpirationDate, DateTime? untilExpirationDate, bool? perpetual, int? sortOrder = 1)
{
// Get Bonds
return (from bond in DALLinqClasses.Instance.BONDs
join company in DALLinqClasses.Instance.COMPANies on bond.Company_ID equals company.CompanyID
into companyJoin
from companyJ in companyJoin.DefaultIfEmpty()
join sellBuy in DALLinqClasses.Instance.SELL_BUY_OPERATIONs on bond.BondID equals sellBuy.Investment_ID
join account in DALLinqClasses.Instance.BANK_ACCOUNTs on sellBuy.BankAccount_ID equals account.BankAccountID
join groupsTable in DALLinqClasses.Instance.GROUPs on account.GroupAccount_ID equals groupsTable.GroupID
join customer in DALLinqClasses.Instance.CUSTOMERs on groupsTable.Customer_ID equals customer.CustomerID
join rating in DALLinqClasses.Instance.RATINGs on bond.Rating_ID equals rating.RatingID
into ratingJoin
from ratingJ in ratingJoin.DefaultIfEmpty()
join currency in DALLinqClasses.Instance.CURRENCies on bond.Currency_ID equals currency.CurrencyID
join country in DALLinqClasses.Instance.COUNTRies on bond.Country_ID equals country.CountryID
into countryJoin
from countryJ in countryJoin.DefaultIfEmpty()
join field in DALLinqClasses.Instance.FIELDs on bond.Field_ID equals field.FieldID
into fieldJoin
from fieldJ in fieldJoin.DefaultIfEmpty()
join collateral in DALLinqClasses.Instance.RISC_LEVELs on bond.RiscLevel_ID equals collateral.RiscLevelID
into collateralJoin
from collateralJ in collateralJoin.DefaultIfEmpty()
join orderi in // For order by
DALLinqClasses.Instance.PORTFOLIO_ORDERs.Where(x => x.InvestmentType_ID == (int)INVESTMENT_TYPES.BONDS)
on new EntTwoInts { BankAccountID = bond.BondID, GroupID = groupsTable.GroupID }
equals
new EntTwoInts { BankAccountID = orderi.Investment_ID, GroupID = orderi.Group_ID }
into orderJoin
from orderJ in orderJoin.DefaultIfEmpty()
where sellBuy.InvestmentType_ID == (int)INVESTMENT_TYPES.BONDS
&& groups.Contains(groupsTable.GroupID)
&& (collaterals.Contains(bond.RiscLevel_ID ?? -1) || collaterals.Contains(-1))
&& (ratings.Contains(bond.Rating_ID ?? -1) || ratings.Contains(-1))
&& (companies.Contains(bond.Company_ID ?? -1) || companies.Contains(-1))
&& (countries.Contains(bond.Country_ID ?? -1) || countries.Contains(-1))
&& (fields.Contains(bond.Field_ID ?? -1) || fields.Contains(-1))
&& (currencies.Contains(bond.Currency_ID) || currencies.Contains(-1))
&& (bond.ExpirationDate >= fromExpirationDate || fromExpirationDate == null)
&& (bond.ExpirationDate <= untilExpirationDate || untilExpirationDate == null)
&& (perpetual == bond.Perpetual || perpetual == null)
group sellBuy by new { bond, companyJ, groupsTable, account, orderJ, customer, ratingJ, collateralJ, countryJ, fieldJ } into g
orderby g.Key.orderJ != null ? false : true, g.Key.orderJ.SortOrder, g.Key.groupsTable.GroupName, g.Key.companyJ.CompanyName
select new EntBondPortfolio
{
Rating = g.Key.ratingJ.RatingName,
RiscLevel = g.Key.collateralJ.RiscLevelName,
Group = g.Key.groupsTable.GroupName,
Client = g.Key.customer.FirstName + ' ' + g.Key.customer.LastName,
GroupId = g.Key.groupsTable.GroupID,
Company = g.Key.companyJ.CompanyName,
CurrencyId = g.Key.bond.Currency_ID,
BondId = g.Key.bond.BondID,
CallText = g.Key.bond.CallText,
Field = g.Key.fieldJ.FieldName,
Country = g.Key.countryJ.CountryName,
CouponPercent = g.Key.bond.CouponPercent,
// Get total sum of coupons in checking account of current bond
CouponsPaid = DALLinqClasses.Instance.CHECKING_ACCOUNTs.
Where(x => x.ActionType_ID == (int)ACTION_TYPES.COUPON
&& g.Select(y => y.SellBuyOperationID).
Contains(x.SellBuyOperation_ID.GetValueOrDefault()))
.Sum(s => s.ActualSum),
ExpirationDate = g.Key.bond.ExpirationDate,
FaceValue = (g.Where(x => x.IsSell == false).Sum(x => x.FaceValue) - (g.Where(x => x.IsSell == true).Sum(x => x.FaceValue) ?? 0)),
Isin = g.Key.bond.Isin,
LastBuyDate = g.Where(x => x.IsSell == false).Max(x => x.SellBuyOperationDate),
CurrentPrice = DALInvestmentTypes.Instance.GetCurrentPriceOfBond(g.Key.bond.BondID, BONDS_HISTORY_TYPES.MarketValue),
CurrentYield = DALInvestmentTypes.Instance.GetCurrentPriceOfBond(g.Key.bond.BondID, BONDS_HISTORY_TYPES.Yield),
CurrentAcrInterest = DALInvestmentTypes.Instance.GetCurrentPriceOfBond(g.Key.bond.BondID, BONDS_HISTORY_TYPES.AcrInterest),
PurchasePrice = g.Where(x => x.IsSell == false).Sum(x => x.FaceValue) == 0 ? 0 :
g.Where(x => x.IsSell == false).Sum(x => x.FaceValue * x.Price)
/ g.Where(x => x.IsSell == false).Sum(x => x.FaceValue),
Instruction = DALInstructions.Instance.IsInvestmentHaveInstruction(INVESTMENT_TYPES.BONDS, g.Key.bond.BondID, g.Key.account.BankAccountID),
}).ToList();
}

How to Select new model list after GroupBy mothod in Linq?

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();

LINQ to Entities does not recognize the method

This is my Code where I am fetching data.
var list = (from u in _dbContext.Users
where u.IsActive
&& u.IsVisible
&& u.IsPuller.HasValue
&& u.IsPuller.Value
select new PartsPullerUsers
{
AvatarCroppedAbsolutePath = u.AvatarCroppedAbsolutePath,
Bio = u.Bio,
CreateDateTime = u.CreationDate,
Id = u.Id,
ModifieDateTime = u.LastModificationDate,
ReviewCount = u.ReviewsReceived.Count(review => review.IsActive && review.IsVisible),
UserName = u.UserName,
Locations = (from ul in _dbContext.UserLocationRelationships
join l in _dbContext.Locations on ul.LocationId equals l.Id
where ul.IsActive && ul.UserId == u.Id
select new PartsPullerLocation
{
LocationId = ul.LocationId,
Name = ul.Location.Name
}),
Rating = u.GetPullerRating()
});
Now Here is my Extension.
public static int GetPullerRating(this User source)
{
var reviewCount = source.ReviewsReceived.Count(r => r.IsActive && r.IsVisible);
if (reviewCount == 0)
return 0;
var totalSum = source.ReviewsReceived.Where(r => r.IsActive && r.IsVisible).Sum(r => r.Rating);
var averageRating = totalSum / reviewCount;
return averageRating;
}
I have check this Post LINQ to Entities does not recognize the method
And I come to know I need to use
public System.Linq.Expressions.Expression<Func<Row52.Data.Entities.User, int>> GetPullerRatingtest
But how ?
Thanks
You can use conditionals inside LINQ to Entity queries:
AverageRating = u.ReviewsReceived.Count(r => r.IsActive && r.IsVisible) > 0 ?
u.ReviewsReceived.Where(r => r.IsActive && r.IsVisible).Sum(r => r.Rating) /
u.ReviewsReceived.Count(r => r.IsActive && r.IsVisible)
: 0
This will be calculated by the server, and returned as part of your list. Although with 10 million rows like you said, I would do some serious filtering before executing this.
Code within LINQ (to Entities) query is executed within database, so you can't put random C# code there. So you should either use user.GetPullerRating() after it is retrieved or create a property if you don't want to do the calculation every time.
You can also do:
foreach (var u in list)
u.Rating = u.GetPullerRating()
By the way, why is it extension method.

Categories

Resources