Get a value using Ling to XML and where clause - linq

I want to use Linq to XML and I am trying to figure out to way to get the value for currency CAD, BuyRateForeign, basically I need to get value 5,602895.
<ExchRates>
<ExchRate>
<Bank>Bank</Bank>
<CurrencyBase>USD</CurrencyBase>
<Date>24.05.2013.</Date>
<Currency Code="036">
<Name>AUD</Name>
<Unit>1</Unit>
<BuyRateCache>5,569450</BuyRateCache>
<BuyRateForeign>5,625707</BuyRateForeign>
<MeanRate>5,711378</MeanRate>
<SellRateForeign>5,797049</SellRateForeign>
<SellRateCache>5,855019</SellRateCache>
</Currency>
<Currency Code="124">
<Name>CAD</Name>
<Unit>1</Unit>
<BuyRateCache>5,546866</BuyRateCache>
<BuyRateForeign>5,602895</BuyRateForeign>
<MeanRate>5,688218</MeanRate>
<SellRateForeign>5,773541</SellRateForeign>
<SellRateCache>5,831276</SellRateCache>
</Currency>
</ExchRate>
</ExchRates>

var xDoc = XDocument.Load("path/to/your.xml");
var cadForeignBuyRate =
xDoc.Root.Element("ExchRate").First(e => e.Element("Bank").Value == "Bank")
.Elements("Currency").First(e => e.Element("Name").Value == "CAD")
.Element("BuyRateForeign").Value;

var xDoc = XDocument.Load("path/to/your.xml");
var BuyRateForeign = from nm in xDoc.Descendants("Currency")
where (string)nm.Element("Name") == "CAD"
select (string)nm.Element("BuyRateForeign");
Using Lambda expression
var stringRate = xDoc.Descendants("Currency")
.Where(p=> (string)p.Element("Name") == "CAD")
.Select(p => (string)p.Element("BuyRateForeign"))
.SingleOrDefault();

Related

Get Group sum not using group.Sum() in linq

The following query works, but I want to get the same result without using grp.Sum(). Can we do it?
from item in (await VehicleReplaceCostDataAsync())
group item by (item.type, item.size, item.ADA, item.eseq) into grp
orderby (grp.Key.eseq, grp.Key.size, grp.Key.ADA)
select new VehicleReplacementCost
{
type = grp.Key.type,
size = grp.Key.size,
ADA = grp.Key.ADA,
count = grp.Sum(x => x.count),
cost = grp.Sum(x => x.cost),
Fcount = grp.Sum(x => x.Fcount),
Fcost = grp.Sum(x => x.Fcost),
eseq = grp.Key.eseq,
}).ToList();
Perhaps by using .Aggregate()? [docs]
count = grp.Aggregate(0, (a, b) => a + b.count)
Thanks for the answer from Astrid. It looks like a good one, but I didn't test it. My colleague gave this solution instead by using yield:
var groups = costs
.GroupBy(type => (type.SystemId, type.Type, type.Size, type.ADA, type.Eseq))
.OrderBy(group => (group.Key.SystemId, group.Key.Eseq, group.Key.Size, group.Key.ADA));
foreach (var group in groups)
{
var result = new ProgramGuideVehicleCostRow
{
SystemId = group.Key.SystemId,
Type = group.Key.Type,
Size = group.Key.Size,
ADA = group.Key.ADA,
};
foreach (var row in group)
{
result.Cost += row.Cost;
result.Fcost += row.Fcost;
result.Count += row.Count;
result.Fcount += row.Fcount;
}
yield return result;
}

Date filtering in Linq

Hi I'm trying to filter my result with a date.
What I tried so far:
var lastYear = (DateTime.Now.Year) - 1;
var salesLastYear = _documentService.GetDocuments(
d => d.DocumentTypeId == saleDocumentId &&
d.EffectiveOnUtc.Contains(lastYear))
.Select(d => d.Id).ToList();
var salesLastYear = _documentService.GetDocuments(
d => d.DocumentTypeId == saleDocumentId &&
(d.EffectiveOnUtc.Year == lastYear))
.Select(d => d.Id).ToList();
Both gave no errors in visual studio, but did raise an exeption during execution.
Also tried to convert both the values to a string, but that also failed.
Working on the assumption that your EffectiveOnUtc is a DateTime, and you want to filter to records within the previous calendar year:
int lastYear = DateTime.Now.Year - 1;
DateTime minDate = new DateTime(lastYear, 1, 1);
DateTime maxDate = minDate.AddYears(1);
var salesLastYear = _documentService.GetDocuments(
d => d.DocumentTypeId == saleDocumentId
&& d.EffectiveOnUtc >= minDate
&& d.EffectiveOnUtc < maxDate)
Select(d => d.Id).ToList();

Using Any to check against a list in NHibernate

I am trying to get all #events where that have a FiscalYear.id inIList<int> years. I am using any() but it is throwing the following stacktrace error:
Unrecognised method call:
System.Linq.Enumerable:Boolean Any[TSource](System.Collections.Generic.IEnumerable`1[TSource], System.Func`2[TSource,System.Boolean])
Any Ideas? Here is the code:
FindAllPaged(int eventTypeId, IList<int> aors, IList<int> years)
{
IList<Domain.Event> results =
session.QueryOver<Event>()
.Where(#event => !#event.IsDeleted &&
#event.EventType.Id == eventTypeId &&
years.Any(y => y == #event.FiscalYear.Id))
}
Looks like you are trying to use a Linq method in QueryOver. This isn't supported. Try using the Linq provider instead:
FindAllPaged(int eventTypeId, IList<int> aors, IList<int> years)
{
IList<Domain.Event> results =
session.Query<Event>()
.Where(#event => !#event.IsDeleted &&
#event.EventType.Id == eventTypeId &&
years.Any(y => y == #event.FiscalYear.Id))
}
I also encountered the same exception message
Unrecognised method call:
System.Linq.Enumerable:Boolean Any[TSource](System.Collections.Generic.IEnumerable1[TSource], System.Func2[TSource,System.Boolean])
when using IqueryOver with Contains method
Ex:
var departmentTypesArray = criteria.DepartmentTypes.ToArray();
qover = qover.Where(p => departmentTypesArray.Contains(p.DepartmentType));
when i check the database, i don't have any records inside the table that i am making query.
when i changed my query with Restrictions, then it works for me
qover = qover.WhereRestrictionOn(p => .DepartmentType).IsIn(departmentTypesArray);
Try using the Contains method instead:
IList<Domain.Event> results = session
.QueryOver<Event>()
.Where(e => !#event.IsDeleted &&
#event.EventType.Id == eventTypeId &&
years.Contains(#event.FiscalYear.Id))
.ToList();
Or build your restrictions the long way using IsIn:
IList<Domain.Event> results = session
.QueryOver<Event>()
.Where(e => !#event.IsDeleted && #event.EventType.Id == eventTypeId)
.And(Restrictions.On<Event>(#event => #event.FiscalYear.Id)
.IsIn(years.ToArray()))
.ToList();
You could try this:
IList<Domain.Event> results = session.QueryOver<Event>().ToList().FindAll(e => !e.IsDeleted && e.Id.Equals(eventTypeId) && years.Contains(e.FiscalYear.Id))

LINQ Performance Issue on only a few hundred records

in the following code i've commented on the line that SLOWS my page right down. I did some speed test to reveal the CONTAINS LINQ expression is the problem.
Does anyone know how to change this one line to be more efficient using something else instead. I'm also curious as to why its so slow.
Any ideas (thanks in advance):
var allWaste = _securityRepository.FindAllWaste(userId, SystemType.W);
var allWasteIndicatorItems = _securityRepository.FindAllWasteIndicatorItems();
// First get all WASTE RECORDS
var searchResults = (from s in allWaste
join x in allWasteIndicatorItems on s.WasteId equals x.WasteId
where (s.Description.Contains(searchText)
&& s.Site.SiteDescription.EndsWith(searchTextSite)
&& (s.CollectedDate >= startDate && s.CollectedDate <= endDate))
&& x.EWC.EndsWith(searchTextEWC)
select s).Distinct();
var results = searchResults.AsEnumerable();
if (hazardous != "-1")
{
// User has requested to filter on Hazardous or Non Hazardous only rather than Show All
var HazardousBoolFiltered = (from we in _db.WasteIndicatorItems
.Join(_db.WasteIndicators, wii => wii.WasteIndicatorId, wi => wi.WasteIndicatorId, (wii, wi) => new { wasteid = wii.WasteId, wasteindicatorid = wii.WasteIndicatorId, hazardtypeid = wi.HazardTypeId })
.Join(_db.HazardTypes, w => w.hazardtypeid, h => h.HazardTypeId, (w, h) => new { wasteid = w.wasteid, hazardous = h.Hazardous })
.GroupBy(g => new { g.wasteid, g.hazardous })
.Where(g => g.Key.hazardous == true && g.Count() >= 1)
select we).AsEnumerable(); // THIS IS FAST
// Now join the 2 object to eliminate all the keys that do not apply
if (bHazardous)
results = (from r in results join x in HazardousBoolFiltered on r.WasteId equals x.Key.wasteid select r).AsEnumerable(); //This is FAST
else
results = (from r in results.Where(x => !HazardousBoolFiltered
.Select(y => y.Key.wasteid).Contains(x.WasteId)) select r).AsEnumerable(); // This is DOG SLOW 10-15 seconds !--- THIS IS SLOWING EXECUTION by 10 times --!
}
return results.AsQueryable();
I suggest using a logging / tracing framework like smart inspect or log4net combined with a debug text writer.
http://www.codesprouts.com/post/View-LINQ-To-SQL-Statements-Using-A-Debug-TextWriter.aspx
another possibility is to use the sql server profiler and see what sql linq2sql produces.
also a very nice way is to use the mvc mini profiler in combination with the Profiled DB Connection and the SqlFormatters.SqlServerFormatter.
Try Any (MSDN)
Try this:
results = (from r in results
.Where(x => !HazardousBoolFiltered
.Any(y => y.Key.wasteid == r.WasteId)))
.AsEnumerable()
Or Count:
results = (from r in results
.Where(x => HazardousBoolFiltered
.Count(y => y.Key.wasteid == r.WasteId) == 0))
.AsEnumerable()

Error trying to exclude records with a JOIN to another object

In my code below, is there any way I can use the results in the object 'WasteRecordsExcluded' to join with searchResults, essentially excluding the WasteId's I don't want.
If I debug to the last line I get the error :
base {System.SystemException} = {"The query contains references to items defined on a different data context."}
Or if joining is impossible then i could change bHazardous from TRUE to FALSE and FALSE to TRUE and do some kind of 'NOT IN' comparison.
Going bananas with this one, anyone help? Kind Regards :
var allWaste = _securityRepository.FindAllWaste(userId, SystemType.W);
var allWasteIndicatorItems = _securityRepository.FindAllWasteIndicatorItems();
// First get all WASTE RECORDS
var searchResults = (from s in allWaste
join x in allWasteIndicatorItems on s.WasteId equals x.WasteId
where (s.Description.Contains(searchText)
&& s.Site.SiteDescription.EndsWith(searchTextSite)
&& (s.CollectedDate >= startDate && s.CollectedDate <= endDate))
&& x.EWC.EndsWith(searchTextEWC)
select s).Distinct();
var results = searchResults;
if (hazardous != "-1")
{
// User has requested to filter on Hazardous or Non Hazardous only rather than Show All
var WasteRecordsExcluded = (from we in _db.WasteIndicatorItems
.Join(_db.WasteIndicators, wii => wii.WasteIndicatorId, wi => wi.WasteIndicatorId, (wii, wi) => new { wasteid = wii.WasteId, wasteindicatorid = wii.WasteIndicatorId, hazardtypeid = wi.HazardTypeId })
.Join(_db.HazardTypes, w => w.hazardtypeid, h => h.HazardTypeId, (w, h) => new { wasteid = w.wasteid, hazardous = h.Hazardous })
.GroupBy(g => new { g.wasteid, g.hazardous })
.Where(g => g.Key.hazardous == bHazardous && g.Count() >= 1)
select we);
// Now join the 2 object to eliminate all the keys that do not apply
results = results.Where(n => WasteRecordsExcluded.All(t2 => n.WasteId == t2.Key.wasteid));
}
return results;
Maybe something like this:
.....
var results = searchResults.ToList();
.....
.....
.Where(g => g.Key.hazardous == bHazardous && g.Count() >= 1)
select we).ToList();
.....

Resources