Reflected property(dynamic property) inside Linq lambda - c#

How can i replace x.Demographic.AgeRange with any other field?
Eg
var field_to_check = "Country";
x.Demographic.ReflectedProperty(field_to_check)=="USA"
var field_to_check = "AgeRnage";
x.Demographic.ReflectedProperty(field_to_check)=="20-30"
I Tried with a refelcted property. but cant succeed.
Favourability = db.Questions
.OrderByDescending(x => x.Responces.Count(y => y.Responseval == Constants.options.Agree || y.Responseval == Constants.options.Tend_to_Agree))
.Select(z => new
{
z.QuestionTitle,
Count = z.Responces.Where(x =>
x.Demographic.AgeRange == repval &&
(x.Responseval == Constants.options.Agree || x.Responseval == Constants.options.Tend_to_Agree)
)
.Count()
})
.Select(z => new
{
z.QuestionTitle,
z.Count,
Perc = ((z.Count / totresponcecount) * 100)
}
)
.ToList();
so that i can write only one linq statement as dynamic filtering rather than switch statements for all required properties.

You can construct the expression tree from multiple different ones. Use LinqKit, and write:
Expression<Func<Demography, string>> fieldSpec = d => d.AgeRange;
And then in your expession:
var exp = db.Questions.AsExpadable() ... fieldSpec.Expand(x.Demographic) == repval ...
Now all you need to do is construct the fieldSpec dynamically, which is an excercise for you :)

Related

How can I set the value of a parameter in a Select using LINQ?

I am trying to create a report using LINQ but having problems.
var AppVersion = Start
.Select(x => new AppVersionModel
{
DateYYMMDD = x.DateYYMMDD,
Android043 =
})
What I would like to do is to:
set the value of Android043 to be equal to a 1 here if (x => x.IsAndroid && x.AppVersion == "0.4.3")
But I am not sure how to do that. Can someone give advice to me.
Just wrap the expression inside parentheses to be unambiguous (though the parentheses are unnecessary)
IEnumerable<AppVersionModel> appVersion = Start
.Select( x => new AppVersionModel
{
DateYYMMDD = x.DateYYMMDD,
Android043 = ( x.IsAndroid && x.AppVersion == "0.4.3" )
} );
You can try,
var AppVersion = Start
.Select(x => new AppVersionModel
{
DateYYMMDD = x.DateYYMMDD,
Android043 = (x.IsAndroid && x.AppVersion == "0.4.3") ? 1 : //someothervalue
});

How to use the Exact array value instead of Contains [duplicate]

This question already has answers here:
LINQ equal instead of Contains
(3 answers)
Closed 5 years ago.
I need to use Equals method or something similar instead of using Contains method because i want to search in database for the exact values in selectedDeviceTypeIDs array not any of it.
IEnumerable<Guid> selectedDeviceTypeIDs = DeviceTypeIDs
.Split(',')
.Select( Guid.Parse )
.AsEnumerable();
query = query
.Where( j =>
j.HospitalDepartments.Any( jj =>
jj.Units.Any( m =>
m.Devices.Any( w =>
selectedDeviceTypeIDs.Contains( w.DeviceTypeID )
)
)
)
);
Here is my full code
public HttpResponseMessage GetAvailableHospitalsByAjax(System.Guid? DirectorateOfHealthID = null, System.Guid? UnitTypeID = null, string DeviceTypeIDs = null)
{
Context db = new Context();
var query = db.Hospitals.AsQueryable();
if (DeviceTypeIDs != null)
{
IEnumerable<Guid> selectedDeviceTypeIDs = DeviceTypeIDs.Split(',').Select(Guid.Parse).AsEnumerable();
query = query.Where(j => j.HospitalDepartments.Any(jj => jj.Units.Any(m => m.Devices.Any(w => selectedDeviceTypeIDs.Contains(w.DeviceTypeID)))));
}
if (UnitTypeID != null)
{
query = query.Where(j => j.HospitalDepartments.Any(www => www.Units.Any(u => u.UnitTypeID == UnitTypeID)));
}
if (DirectorateOfHealthID != null)
{
query = query.Where(h => h.DirectorateHealthID == DirectorateOfHealthID);
}
query = query.Where(j => j.HospitalDepartments.Any(u => u.Units.Any(d => d.Devices.Any(s => s.Status == Enums.DeviceStatus.Free)))
&& j.HospitalDepartments.Any(hd => hd.Units.Any(u => u.Beds.Any(b => b.Status == Enums.BedStatus.Free))));
var list = query.ToList();
return Request.CreateResponse(HttpStatusCode.OK, list);
}
Your problem is not Contains() but with the Any() method used in your query which will return true immediately after it finds a device whose DeviceTypeID is in the provided selectedDeviceTypeIDs list.
If you need to check if all the devices of a unit match all the items in the list, you could use:
query = query
.Where(j =>
j.HospitalDepartments.Any(jj =>
jj.Units.Any(m =>
m.Devices.All(
w => selectedDeviceTypeIDs.Contains(w.DeviceTypeID))
&&
selectedDeviceTypeIDs.All(
g => m.Devices.Select(d => d.DeviceTypeID).Contains(g))
)
)
);
Note that if you have duplicate items in the selectedDeviceTypeIDs but not in the Devices of the Unit, it will still return true.

Is it possible to insert a LinqKit PredicateBuilder as a sub query?

I've currently got a working multi level predicate shown below...
var predicate = PredicateBuilder.New<Patient>();
foreach (var code in codeArray) // ect..["AB12", "W231", "Q213"]
{
string localCode = code;
predicate.Or(p => p.Requests.Any(
u => u.Records.Any(
t => t.OutgoingRecords.Any(
s => s.Code == localCode)
)
)
);
}
res = query.AsExpandable().Where(predicate);
// Query is built up from an outside source and is eventually turned into a list via .ToListAsync()
Which is fine except as far as I'm aware it is producing a query in the form of...
query = p => p.PatientEpisodes.Any(u => u.EpisodeGroupings.Any(t => t.EpisodeDiagnoses.Any(s => s.Code == 'AB12'))) ||
p.PatientEpisodes.Any(u => u.EpisodeGroupings.Any(t => t.EpisodeDiagnoses.Any(s => s.Code == 'W231'))) ||
p.PatientEpisodes.Any(u => u.EpisodeGroupings.Any(t => t.EpisodeDiagnoses.Any(s => s.Code == 'Q213')))
Which is just overkill (and somewhat wrong) when all I really should be producing is...
query = p => p.PatientEpisodes.Any(u => u.EpisodeGroupings.Any(t => t.EpisodeDiagnoses.Any(s => s.Code == 'AB12' || s.Code == 'W312' || s.Code == 'Q213')))
Is there a way to insert the predicate at a sub level of a query such as below? My current attempts to do so have failed so far.
var predicate = PredicateBuilder.New<RecordCode>();
foreach (var code in codeArray)
{
string localCode = code;
predicate.Or(p => p.Code == localCode);
}
query = query.AsExpandable().Where(
s => s.Requests.Any(
c => c.Records.Any(
d => d.OutgoingRecords.Any(predicate))));
Many thanks in advance.

How to filter a Lambda expression from possible Querystrings in C#

I'm trying to filter results via a query string but not sure of the best way to do this, what i have so far is:
var topic = Request.QueryString["topic"];
var date = Request.QueryString["date"];
var keyword = Request.QueryString["keyword"];
if (!string.IsNullOrEmpty(topic) || !string.IsNullOrEmpty(date) || !string.IsNullOrEmpty(keyword))
{
items = root.Children().Where(x => x.IsDocumentType("Event-Item") &&
x.GetPropertyValue("eventTitle").ToString().Contains(topic) ||
x.GetPropertyValue("eventDates").ToString().Contains(date) ||
x.GetPropertyValue("eventSummary").ToString().Contains(keyword)).OrderByDescending(x => x.CreateDate).ToList();
}
else
{
items = root.Children().Where(x => x.IsDocumentType("Event-Item")).OrderByDescending(x => x.CreateDate).ToList();
}
Does this look correct? Is there a better(more correct) way of doing this?
Any help greatly appreciated.
How about conditional where for each term?
string topic = Request.QueryString["topic"];
string date = Request.QueryString["date"];
string keyword = Request.QueryString["keyword"];
var filteredItems = root.Children()
.Where(x => x.IsDocumentType("Event-Item"));
if (!string.IsNullOrEmpty(topic))
filteredItems = filteredItems.Where(x => x.GetPropertyValue("eventTitle")
.ToString()
.Contains(topic));
if (!string.IsNullOrEmpty(date))
filteredItems = filteredItems.Where(x => x.GetPropertyValue("eventDates")
.ToString()
.Contains(date));
if (!string.IsNullOrEmpty(keyword))
filteredItems = filteredItems.Where(x => x.GetPropertyValue("eventSummary")
.ToString()
.Contains(keyword));
items = filteredItems.OrderByDescending(x => x.CreateDate).ToList();
I would break it down as follows. You are always filtering on "Event-Item", so take that out of the if/else and do it first. Then check for nulls and filter if needed. Finally, since you are always sorting, do that after everything.
var topic = Request.QueryString["topic"];
var date = Request.QueryString["date"];
var keyword = Request.QueryString["keyword"];
items = root
.Children()
.Where(x => x.IsDocumentType("Event-Item"));
if (!string.IsNullOrEmpty(topic) || !string.IsNullOrEmpty(date) || !string.IsNullOrEmpty(keyword))
{
items = items.Where(x =>
x.GetPropertyValue("eventTitle").ToString().Contains(topic) ||
x.GetPropertyValue("eventDates").ToString().Contains(date) ||
x.GetPropertyValue("eventSummary").ToString().Contains(keyword));
}
items = items.OrderByDescending(x => x.CreateDate);

How to attach a set of 'And' filters to a QueryOver query?

My method has a parameter which will determine which column to perform a where filter on, so to make things generic I need to be able to perform some logic on which column I want to perform the where on.
Is it possible to attach a .And clause to a given QueryOver<> query?
public List<..> GetABC(SomeType type)
{
NHibernateHelper.Session.QueryOver<Blah>()
.Where(x => x.name = "")
.And(x => x.a) // if type == SomeType.A then x.a, otherwise x.b (SomeType.B)
}
How could I do this?
I know when doing a criteria query I could create a criteria and then attach it to the query.
Sure.
var query = NHibernateHelper.Session.QueryOver<Blah>()
.Where(x => x.name = "");
if(type == SomeType.A)
{
query = query.And(x => x.a == ...);
}
else
{
query = query.And(x => x.b == ... );
}
The query will only be executed after the ".List()"
Update: I don't know if you're refering to something like this (in your comment)
var query = NHibernateHelper.Session.QueryOver<Blah>()
.Where(x => x.name = "");
Expression<Func<Blah, bool>> typePredicate = null;
if(type == SomeType.A)
{
typePredicate = x => x.a == ...;
}
else
{
typePredicate = x => x.b == ...;
}
query = query.Where(typePredicate);
Or probably you're more interested in something in the likes of Detached queries?
Not sure I completely understand the question ... but something like this?
public List<..> GetABC(SomeType type)
{
NHibernateHelper.Session.QueryOver<Blah>()
.Where(x => x.name = "")
.And(x => typeof(type) == SomeType.A ? x.a : x.b)
}

Categories

Resources