can some one convert it into linq to sql and remove let somehow?
Func<string, DateTime?> tryToGetDate = value =>
{
DateTime dateValue;
return DateTime.TryParse(value, out dateValue)
? (DateTime?)dateValue
: null;
};
var dates = (from bk in _context.BookDetails
join bkcategories in _context.BookCategories
on bk.BookId equals bkcategories.BookId
where bkcategories.CategoryId == Convert.ToInt64(categoryid)
let dateValue = tryToGetDate(bk.PublishedDate)
where dateValue != null && (DateTime)dateValue >= twomonths && (DateTime)dateValue <= today
orderby bk.PublishedDate descending, bk.BookId
select bk).Take(2).ToList();
var dates = (from bk in _context.BookDetails
join bkcategories in _context.BookCategories
on bk.BookId equals bkcategories.BookId
where bkcategories.CategoryId == Convert.ToInt64(categoryid)
where SqlFunctions.IsDate(bk.PublishedDate.ToString())==1 && bk.PublishedDate >= twomonths && bk.PublishedDate <= today
orderby bk.PublishedDate descending, bk.BookId
select bk).Take(2).ToList();
Related
I wrote a query and worked on LINQPAD
from x in FacilityData
from y in FavInformation
where y.UserID == 1 && x.ID == y.FacilityID
select new
{
xID = x.ID,
xDistrictName = (from y in _Ilcelers
where y.ID == x.DistrictID
select y.IlceAd).FirstOrDefault(),
xName = x.Name,
Value = (from o in Tags
from p in Table_tags
where o.Prefix != null && o.Prefix == p._NAME && o.Facility == y.FacilityID
orderby p.İd descending
select new
{
FType = o.TagType,
Name = o.TagsName,
Value = p._VALUE,
Time = p._TIMESTAMP
}).Take(Tags.Count(h => h.Facility == y.FacilityID))
}
result
the result is perfect
but does not work in visual studio,
Value = (from o in DB.Tags
from p in DB.table_tags
where o.Prefix != null && o.Prefix == p.C_NAME && o.Facility == 11
orderby p.id descending
select new
{
FType=o.TagType,
Name = o.TagsName,
Value = p.C_VALUE,
Time = p.C_TIMESTAMP
}).Take(Tags.Count(h => h.Facility == y.FacilityID))
and it gives an error.
I guess the part with .Take() doesn't work because it's linq to EF.
error:
Limit must be a DbConstantExpression or a Db Parameter Reference Expression. Parametre name: count]
error image
thank you have a good day
Not sure but I will just throw it in. If you are talking about linq to ef/sql, it is possible they dont know a thing about C#. If take() would be the problem try to get the select result local first by doing .tolist(). Afterwards use your take funtion.
.ToList().Take(Tags.Count(h => h.Facility == y.FacilityID))
I have a linq query like this :
var trfplanList = (from at in entities.tdp_ProviderAccomodationType
join ap in entities.tdp_ProviderAccomodationTariffPlan on at.PATID equals ap.FK_PATID
join ac in entities.tdp_ProviderAccomodationCategory on ap.FK_PACID equals ac.PACID
where at.FK_ProviderID == CityID && at.IsApproved == 0 && ap.IsApproved == 0 && ac.AccomodationCategory == "Double Occupy"
orderby at.AccomodationType,ap.FromDate,ap.SType
select new AccomodationTariff
{
AccomodationType = at.AccomodationType,
SType = ap.SType,
FromDate = Convert.ToDateTime(ap.FromDate),
ToDate = Convert.ToDateTime(ap.ToDate),
RoomTariff = Convert.ToDecimal(ap.Rate),
ExPAXRate = Convert.ToDecimal(at.PerPaxRate)
}).ToList();
I have two questions:
Can't I convert value while assigning in the select new {} block ? it is giving me an error in project.
I want use 'case' while selecting ExPAXRate from the database for example in SQL I used to write :
CASE ap.SType WHEN 'Off Season' THEN at.PerPaxRateOS ELSE at.PerPaxRate END AS ExPAXRate
Can I use something like this in linq query ?
Can't I convert value while assigning in the select new {} block
No, you can't (sadly). EF doesn't know how to translate it into SQL.
I want use 'case'
You can use the ternary operator (?):
ExPAXRate = at.OffSeason ? at.PerPaxRateOS : at.PerPaxRate
(assuming that at.OffSeason exists).
A solution for the conversion issue could be to project into an anonymous type first and then, in memory, to AccomodationTariff:
...
select new
{
AccomodationType = at.AccomodationType,
SType = ap.SType,
FromDate = ap.FromDate,
ToDate = ap.ToDate,
RoomTariff = ap.Rate,
ExPAXRate = at.PerPaxRate
}).AsEnumerable()
.Select(x => new AccomodationTariff
{
AccomodationType = x.AccomodationType,
SType = x.SType,
FromDate = Convert.ToDateTime(x.FromDate),
ToDate = Convert.ToDateTime(x.ToDate),
RoomTariff = Convert.ToDecimal(x.Rate),
ExPAXRate = Convert.ToDecimal(x.PerPaxRate)
}).ToList();
my linq query returns duplicate records like below, how i have to use distinct keyword in this linq query.
var draft_recieved = from df in _DataContext.tblDrafts
from dfBody in _DataContext.DraftBodies
from sendUser in _DataContext.tblSends
where (df.DraftId == dfBody.DraftID) && (df.DraftId == sendUser.DraftId) &&
(sendUser.ToEmailId == (Guid)Membership.GetUser().ProviderUserKey)
select new
{
subject = dfBody.Subject,
draftid = df.DraftId
};
.Distinct() has to be applied as an extension method.
var draft_recieved = (from df in _DataContext.tblDrafts
from dfBody in _DataContext.DraftBodies
from sendUser in _DataContext.tblSends
where (df.DraftId == dfBody.DraftID) && (df.DraftId == sendUser.DraftId) &&
(sendUser.ToEmailId == (Guid)Membership.GetUser().ProviderUserKey)
select new
{
subject = dfBody.Subject,
draftid = df.DraftId
}).Distinct();
I have this code:
var query = from deal in db.Deals
where deal.EndDate >= DateTime.UtcNow
select deal;
var priceList = filters.Price.GetPriceRangeList();
foreach(var price in priceList)
{
var startPrice = price.StartPrice;
var endPrice = price.EndPrice;
var priceResult = from deal in query
where (deal.DiscountPrice >= startPrice && deal.DiscountPrice <= endPrice)
select deal;
if(priceResult.Count() != 0)
priceResults = (priceResults == null) ? priceResult : priceResult.Union(priceResults);
}
query = priceResults != null ? query.Intersect(priceResults) : Enumerable.Empty<Deal>().AsQueryable();
My query is slow when priceList has more ten values.
I use Intersect for filters.
How to optimize these queries?
One idea for optimization would be to sort query by StartPrice ascending, that way your inner query can just stop traversal once StartPrice is higher than the DiscountPrice property:
var query = from deal in db.Deals
where deal.EndDate >= DateTime.UtcNow
orderby deal.DiscountPrice ascending
select deal;
..
foreach(..)
{
var startPrice = price.StartPrice;
var endPrice = price.EndPrice;
var queryLocal = query.SkipWhile(deal => deal.DiscountPrice < startPrice);
var priceResult = queryLocal.TakeWhile(deal => deal.DiscountPrice >= startPrice
&& deal.DiscountPrice <= endPrice);
..
}
You have a few issues. The first one is that the query is executed every iteration in your foreach loop. Calling ToList or ToArray will ensure that it is only executed once
Secondly the union is costly. It will iterate priceResult for every iteration of the foreach loop
thirdly your count will also iterate priceResult. Use .Any instead if you wish to know if theres any elements. However I think you can avoid that. If I've read your code correctly I believe the below should have the same result but it does not have the above three issues
var query = (from deal in db.Deals
where deal.EndDate >= DateTime.UtcNow
orderby deal.DiscountPrice ascending
select deal).ToList();
var priceResults = (from price in filters.Price.GetPriceRangeList()
let startPrice = price.StartPrice
let endPrice = price.EndPrice
select query.SkipWhile(d => deal.DiscountPrice < startPrice)
.TakeWhile(d => deal.DiscountPrice <= endPrice)
).SelectMany(x => x);
instead of iterating for each union there's a distinct only once
How can the below be converted to LINQ
SELECT Q.MaterialID AS MaterialID, Q.ProductID AS ProductID, QB.Quantity AS Quantity,
Q.ParameterID AS ParameterID, SUM((Q.ParameterValue * Q.Quantity)/Q.TotalTonnes) AS ParameterValue
FROM #Quality Q
INNER JOIN #QuantityBreakdown QB
ON ((Q.MaterialID = QB.MaterialID) OR (Q.MaterialID IS NULL AND QB.MaterialID IS NULL))
AND ((Q.ProductID = QB.ProductID) OR (Q.ProductID IS NULL AND QB.ProductID IS NULL))
GROUP BY Q.MaterialID, Q.ProductID, ParameterID, QB.Quantity
Am upto:
(from final in (from q in qualities
from qb in quantityBreakDowns
where q.MaterialID == qb.MaterialID && q.ProductID == qb.ProductID
select q)
group final by new {final.MaterialID, final.ProductID, final.ParameterID, final.Quantity}
into FinalResult
select new
{
FinalResult.Key.MaterialID,
FinalResult.Key.ProductID,
FinalResult.Key.ParameterID
//QB.Quantity AS Quantity ??
//SUM((Q.ParameterValue * Q.Quantity)/Q.TotalTonnes) AS ParameterValue ??
}
'??' => how to get these.
Is this right way to do ?
Thanks
I don't think we should be doing your LINQ query for you, but rather pointing you in the right direction to learn LINQ to SQL.
Otherwise the next query you have you will be in the same position.
C# 101 Linq to SQL Examples
VB.NET Linq to SQL 101 Examples
http://www.linqpad.com
http://www.hookedonlinq.com
http://dimecasts.net/Casts/ByTag/Linq2Sql
Something like this should do the trick.
I don't to LinqToSql though so you will need to checkup on how to get the IQuerable object. Otherwise this should point you in the right direction.
var results = from q in myIQuerableObject<Quality>
from qb on qb.MaterialId == q.MaterialId or (qb.MaterialId == null && q.MaterialId == null)
select new {Quality = q, Breakdown = qb}
Ok Sorted out this as :
var result = (from final in
(from q in qualities
from qb in quantityBreakDowns
where q.MaterialID == qb.MaterialID && q.ProductID == qb.ProductID
select q)
group final by
new {final.MaterialID, final.ProductID, final.ParameterID, final.Quantity}
into finalResult
select new
{
finalResult.Key.MaterialID,
finalResult.Key.ProductID,
finalResult.Key.ParameterID,
finalResult.Key.Quantity,
ParameterValue = finalResult.Sum(final => (final.ActualValue*final.Quantity/final.TotalTonnes))}).ToList();
Is this right ?