I have the following sequence:
public static List<string> IgnoredSubCodes => new List<string> {"HERE", "NOT_HERE"};
var demographics = personify.CUS_DEMOGRAPHIC.Where(demographic =>
clubIds.Contains(demographic.MASTER_CUSTOMER_ID) &&
distinctCodes.Contains(demographic.DEMOGRAPHIC_CODE) &&
distinctProgramYears.Contains(demographic.USR_PROGRAM_YEAR) &&
!demographic.DEMOGRAPHIC_SUBCODE.Any(x => PersonifyConstants.DemographicCodes.DemographicSubCodes.IgnoredSubCodes));
The last line above won't work but I'd like to be able to say "don't include any demographic subcode that appears in this list". How can I do that? I've tried a couple of different clauses with .Where and .Any but I'm not understanding the permutation I need. I could hardcode it inside that query as demographic.DEMOGRAPHIC_SUBCODE != "HERE" && demographic.DEMOGRAPHIC_SUBCODE != "NOT_HERE" but I'd like to have all the exclusions in one place.
Could you try this? Hope it will work.
var demographics = personify.CUS_DEMOGRAPHIC.Where(demographic =>
clubIds.Contains(demographic.MASTER_CUSTOMER_ID) &&
distinctCodes.Contains(demographic.DEMOGRAPHIC_CODE) &&
distinctProgramYears.Contains(demographic.USR_PROGRAM_YEAR) &&
!PersonifyConstants.DemographicCodes.DemographicSubCodes.IgnoredSubCodes.Any(code => code == demographic.DEMOGRAPHIC_SUBCODE));
Related
This code is case sensitive, how to make it case insensitive?
return HeaderNames.Length == fileLine.Count &&
HeaderNames
.Select(headItem => fileLine[Array.IndexOf(HeaderNames, headItem)] == headItem)
.All(i => i);
Thanks for your answers/
How about using FindIndex instead of IndexOf.
I assume you have array of strings
Array.FindIndex(HeaderNames, t => t.IndexOf(headItem, StringComparison.InvariantCultureIgnoreCase) >=0);
Example:
var a = new string[]{"green","red"};
var idx = Array.FindIndex(a, t => t.IndexOf("Red", StringComparison.InvariantCultureIgnoreCase) >=0);
Console.WriteLine(idx);
Output
1
Note: You could also use string.Equals instead of t.IndexOf in above suggestion
t=>string.Equals(t, headItem, StringComparison.InvariantCultureIgnoreCase)
It will be a long nested LINQ though.
Edit
If you want to find exact string i.e. dont want to get index of «ed» from «Red» as item existing in array. Use string.Equals.
There is no reason to index back into the array to get the position, there is a version of Select for that. You can use String.Equals and pass the StringComparison option:
return HeaderNames.Length == fileLine.Count &&
HeaderNames.Select((headItem, i) => fileLine[i].Equals(headItem, StringComparison.OrdinalIgnoreCase)).All(i => i);
I am attempting to use the following code to do an update on a table with entity framework. The where statement will only work if I remove the and, either side of the and will bring results, but the and results in a null. I know that the value I am searching for exists.
foreach (fdd element in FddList)
{
var slist = context.ResidenceFDDs.ToList<ResidenceFDD>();
ResidenceFDD fddtoupdate = slist
.Where(s =>
s.StName.Contains("Adrienne") &&
s.StNum == element.addressnumb.ToString())
.FirstOrDefault<ResidenceFDD>();
fddtoupdate.Comments = "Comment newly added.";
context.SaveChanges();
}
if you are using .toString() then use as below
ResidenceFDD fddtoupdate = slist.Where(
s =>
s.StName.Contains("Adrienne") &&
s.StNum == element.addressnumb.ToString())
.FirstOrDefault<ResidenceFDD>().AsEnumerable();
I am using EF4.3 with a unit-of-work + repository pattern.
I have a method which act as a base of some other methods, here's how the code looks.
This is my 'base' method:
public static IQueryable<Deal> FindActive()
{
var r = new ReadRepo<Deal>(Local.Items.Uow.Context);
return r.Find(d =>
d.ActiveFrom <= DateTime.Now &&
(d.ActiveUntilComputed == null || d.ActiveUntilComputed > DateTime.Now) &&
d.Published);
}
Here is one of the methods that calls the base method:
public static IQueryable<Deal> FindActiveByStore(int storeId)
{
Guard.Default(storeId, "storeId");
return FindActive().Where(d => d.StoreId == storeId);
}
As you can see in FindActiveByStore, I first call FindActive, which then chains Find(). FindActive is followed by a Where() to add a secondary predicate (excuse the terminology).
I wondered if it was possible to pass a predicate to FindActive instead of using a Where(), and in fact whether it would make a difference in terms of performance.
Like this:
FindActive(d => d.StoreId == storeId)
FindActive already passes a predicate to Find() so it would need to combine both.
I'm guessing that the answers I get back will be along the lines 'its not worth it' in terms of effort or performance but I thought i'd ask the experts anyway.
You can use this code (You reduce number lines of code)
public IQueryable<Deal> FindActiveByStore(Expression<Func<Deal,bool>> predicate)
{
var r = new ReadRepo<Deal>(Local.Items.Uow.Context);
return r.Find(d => d.ActiveFrom <= DateTime.Now
&& (d.ActiveUntilComputed == null || d.ActiveUntilComputed > DateTime.Now)
&& d.Published)
.Where(predicate);
}
from _tupleRows in this.TupleSet
from _member in _tupleRows.Members
where (_member.HasChildMembers && !_member.DrilledDown)
select new
{
_member1 = _member,
_member2 = (from _searched in this.TupleSet
from _compareMember in _searched.Members
where (_member.UniqueName == _compareMember.UniqueName &&
_member.LevelDepth == _compareMember.LevelDepth &&
_compareMember.DrilledDown)
select _compareMember).FirstOrDefault()
};
I need to convert this simple LINQ expression to an equivalent lambda expression
from _tupleRows in this.TupleSet
from _member in _tupleRows.Members
where (_member.HasChildMembers && !_member.DrilledDown)
select new
{
_member1 = _member,
_member2 = (from _searched in this.TupleSet
from _compareMember in _searched.Members
where (_member.UniqueName == _compareMember.UniqueName
&& _member.LevelDepth == _compareMember.LevelDepth
&& _compareMember.DrilledDown)
select _compareMember).FirstOrDefault()
};
becomes:
this.TupleSet
.SelectMany(tupleRows =>
tupleRows.Members
.Where(member => member.HasChildMembers && !member.DrilledDown)
.Select(member => new
{
_member1 = member,
_member2 = this.TupleSet
.SelectMany(searched =>
searched.Members
.Where(compareMember =>
member.UniqueName == compareMember.UniqueName
&& member.LevelDepth == compareMember.LevelDepth
&& compareMember.DrilledDown))
.FirstOrDefault(),
}));
They're really not hard to convert. Just start at the top and append as you go.
Something like:
this.TupleSet.SelectMany(ts => ts.Members)
.Where(m => m.HasChildMembers && !m.DrilledDown)
.Select(m => new
{
_member1 = m,
_member2 = this.TupleSet.SelectMany(ts => ts.Members)
.Where(other => m.UniqueName == other.UniqueName
&& m.LevelDepth == other.LevelDepth
&& other.DrilledDown
)
.FirstOrDefault()
});
No guarantees this is perfect or will even compile, but then I'm not trying to do your work for you, I'm trying to give you a demonstration of how you might do these conversions yourself.
Also, do yourself a favor and use simpler identifiers in lambdas when you can. They're very limited scope, and you're chaining calls to make one big statement, so often it will usually be very obvious in context what a variable means. I may not have the best example here, but the original variable names were way too verbose, IMO.
The nested query also seems a little strange. If there is a way to structure your data so you don't have to do that nested query I think you'll get better perf and simpler queries.
I am having an issue with getting linq to entities to perform well. The query I have (not mine, maintaining someone's code :-)), has several includes that I've determined are all necessary for the WPF screen that consumes the results of this query.
Now, the SQL generated executes very fast and only returns one row of data. But it is returning 570 columns, and i think the performance hit is in the overhead of creating all the objects and all of those fields.
I've tried using lazy loading, but that doesn't seem to have any effect on performance.
I've tried removing any of the "include" statements that aren't necessary, but it appears that they all are needed.
here's the linq query:
var myQuery =
from appt in ctx.Appointments
.Include("ScheduleColumnProfile")
.Include("EncounterReason")
.Include("Visit")
.Include("Visit.Patient")
.Include("Visit.Patient.PatientInsurances")
.Include("Visit.Patient.PatientInsurances.InsuranceType")
.Include("Visit.Patient.PatientInsurances.InsuranceCarrier")
.Include("MasterLookup")
.Include("User1")
.Include("User2")
.Include("Site")
.Include("Visit.Patient_CoPay")
.Include("Visit.Patient_CoPay.User")
.Include("Visit.VisitInstructions.InstructionSheet")
where appt.VisitId == visitId
&& appt.MasterLookup.LookupDescription.ToUpper() != Rescheduled
&& appt.Site.PracticeID == practiceId
&& appt.MasterLookup.LookupDescription.ToUpper() != Cancelled
orderby appt.AppointmentId descending
select appt;
The SQL generate is 4000 lines long with 570 columns in the select statment and 3 or 4 Union ALLs, so I'm not going to paste it here unless someone REALLY wants to see it. Basically, i'm looking for a way to get rid of the unions if possible, and trim down the columns to only what's needed.
Help!
:-)
if anyone is keeping track, this is the solution that ended up working for me. Thanks to everyone who commented and made suggestions... it eventually lead me to what i have below.
ctx.ContextOptions.LazyLoadingEnabled = true;
var myQuery =
from appt in ctx.Appointments
where appt.VisitId == visitId
&& appt.MasterLookup.LookupDescription.ToUpper() != Rescheduled
&& appt.Site.PracticeID == practiceId
&& appt.MasterLookup.LookupDescription.ToUpper() != Cancelled
orderby appt.AppointmentId descending
select appt;
var myAppt = myQuery.FirstOrDefault();
ctx.LoadProperty(myAppt, a => a.EncounterReason);
ctx.LoadProperty(myAppt, a => a.ScheduleColumnProfile);
ctx.LoadProperty(myAppt, a => a.Visit);
ctx.LoadProperty(myAppt, a => a.MasterLookup);
ctx.LoadProperty(myAppt, a => a.User1);
ctx.LoadProperty(myAppt, a => a.User2);
ctx.LoadProperty(myAppt, a => a.PatientReferredProvider);
var myVisit = myAppt.Visit;
ctx.LoadProperty(myVisit, v => v.Patient);
ctx.LoadProperty(myVisit, v => v.Patient_CoPay);
ctx.LoadProperty(myVisit, v => v.VisitInstructions);
ctx.LoadProperty(myVisit, v => v.EligibilityChecks);
var pat = myVisit.Patient;
ctx.LoadProperty(pat, p => p.PatientInsurances);
//load child insurances
foreach (PatientInsurance patIns in myAppt.Visit.Patient.PatientInsurances)
{
ctx.LoadProperty(patIns, p => p.InsuranceType);
ctx.LoadProperty(patIns, p => p.InsuranceCarrier);
}
//load child instruction sheets
foreach (VisitInstruction vi in myAppt.Visit.VisitInstructions)
{
ctx.LoadProperty(vi, i => i.InstructionSheet);
}
//load child copays
foreach (Patient_CoPay coPay in myAppt.Visit.Patient_CoPay)
{
ctx.LoadProperty(coPay, c => c.User);
}
//load child eligibility checks
foreach (EligibilityCheck ec in myAppt.Visit.EligibilityChecks)
{
ctx.LoadProperty(ec, e => ec.MasterLookup);
ctx.LoadProperty(ec, e => ec.EligibilityResponse);
}
I would recommend creating a new Class that contains only the properties that you need to display. When you project to a new type you don't need to have Include statements, but you can still access the navigation properties of the entity.
var myQuery = from appt in ctx.Appointments
where appt.VisitId == visitId
&& appt.MasterLookup.LookupDescription.ToUpper() != Rescheduled
&& appt.Site.PracticeID == practiceId
&& appt.MasterLookup.LookupDescription.ToUpper() != Cancelled
orderby appt.AppointmentId descending
select new DisplayClass
{
Property1 = appt.Prop1,
Proeprty2 = appt.Visit.Prop1,
.
.
.
};