I have following a table called Resources where it has couple of capacity fields ; CapM3, CapUD and CapMT.
I would like to get list of resources where capacity is equal or larger than a default supplied resource.
public static IList<Resources> GetSwapResources(string resourceID)
{
//selected resource
var res = db.Resources.FirstOrDefault(p => p.ResourceID == resourceID);
//select all active resources excluding selected
var resources = db.Resources.Where(p => p.Active == true && p.ResourceID != resourceID);
//not sure how to filter here
return resources.ToList();
}
}
I think I will be able to do this by looping for desired results. But, can that be handled within LINQ query itself?
I think I will be able to do this by looping for desired results. But,
can that be handled within LINQ query itself?
Yes, you can chain as many conditions to the Where clause as you wish:
var res = db.Resources
.Where(p => p.ResourceID == resourceID)
.Where(p => p.Active == true)
.Where(p => p.CapM3 >= 1234)
.Where(p => p.CapM3 >= 5678);
Or if you wanted to use OR instead of AND:
var res = db.Resources
.Where(p => p.ResourceID == resourceID)
.Where(p => p.Active == true)
.Where(p => p.CapM3 >= 1234 || p.CapM3 >= 5678);
I figured out on how to achieve desired result :
public static IList<Resources> GetSwapResources(string resourceID)
{
//selected resource
var res = db.Resources.FirstOrDefault(p => p.ResourceID == resourceID);
//select all active resources excluding selected
var resources = db.Resources.Where(p => p.Active == true && p.ResourceID != resourceID);
.Where(a => a.CapM3 <= res.CapM3 && a.CapMT <= res.CapMT && a.CapUD<= res.CapUD);
return resources.ToList();
}
}
Related
When var items = q3.ToList(); executes from the code snippet below, it throws exception System.NotSupportedException. The aim is to get the list of items after the grouping.
Exception:
Unable to create a constant value of type 'AppDB.Stage.Rules'. Only primitive types or enumeration types are supported in this context.
var valuations = context.stage
.Where(q => q.stageID == stageID && !rules.ToList().Any(r => r.type1 == q.type1 || r.type2 == q.type2))
.GroupBy(q => q.stageKey)
.Select(g => g) ;
var q3 = valuations.Select(y => new StageType
{
TypeKey = y.Key,
TypeName= "UNKNOWN",
});
var items = q3.ToList(); //error here
Your database doesn't have any idea of what your in-memory rules actually is, and in-turn cant convert this statement to SQL
The simplest solution will be to leave it as an IQueryable and don't use ToList,
context.stage
.Where(q => q.stageID == stageID && !rules.Any(r => r.type1 == q.type1 || r.type2 == q.type2))
.GroupBy(q => q.stageKey)
.Select(g => g) ;
However, if it is already in memory, then you will have to send the values as a primitive list
var type1s = rules.Select(x => x.type1);
var type2s = rules.Select(x => x.type2);
context.stage
.Where(q => q.stageID == stageID && !type1s.Contains(q.type1) && !type2s.Contains(q.type2))
.GroupBy(q => q.stageKey)
.Select(g => g) ;
Because rules.ToList() makes results in memory, you can't use it inside an IQueryable that executes over SQL. You should first bring your data into memory and then narrow it by other in-memory object.
var valuations = context.stage.ToList()
.Where(q => q.stageID == stageID && !rules.ToList().Any(r => r.type1 == q.type1 || r.type2 == q.type2))
.GroupBy(q => q.stageKey)
.Select(g => g) ;
var q3 = valuations.Select(y => new StageType
{
TypeKey = y.Key,
TypeName= "UNKNOWN",
});
var items = q3.ToList();
I getting this error when I join:
An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: The specified LINQ expression contains references to queries that are associated with different contexts.
var rightsList = RoleRightService.GetRoleRights<RoleRight>().Where(x => x.RoleCode == role && x.CompanyId == USER_OBJECT.CompanyId).AsEnumerable();
var securables = SecurableServices.GetSecurable<Securable>()
.GroupBy(a => new { a.RegistrationType_LookUpId })
.Select(r => new
{
id = r.Select(x => x.SecurableID),
registrationType = r.Key.RegistrationType_LookUpId,
RegistrationTypeName = r.Select(x => x.RegistrationType.LookUpDescription).Distinct().FirstOrDefault(),
IsChecked = false,
pageList = r.GroupBy(b => new { b.PageID })
.Select(p => new SecurableViewModel
{
Id = p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.SecurableID).FirstOrDefault(),
PageId = p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.PageID).FirstOrDefault(),
PageName = p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.PageDescription).FirstOrDefault(),// && rr.AccessRight !=0
IsChecked = rightsList.Where(rr => rr.SecurableID == (p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.SecurableID).FirstOrDefault())).Count() > 0,
operationList = r.Where(x => x.PageID == p.Key.PageID && x.Type == 2)
.Select(o => new RoleRightViewModel
{
Id = o.SecurableID,
OperationID = o.OperationID,
OperationName = o.OperationDescription,
IsChecked = rightsList.Where(rr => rr.SecurableID == o.SecurableID).Count() > 0,
})
.ToList()
}).ToList()
}).ToList();
I am getting error
The specified LINQ expression contains references to queries that are associated with different contexts.
For this line:
IsChecked = rightsList.Where(rr => rr.SecurableID == (p.Where(x => x.PageID == p.Key.PageID && x.Type == 1).Select(x => x.SecurableID).FirstOrDefault())).Count() > 0,
is there possibilty to right delegate for this
It looks like you are using multiple EF entity contexts, possibly to query more than one database. EF is not able to perform a linq to entities query across more than one EF context.
In order to execute this query without error is will be necessary to use linq to objects instead by projecting the data from each context into memory before combining them. Please note this may have a negative performance impact since all objects will need to be fetched into memory before being filtered down.
Try adding a .ToList() between your GroupBy and Select statements:
var securables = SecurableServices.GetSecurable<Securable>()
.GroupBy(a => new { a.RegistrationType_LookUpId })
.ToList()
.Select(r => new
...
public int being = 0;
public void Insert(Currency current, int number)
{
being = db.Currency.Where(x => x.ForDate == current.ForDate)
.Where(x => x.TitleId == current.TitleId)
.Where(x => x.Value == current.Value).Count(x=>x.Id > 0);
if (being == 0)
{
db.Currency.AddOrUpdate(current);
}
}
it's my code works so slowly, because of getting date but it is not necessary, i don't know other way.
maybe something like :
db.Currency.Find().Value.Equals(current.Value).where...where...
I think your main problem is the .Count(x => x.Id > 0), which forces the evaluation of all the conditions before and actually get the total number.
If you can, replace it with Any. In that way, it just has to get one row at most:
bool isBeing = db.Currency
.Where(x => x.ForDate == current.ForDate
&& x.TitleId == current.TitleId
&& x.Value == current.Value
&& x.Id > 0
)
.Any();
You can do all your conditions in just one where, and also you can skip having a bool variable to check your conditions
if(db.Currency.Where(x => x.ForDate == current.ForDate
&& x.TitleId == current.TitleId && x.Value == current.Value && x.Id > 0).Any())
{
db.Currency.AddOrUpdate(current);
}
Operator should be ‘AND’ and not a ‘OR’.
I am trying to refactor the following code and i understood the following way of writing linq query may not be the correct way. Can somone advice me how to combine the following into one query.
AllCompany.Where(itm => itm != null).Distinct().ToList();
if (AllCompany.Count > 0)
{
//COMPANY NAME
if (isfldCompanyName)
{
AllCompany = AllCompany.Where(company => company["Company Name"].StartsWith(fldCompanyName)).ToList();
}
//SECTOR
if (isfldSector)
{
AllCompany = AllCompany.Where(company => fldSector.Intersect(company["Sectors"].Split('|')).Any()).ToList();
}
//LOCATION
if (isfldLocation)
{
AllCompany = AllCompany.Where(company => fldLocation.Intersect(company["Location"].Split('|')).Any()).ToList();
}
//CREATED DATE
if (isfldcreatedDate)
{
AllCompany = AllCompany.Where(company => company.Statistics.Created >= createdDate).ToList();
}
//LAST UPDATED DATE
if (isfldUpdatedDate)
{
AllCompany = AllCompany.Where(company => company.Statistics.Updated >= updatedDate).ToList();
}
//Allow Placements
if (isfldEmployerLevel)
{
fldEmployerLevel = (fldEmployerLevel == "Yes") ? "1" : "";
AllCompany = AllCompany.Where(company => company["Allow Placements"].ToString() == fldEmployerLevel).ToList();
}
Firstly, unless AllCompany is of some magic custom type, the first line gives you nothing.
Also I have a doubt that Distinctworks the way You want it to. I don't know the type of AllCompany but I would guess it gives you only reference distinction.
Either way here'w what I think You want:
fldEmployerLevel = (fldEmployerLevel == "Yes") ? "1" : "";
var result = AllCompany.Where(itm => itm != null)
.Where(company => !isfldCompanyName || company["Company Name"].StartsWith(fldCompanyName))
.Where(company => !isfldSector|| fldSector.Intersect(company["Sectors"].Split('|')).Any())
.Where(company => !isfldLocation|| fldLocation.Intersect(company["Location"].Split('|')).Any())
.Where(company => !isfldcreatedDate|| company.Statistics.Created >= createdDate)
.Where(company => !isfldUpdatedDate|| company.Statistics.Updated >= updatedDate)
.Where(company => !isfldEmployerLevel|| company["Allow Placements"].ToString() == fldEmployerLevel)
.Distinct()
.ToList();
Edit:
I moved Distinct to the end of the query to optimize the processing.
How about trying like this;
AllCompany = AllCompany .Where(company => (company => company.Statistics.Created >= createdDate)) && (company.Statistics.Updated >= updatedDate));
If every part of query is optional (like created date, last update date..) then you can build linq query string.
Here's a sneaky trick. If you define the following extension method in its own static class:
public virtual IEnumerable<T> WhereAll(params Expression<Predicate<T> filters)
{
return filters.Aggregate(dbSet, (acc, element) => acc.Where(element));
}
then you can write
var result = AllCompany.WhereAll(itm => itm != null,
company => !isfldCompanyName || company["Company Name"].StartsWith(fldCompanyName),
company => !isfldSectorn || fldSector.Intersect(company["Sectors"].Split('|')).Any(),
company => !isfldLocation || fldLocation.Intersect(company["Location"].Split('|')).Any(),
company => !isfldcreatedDate || company.Statistics.Created >= createdDate,
company => !isfldUpdatedDate || company.Statistics.Updated >= updatedDate,
company => !isfldEmployerLevel || company["Allow Placements"].ToString() == fldEmployerLevel)
.Distinct()
.ToList();
Please see the code below:
var pcPageList = db.PcPages
.Where(m =>
m.Quarter == exactQuarter &&
m.Url == pageUrl &&
m.UpdatedOn.ToDateTime().Date.ToString("dd/MMM").ToLower() == "02/nov")
.OrderBy(m => m.UpdatedOn)
.FirstOrDefault();
When I run this above, the application throws error says: "ToDateTime" is not implemented yet. Anyone please can advice ?
How about:
var updateStart = DateTime.ParseExact("02/nov", "dd/MMM", CultureInfo.InvariantCulture);
var updateEnd = updateStart.AddDays(1.0);
var pcPageList = db.PcPages
.Where(m =>
m.Quarter == exactQuarter &&
m.Url == pageUrl &&
m.UpdatedOn >= updateStart &&
m.UpdatedOn < updateEnd)
.OrderBy(m => m.UpdatedOn)
.FirstOrDefault();
I think, you should be calling ToDateTime using Convert class as:
Convert.ToDateTime(m.UpdatedOn).Date...
And remove the Date in between as:
Convert.ToDateTime(m.UpdatedOn).ToString("dd/MMM").ToLower() == "02/nov"
Rather than doing a string comparison, it would be more efficient to compare the date components directly. I haven't tested this, but something like the following may work:
var pcPageList = db.PcPages
.Where(m => m.Quarter == exactQuarter && m.Url == pageUrl)
// You may need to materialize the results of the query at this point
// or use Convert.ToDateTime(...) instead of ToDateTime()
.Select(m => new { Row = m, UpdatedOn = m.UpdatedOn.ToDateTime() })
.Where(a => a.UpdatedOn.Month == 11 && a.UpdatedOn.Day == 2)
.Select(a => a.Row)
.OrderBy(m => m.UpdatedOn)
.FirstOrDefault();