This statement is using a foreach which I am trying to get rid of:
CBTAppointmentDto app = null;
ModifyAppointmentRequest alias = null;
Domain.PearsonVue.TestCenter center = null;
Exam exam = null;
var result = Session.QueryOver(() => alias)
.Where(x => x.Candidate.Id == candidateId)
.Where(x => x.EventType == "ApptCreated")
.JoinAlias(x => x.Exams, () => exam)
.JoinAlias(() => alias.TestCenter, () => center)
.SelectList(list => list
.Select(() => exam.ExamName).WithAlias(() => app.TestName)
.Select(() => exam.ExamSeriesCode)
.WithAlias(() => app.ExamSeriesCode)
.Select(() => alias.AppointmentStartTime)
.WithAlias(() => app.TestDate)
.Select(() => center.TestCenterName)
.WithAlias(() => app.TestCenterName))
.TransformUsing(Transformers.AliasToBean<CBTAppointmentDto>())
.List<CBTAppointmentDto>().ToList();
foreach (var cbtAppointmentDto in result)
{
var session = Session.QueryOver<TestSession>()
.Where(x => x.SessionName == cbtAppointmentDto.ExamSeriesCode)
.SingleOrDefault();
if (session == null) continue;
cbtAppointmentDto.TestStartDate = session.TestsStartDate;
cbtAppointmentDto.TestEndDate = session.TestsEndDate;
}
return result;
Is there a way to do it with aQueryOver statement only?
Any suggestions ?
to save roundtrips use batch selects with ToFutureValue
var sessions = results.Select(cbtAppointmentDto => Session.QueryOver<TestSession>()
.Where(x => x.SessionName == cbtAppointmentDto.ExamSeriesCode)
.FutureValue()).ToOList();
for (int i = 0; i < sessions.Count; i++)
{
var session = sessions[i].Value;
if (session != null)
{
results[i].TestStartDate = session.TestsStartDate;
results[i].TestEndDate = session.TestsEndDate;
}
}
Related
I have the following working query:
posts.Where(post =>
post.Fields
.Where(x =>
x.RegionId == "RecipeArticleDetails" &&
(x.FieldId == "RecipePrepTime" || x.FieldId == "RecipeCookTime")
)
.GroupBy(x => x.PostId)
.Select(x => new { ID = x.Key, Value = x.Sum(y => Convert.ToInt32(y.Value)) })
.Where(x => x.Value > 10 && x.Value < 40)
.Any()
)
List<string> suppliedTimes = new List<string>(){
"10-60","0-10"
};
I would like to replace Where(x => x.Value > 10 && x.Value < 40) so it looks up from a list of ranges:
List<string> suppliedTimes = new List<string>(){
"10-60","0-10"
};
My understanding is I can use select to iterate over the items:
posts.Where(post =>
suppliedTimes.Select(x => new {low = Convert.ToInt32(x.Split("-",StringSplitOptions.RemoveEmptyEntries)[0]), high = Convert.ToInt32(x.Split("-",StringSplitOptions.RemoveEmptyEntries)[1]) })
.Any( a =>
post.Fields
.Where(x =>
x.RegionId == "RecipeArticleDetails" &&
(x.FieldId == "RecipePrepTime" || x.FieldId == "RecipeCookTime")
)
.GroupBy(x => x.PostId)
.Select(x => new { ID = x.Key, Value = x.Sum(y => Convert.ToInt32(y.Value)) })
.Where(x => x.Value > a.low && x.Value < a.high)
.Any()
)
)
However this code results in the error:
could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Please can someone explain how I can achieve this and why what I have isn't working.
To make it work with EF Core I would suggest my extnsion FilterByItems and change the way how to retrieve records.
List<string> suppliedTimes = new List<string>(){
"10-60","0-10"
};
var ranges = suppliedTimes
.Select(x => x.Split("-", StringSplitOptions.RemoveEmptyEntries))
.Select(x => new {
low = Convert.ToInt32(x[0]),
high = Convert.ToInt32(x[1])
});
var fields = context.Fields
.Where(x =>
x.RegionId == "RecipeArticleDetails" &&
(x.FieldId == "RecipePrepTime" || x.FieldId == "RecipeCookTime")
)
.GroupBy(x => x.PostId)
.Select(x => new { ID = x.Key, Value = x.Sum(y => Convert.ToInt32(y.Value)) })
.FilterByItems(ranges, (e, r) => e.Value > r.low && e.Value < r.high, true);
var posts = posts
.Join(fields, p => p.Id, f => f.ID, (p, f) => p);
i have this:
int item = particleEdges.ElementAt(i).Key;
Point3 hashPoint = particleEdges[item][j].hashEdge;
var hashList = particleEdges
.Where(p => p.Value.Any(q => q.hashEdge == hashPoint))
.Select(r => r.Key != item)
.ToList();
How to exclude "item" from hashList? Broke my head. Linq doesn't want to open to me.
var hashList = particleEdges
.Where(p => p.Value.Any(q => q.hashEdge == hashPoint))
.Where(r => r.Key != item)
.Select(s => s.Key)
.ToList();
I'm trying to return an IEnumerable activities instead of "var"
var activities = ctx.Activities.Where(a => a.SiteID == propID)
.Where(a => a.ActivityTypeName == "Call")
.Select(x => new
{
x.DateTimeEntry,
x.Contact.OwnerContact.ParcelDatas
.FirstOrDefault(a => a.OwnerContactID == x.Contact.OwnerContact.OOwnerID)
.Parcel_LetterTracking.LMailDate,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID)
.FAQ_Library.FaqNum,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID)
.FAQ_Library.Question
});
edit: data type Object compiles but I'm not sure if that's right.
.Select already returns a an IEnumerable<TResult> also combine your ..where() clauses with && instead. https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.select?view=netframework-4.8 also one other thing you can do is use .AsEnuemerable()
var activities = ctx.Activities.Where(a => a.SiteID == propID && a.ActivityTypeName == "Call")
.Select(x => new
{
x.DateTimeEntry,
x.Contact.OwnerContact.ParcelDatas.FirstOrDefault(a => a.OwnerContactID == x.Contact.OwnerContact.OOwnerID).Parcel_LetterTracking.LMailDate,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID).FAQ_Library.FaqNum,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID).FAQ_Library.Question
}).AsEnumerable();
I have this Linq lambda expression which generates abnormally complex SQL select to database. Is it somehow possibility to simplify it?
var devices = db.Devices
.Where(a => a.active == true)
.Select(a => new DeviceToDisplay
{
Id = a.Id,
serialNumber = a.serialNumber,
deviceRegion = a.deviceRegion,
activeIP = a.IPaddresses.Where(b => b.active == true).Select(b => b.IPaddress1).FirstOrDefault(),
Wip = a.IPaddresses.Where(b => b.active == true).Select(b => b.W_IP).FirstOrDefault(),
Sip = a.IPaddresses.Where(b => b.active == true).Select(b => b.S_IP).FirstOrDefault(),
model = a.SPdatas.Where(c => c.model != "").OrderByDescending(c => c.collectionDate).Select(c => c.model).FirstOrDefault(),
firmware = a.SPdatas.Where(c => c.model != "").OrderByDescending(c => c.collectionDate).Select(c => c.firmware).FirstOrDefault(),
lastMPteamActivity = a.activityLogs.OrderByDescending(c => c.updatedDate).Select(c => c.updatedDate).FirstOrDefault(),
country = a.MPPinformations.Select(c => c.country).FirstOrDefault()
});
For a start, your linq query looks very complicated. Imagine how you would implement this by writing a SQL query for example.
A suggestion: you are writing things like:
a.IPaddresses.Where(b => b.active == true).
and
a.SPdatas.Where(c => c.model != "").OrderByDescending(c => c.collectionDate).
in multiple places.
Instead you could create an anonymous type. For example,
var foo = from x in sb.Devices.Where(a=> a.active)
select new { Id = x.ID,
IPAddress = a.IPaddresses.Where(b => b.active), ... }
You can then use foo to create your Devices object.
See if this is any better:
var devices = db.Devices
.Where(a => a.active == true)
.Select(a => new DeviceToDisplay {
Id = a.Id,
serialNumber = a.serialNumber,
deviceRegion = a.deviceRegion,
activeIP = a.IPaddresses.Where(b => b.active == true).FirstOrDefault(),
SPdata = a.SPdatas.Where(c => c.model != "").OrderByDescending(c => c.collectionDate).FirstOrDefault(),
lastMPteamActivity = a.activityLogs.OrderByDescending(c => c.updatedDate).Select(c => c.updatedDate).FirstOrDefault(),
country = a.MPPinformations.Select(c => c.country).FirstOrDefault()
})
.Select(a=> new DeviceToDisplay {
Id=a.Id,
serialNumber=a.serialNumber,
deviceRegion=a.deviceRegion,
activeIP=a.activeIP.IPaddress1,
Wip=a.activeIP.W_IP,
Sip=a.activeIP.S_IP,
model=a.SPdata.model,
firmware=a.SPdata.firmware,
lastMPteamActivity=a.lastMPteamActivity,
country=a.county
});
I have linq query as below
using (RMPortalEntities _RMPortalEntities = new RMPortalEntities()) {
var _RSVP_ButtonLocations = _RMPortalEntities
.tbl_RSVP_ButtonLocation
.Join(_RMPortalEntities.tbl_RSVP_Setting,
_RSVP_ButtonLocation => Guid.Parse(_RSVP_ButtonLocation.ID),
_RSVP_Setting => _RSVP_Setting.RSVP_Button_Location_ID,
(_RSVP_ButtonLocation, _RSVP_Setting) => new { _RSVP_ButtonLocation, _RSVP_Setting })
.Join(_RMPortalEntities.tbl_Event,
_RSVP_ButtonLocation_RSVP_Setting => _RSVP_ButtonLocation_RSVP_Setting._RSVP_Setting.EventID,
_Event => _Event.ID,
(_RSVP_ButtonLocation_RSVP_Setting, _Event) => new { _RSVP_ButtonLocation_RSVP_Setting, _Event })
.Where(x => x._Event.Active == true
&& x._Event.ID == _EventID)
.Select(x => new
{
RSVP_ButtonLocations = x._RSVP_ButtonLocation_RSVP_Setting._RSVP_ButtonLocation.RSVP_ButtonLocation
});
return _RSVP_ButtonLocations.FirstOrDefault().RSVP_ButtonLocations;
}
But problem is linq query does not allow me to convert string to Guid value.
Could anyone give me suggestion please?
Building on CjCoax comment you can store an instance of GUID and then use it later in the query:
using (RMPortalEntities _RMPortalEntities = new RMPortalEntities()) {
var GUID = new Guid(_RMPortalEntities.tbl_RSVP_ButtonLocation.ID);
var _RSVP_ButtonLocations = _RMPortalEntities
.tbl_RSVP_ButtonLocation
.Join(_RMPortalEntities.tbl_RSVP_Setting,
_RSVP_ButtonLocation => GUID,
_RSVP_Setting => _RSVP_Setting.RSVP_Button_Location_ID,
(_RSVP_ButtonLocation, _RSVP_Setting) => new { _RSVP_ButtonLocation, _RSVP_Setting })
.Join(_RMPortalEntities.tbl_Event,
_RSVP_ButtonLocation_RSVP_Setting => _RSVP_ButtonLocation_RSVP_Setting._RSVP_Setting.EventID,
_Event => _Event.ID,
(_RSVP_ButtonLocation_RSVP_Setting, _Event) => new { _RSVP_ButtonLocation_RSVP_Setting, _Event })
.Where(x => x._Event.Active == true
&& x._Event.ID == _EventID)
.Select(x => new
{
RSVP_ButtonLocations = x._RSVP_ButtonLocation_RSVP_Setting._RSVP_ButtonLocation.RSVP_ButtonLocation
});
return _RSVP_ButtonLocations.FirstOrDefault().RSVP_ButtonLocations;
}