Reputation: 6563
I have got a bad requirement to do; anyway I have to implement that in my application.
I have a Track
class
public class Track
{
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
and i have some test data
List<Track> Records = new List<Track>
{
new Track { City = "a", Name = "a", Country = "i" }, // Track 1
new Track { City = "b", Name = "b", Country = "i" }, // Track 2
new Track { City = "a", Name = null, Country = "J" }, // Track 3
new Track { City = "c", Name = "a", Country = "J" }, // Track 4
new Track { City = "b", Name = "a", Country = null}, // Track 5
};
Requirement is i should query the data from Records
based on values passed. If any of the property is null
then search criteria should ignore that property. It should query based on NonNull
properties.
Example:
If i query for City = a, Name = "b", Country = "i" then Result is: Track 1 & Track 3
If i query for City = c, Name = "p", Country = "w" then Result is: Track 4
Name
& Country
have null values in Track 3
& Track 5
.So it will ignore in search. Hope it is clear
I finally land up with below logic
var filterRecords = new List<Track>();
if (!Records.Any(t => string.IsNullOrWhiteSpace(t.City)))
{
filterRecords = Records.Where(c => c.City == _city).ToList(); // Here _city is the method parameter.. assume "a"
}
if (!Records.Any(t => string.IsNullOrWhiteSpace(t.Country)))
{
filterRecords = filterRecords.Where(c => c.City == _country).ToList(); // Here _country is the method parameter.. assume "c"
}
Track
class has 12 properties. Checking for 12 times like above is not good sign.
I would like to achieve this by using LINQ
or any other which is simple.
Any suggestions please?.
Upvotes: 3
Views: 2559
Reputation: 236218
Best solution came to my mind is to build aggregate filter (You can use your Track object for that, because it already has all possible properties for filtering collection, and they are nullable):
Track filter = records.Aggregate(
new Track() { City = _city, Country = _country, Name = _name },
(f, t) => new Track()
{
City = String.IsNullOrEmpty(t.City) ? null : f.City,
Country = String.IsNullOrEmpty(t.Country) ? null : f.Country,
Name = String.IsNullOrEmpty(t.Name) ? null : f.Name
},
f => f);
This will require only one iteration over collection to define which fields has null. Then simply apply filter to your records:
var query = from t in Records
where (filter.City == null || t.City == filter.City) &&
(filter.Country == null || t.Country == filter.Country) &&
(filter.Name == null || t.Name == filter.Name)
select t;
Upvotes: 6
Reputation: 431
something like this
var listRecords = from track in Records
where (track.city == _city && !string.IsEmpyOrNull(track.city)) &&
(track.Name== _name && !string.IsEmpyOrNull(track.Name))
select track;
and you can add the rest of the conditions
Upvotes: -1
Reputation: 14361
do the quality and quantity of results returned matter to you? I assume you have mechanisms to handle the quantity.
You can validate your search keywords before throwing queries. Do you only care about nulls? How about redundant keywords? I would consider: 1. validate keywords - 12 can be looped. 2. Build the search keyword strong 3. Shoot a query
Seems pretty straightforward, unless there's more to it than what you described here.
Please recorrect me, if my understanding of your question is not in the expected direction.
Upvotes: 0
Reputation: 48686
If I'm understanding, it should be this simple:
var results = Records.Select(p => p.City != null &&
p.Country != null &&
p.Name != null).ToList();
Upvotes: 0
Reputation: 41236
You can easily chain these expressions together to create something like the following. Enumerating the records X times is going to slow down your code. Example:
var actualResult = Records
.Where(x => x.City == _city || string.IsNullOrEmpty(x.City))
.Where(x => x.Country == _country || string.IsNullOrEmpty(x.Country))
/// .... and so on
.ToList()
Now, if you're looking to not just write 12 lines of code, there are more complicated solutions that involve Reflection and mapping, but that's not really needed in this situation. If your property count is huge, then maybe it might be worth it. But 12 properties is small enough that there isn't much code smell here to me.
Upvotes: 0