How can I do this with one QueryOver statement - c#

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

How to iterate over a list to build a Linq query

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

Linq complex queries C#

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

Is there a way to set this entity/linq query to IEnumerable?

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

Select multiple child columns with the same filter

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

Convert string to guid in linq join query : conditional statement

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;
}

Categories