This is my first post in this site.
I have a list of vehicles in my database and every vehicle has a Vin (License Plate Number, in example "6TRJ244", it is a string value).
I receive a list of search values, in example "A", "B","J"
I need to filter the vehicles which Vin Contains one of the search values.
In example if I have three vehicles with Vin: Vehicle1_Vin = "123AJ", Vehicle2_Vin = "123BJ", Vehicle3_Vin = "777CR"
If I receive as search values "X", "A","C" I should return Vehicles 1 and 3
With LINQ I am trying to do something like this
var searchParams = new List<string>() { "A", "B", "C"};
vehicles = vehicles.Where((vehicle) => searchParams.Any((searchParam) => vehicle.Vin.Contains(searchParam)));
But I receive this error message
"System.InvalidOperationException: The LINQ expression 'searchParam => EntityShaperExpression:
ProjectAlpha.BusinessObjects.Models.Vehicle
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
.Vin.Contains(searchParam)' 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."
Thanks ins advance!
You could try use functions if you are using net core try with something like this
IQueryable<T> nightClub = nightClub.Where(nc => EF.Functions.Like(nc.Name, "%Dfox%");
It is not clear what collection type vehicles variable is so better introduce new variable or transfer IEnumerable to same type as source collection (ToArray/ToList etc):
var searchParams = new List<string>() { "A", "B", "C"};
var filtered = vehicles.Where(vehicle => searchParams.Any(vehicle.Vin.Contains));
Related
I have a field "details" varchar(MAX) in my table with the detailed description of an item, I need to select the records that contain the keywords passed by the user in a string array.
var searchTerms = new List<string> { "car", "black", "bike", "blue" };
I tried to do it like this:
var result = (from i in _contexto.itens
where searchTerms.Any(d => i.details.Contains(d))
select i.id);
and I get the following error:
The LINQ expression 'DbSet()
.Where(i => __searchTerms_0
.Any(d => i.details.Contains(d)))' 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.
I also tried this link's approach using the "SearchExtensions nuget package" and the same error occurs.
How can I do this? or should I make a query for each item in the array?
Example of a text I want to search for:
It is a long established fact that a car will be distracted by the
readable content of a page when looking at its bike. The point of
using Lorem Ipsum is that it has a more-or-less normal distribution
Thanks!
var searchTerms = new List<string> { "car", "black", "bike", "blue" };
string examplestring = "It is a long established fact that a car will be distracted by the readable content of a page when looking at its bike. The point of using Lorem Ipsum is that it has a more-or-less normal distribution";
var result = searchTerms.Select(s => (examplestring.Contains(s)) ? (object)searchTerms.IndexOf(s) : null).Where(w => w != null).ToList();
Adapting Alexander's advice from the link you gave, for your situation:
var searchTerms = new List<string> { "car", "black", "bike", "blue" };
Expressions<Func<TYPE_OF_OBJECT_IN_ITENS_HERE, bool>> expression = it => false;
foreach(var searchTerm in searchTerms)
{
expression = expression.Or(it => it.details.Contains(searchTerm));
}
var result = _contexto.itens.Where(expression);
You didn't post any detail about the type of object inside itens, so you'll have to replace that above
I have this dictionary Dictionary<string, List<Payments>>, which holds employees, each employee having a list of payments. The Payments class has a string property named PayCategoryId. I want to filter this dictionary and get only the employees with payments having some specific PayCategoryId values and for each employee only those payments. I'm pretty sure this can be achieved by using LINQ, but I have almost zero experience with LINQ, so need your help.
The original (unfiltered) dictionary has 76 items (employees). The employee which I'll use as an example has 27 payments, some of them having the required PayCategoryId.
What I've done:
List with the required PayCategoryId:
var payCategoriesID = new List<string> (){ "a", "b", "c" };
Semi-filter the dictionary with this LINQ (I'm sure it's a mess, but is working!):
var result = dict.Where(o => o.Value.Where(x => payCategoriesID.Contains(x.PayCategoryId)).Any()).ToDictionary(mc => mc.Key, mc => mc.Value);
The semi-filtered resulted dictionary has only 34 items. The employees having no payments with the required PayCategoryId were filtered out. But my example employee still has all 27 payments in the list. I need his list to be filtered too and have only the payments having PayCategoryId = one of the IDs from payCategoriesID list.
Of course, the example employee is just an example, all employees should be filtered.
Can you help, please?
Adrian
You can use Select() to project into an enumerable of anonymous type and get only the value you want, then build back a dictionary.
var match = dict
.Select(kv => new
{
Employee = kv.Key,
Payments = kv.Value.Where(p => payCategoriesID.Contains(p.PayCategoryId))
})
.Where(emp => emp.Payments.Any())
.ToDictionary(k => k.Employee, v => v.Payments);
The first step creates an object with key and filtered values, then the Where() remove the empty lists. That way you only iterate through the ids list once (per element on the dictionary).
Also, not really related, but the Any() method has an overload which takes a predicate, so instead of
o.Value.Where(x => payCategoriesID.Contains(x.PayCategoryId)).Any()
you can do directly
o.Value.Any(x => payCategoriesID.Contains(x.PayCategoryId))
Same goes for other LINQ methods such as Count(), First(), FirstOrDefault(), Last() and more.
var result = dict.Where(o => o.Value.Where(x => payCategoriesID.Contains(x.PayCategoryId)).Any()).ToDictionary(mc => mc.Key, mc => mc.Value.Where(t=> payCategoriesID.Contains(t.PayCategoryId)));
I have an unknown number of complex keys passed into my function at runtime. They will be structured like this:
var keys = new List<List<string>>
{
new List<string> { "1", "a" },
new List<string> { "2", "b" },
new List<string> { "3", "c" }
};
The inner list will always have two values. The outter list could have n values. I am attempting to query a table where records match any of the pairs in the List. I tried this query like this:
var filtered =
dataContext.T.Where(
s => keys.Any(k =>
k[0] == s.Column0
&& k[1] == s.Column1));
At this point, LinqToEntities fails because it seems that linq is unable to process lists (or arrays?) inside an .Any() method.
This is the error I get when I run this code:
"LINQ to Entities does not recognize the method 'System.String get_Item(Int32)' method, and this method cannot be translated into a store expression."
So my question is, how can I query for records that match any pair of values in the lists? I can change anything about the structure as long as I can query for any in a set of pairs.
Thanks for any guidance.
Don't think you can use any enumerable like that in linq 2 entities.
One workaround would be to concatenate your pairs, with a "should never appear" string in the middle.
var concatenatedkeys = keys.Select(m => m[0] + "~" + m[1]).ToList();
var filtered =
dataContext.T.Where(s => concatenatedKeys.Contains(
s.Column0 ?? string.Empty +
"~" +
s.Column1));
The answer does solve the problem that I posed in the question. However, I ran into a similar issue once I needed to compare values across linked entities.
The concatenation solution ran into problems with this scenario:
var filtered =
dataContext.T.Where(s => concatenatedKeys.Contains(
s.AnotherEntity.Column0 ?? string.Empty +
"~" +
s.AnotherEntity.Column1));
To solve this, I ended up using LinqKit to create the .Where() expression using the PredicateBuilder.
I'm using EF and have a context from which I can get a collection of Item objects using _inventoryContext.Items. Now, these item objects have a string value called Carrier. Let's say there are 5 items in Items collection and they have these Carrier values:
"A", "A", "B", "C", "C"
How do I use _inventoryContext.Items to get back the unique carrier values?
"A", "B", "C"
Note that
var carriers = _inventoryContext.Items.Select(i => i.Carrier).Distinct();
does not work; I get "The method 'Distinct' is not supported" with no inner exception.
I'm using SQL Server 2008 Express. Items is a DataServiceQuery<Item> and its Carrier property is a string.
Your example should work, but here is another way you can try
List<string> carriers = _inventoryContext.Items.GroupBy(i => i.Carrier)
.Select(i => i.Key)
.ToList();
I'm having a List<List<String>>, and which contains
{ {"A" , "B" },
{"C" , "D" }
}
I need to union all the innerlist into another list
So the resulting List<String> will contain
{"A","B","C","D"}
Now im using for loop to do this
Is there any way to do this Using LINQ or Lambda Expression.
Please help me to do this.
Thanks in advance.
Not Exactly a Union, but you can try this
YourList.SelectMany(l=>l).Distinct()
List<List<string>> collections = new List<List<string>>()
{
new List<string>(){"A" , "B" },
new List<string>() {"C" , "D" }
};
var list = collections.SelectMany(x => x).ToList();
SelectMany builds up a expression tree that when evaluated flattens the list of list to a single list of combined members.
ToList forces the expression tree to be evaluated and which results in a List.
If you want to eliminate duplicates you can add a Distinct call before the call to 'ToList()'
You can use the SelectMany extension method.
List<List<String>> masterList = { {"A" , "B" }, {"C" , "D" } };
IEnumerable<string> results = masterList.SelectMany(l => l);
var result = myLists.SelectMany(l => l);
How about Aggregate?
myLists.Aggregate((left, right) => left.Union(right));
To me, this is more expressive than using SelectMany, because it is telling you exactly what you are doing: Aggregate your list of lists by calling union on them all.
Just for kicks:
(from list in theList from e in list select e).Distinct().ToList()
This is of course the same solution as #Alexander Taran's, just with query syntax instead of lambda syntax. (Or at least it should be – I don't have my LINQPad handy.)