How to do a LINQ query with Split operation - c#

I have the following linq query:
MyClass myobj = (from p in Session.All<MyClass>()
where p.tags.Split(' ').Contains(searchTag)
select p).FirstOrDefault();
When I run this, I get:
System.NotSupportedException: LINQ to Entities does not recognize the
method 'System.String[] Split(Char[])' method, and this method cannot
be translated into a store expression.
What is a good way to do what I am attempting to do?

The real problem here is the db design, but assuming you have no control over this one idea is to split the query.
First retrieve any rows that contain the search tag anywhere within them.
List<MyClass> myobjs = (from p in Session.All<MyClass>()
where p.tags.Contains(searchTag)
select p).ToList();
Then perform the correct tag search on the retrieved objects in memory.
MyClass myobj = myobjs.FirstOrDefault(m => m.tags.Split(' ').Contains(searchTag));

So, assuming tags = tag1 tag2 tag3, and searchTag is tag2 you can just do:
MyClass myobj = (from p in Session.All<MyClass>()
where p.tags.IndexOf(searchTag) > -1
and searchTag.IndexOf(" ") == -1
select p).FirstOrDefault();

Related

Invalid 'where' condition. An entity member is invoking an invalid property or method

I've tried several methods to serach a client who have a propritaire.id in membresEquipeDuClient list, but each time I'm getting the "Invalid 'where' condition. An entity member is invoking an invalid property or method."-error!
I got the error in the second request,
The methods I've used :
List<TeamMembership> membresEquipeDuClient = (from k in context.CreateQuery<TeamMembership>()
where k.teamid == equipeDuClient.Id
select k).ToList();
var pRechercheNumeroClient = (from p in context.CreateQuery<Client>()
where membresEquipeDuClient.Any(a => a.systemuserid == p.proprietaire.Id)
select p).FirstOrDefault();
Any idea how to fix this?
Thx for all the help!
As said in the comment, Any is not supported, but Contains is. So you can do:
var systemUserIds =
(
from k in context.CreateQuery<TeamMembership>()
where k.teamid == equipeDuClient.Id
select k.systemuserid // Select the Id only
).ToList();
var pRechercheNumeroClient =
(
from p in context.CreateQuery<Client>()
where systemUserIds.Contains(p.proprietaire.Id)
select p
).FirstOrDefault();
I'm not familiar with Dynamics CRM, but I think you can remove the ToList from the first statement, so it will be an IQueryable and both statements will be executed as one expression.
var pRechercheNumeroClient = (from p in context.CreateQuery<Client>()
where membresEquipeDuClient.Select(a => a.systemuserid).Contains(p.proprietaire.Id)
select p).FirstOrDefault();

MVC search a LINQ query

I have a very simple query
var query = (from s in db.Stocks
select s).ToList();
and now basically I want to then search that query to see if any of the stock objects names in the query contain "a"
I have this
if(!string.IsNullOrEmpty(searchModel.Name) )
{
query = query.Where(x => x.Name.Contains(searchModel.Name));
}
but I am getting this error
Cannot implicity convert type "system.collections.generic.ienumerable<etc etc> to system.collections.generic.list
How can I search my query result?
Its ok I have the answer
I just need to add .ToList to the end of my query statement like so
if(!string.IsNullOrEmpty(searchModel.Name) )
{
query = query.Where(x => x.Name.Contains(searchModel.Name)).ToList();
}
The reason is because in the first query
var query = (from s in db.Stocks
select s).ToList();
you have fixed the data type of the variable query to be List (toList()) . Now when you query it again with Where it returns IEnumerable and can't be assigned to the type List . You can do it in one line as in below
var query = from s in db.Stocks
where s.contains(searchModel.Name)
select s
try
query = query.Where(x => x.Name.Contains(searchModel.Name)).ToList();
you can re-write the query as following:
var query = (from s in db.Stocks.ToList()
where !string.IsNullOrEmpty(searchModel.Name) ? s.Contains(searchModel.Name) : true
select s).ToList();
the new added line means: if SearchModel.Name is filled then search using it, otherwise do nothing
or you can keep your code as it, but add .ToList() after the table name, or remote .ToList() on the end of your query code which enforce the datatype of result

Checking the contents of a LINQ query that is being added to

I'm creating a LINQ query that needs to check on the contents before adding something from the list, so what I have is this
var foo = (from f in list1
from p in list1.list2
from m in p.Bar
let t = m.Type
let c = someMethod(t)
where c.Type == type && !foo.Contains(p)
select p).ToList();
the !foo.Contains(p) is not allowed, so is there a way of checking the query as it goes along or before the ToList() should I just add Distinct() to do the same as the condition?
There is no way to access the query as it is being built in the manner you are doing. If you want to ensure that a particular value only appears once in the output then Distinct is the best approach

A simple query on LINQ

var q = from child in doc.Descendants("level")
where (int)child.Attribute("id") == 55
select (string)child.Element("Points").**Value.ToString()**;
I would like to get q as a type string after executing this query. Even after keeping the extra bolded line this is giving me some IEnumerable type.
Well let me put it this way. I would like to make the above query something like below one without the runtime throwing any error.
string q = from child in doc.Descendants("level")
where (int)child.Attribute("id") == 55
select (string)child.Element("Points");
Any help?
var q = (from child in doc.Descendants("level")
where (int)child.Attribute("id") == 55
select (string)child.Element("Points")).FirstOrDefault();
Enumerable.FirstOrDefault Method (IEnumerable)
LINQ will always return an enumerable result. To get it to evaluate and return one result you can use
.First()
.FirstOrDefault()
.Single()
.SingleOrDefault()
depending on your requirement.
The query will return IEnumerable even if the result contains single record. Try this -
if q.count() > 0
var singleQ = q.First();
Or if you are sure that there will be atleast one record then do it like this -
string q = (from child in doc.Descendants("level")
where (int)child.Attribute("id") == 55
select (string)child.Element("Points")).First();

Doing a Cast Within a LINQ Query

Is it possible to do a cast within a LINQ query (for the compiler's sake)?
The following code isn't terrible, but it would be nice to make it into one query:
Content content = dataStore.RootControl as Controls.Content;
List<TabSection> tabList = (from t in content.ChildControls
select t).OfType<TabSection>().ToList();
List<Paragraph> paragraphList = (from t in tabList
from p in t.ChildControls
select p).OfType<Paragraph>().ToList();
List<Line> parentLineList = (from p in paragraphList
from pl in p.ChildControls
select pl).OfType<Line>().ToList();
The code continues on with a few more queries, but the gist is I have to create a List out of each query in order for the compiler to know that all of the objects in content.ChildControls are of type TabSection and all of the objects in t.ChildControls are of type Paragraph...and so on and and so forth.
Is there a way within the LINQ query to tell the compiler that t in from t in content.ChildControls is a TabSection?
Try this:
from TabSection t in content.ChildControls
Also, even if this were not available (or for a different, future scenario you may encounter), you wouldn't be restricted to converting everything to Lists. Converting to a List causes query evaluation on the spot. But if you removing the ToList call, you could work with the IEnumerable type, which would continue to defer the execution of the query until you actually iterate or store in a real container.
Depending on what you are trying to do, one of these might do the trick:
List<Line> parentLineList1 =
(from t in content.ChildControls.OfType<TabSection>()
from p in t.ChildControls.OfType<Paragraph>()
from pl in p.ChildControls.OfType<Line>()
select pl).ToList();
List<Line> parentLineList2 =
(from TabSection t in content.ChildControls
from Paragraph p in t.ChildControls
from Line pl in p.ChildControls
select pl).ToList();
Note that one uses OfType<T>(), which you were using. This will filter the results and return only the items of the specified type. The second query implicitly uses Cast<T>(), which casts the results into the specified type. If any item cannot be cast, an exception is thrown. As mentioned by Turbulent Intellect, you should refrain from calling ToList() as long as possible, or try to avoid it altogether.
List<TabSection> tabList = (from t in content.ChildControls
let ts = t as TabSection
where ts != null
select ts).ToList();
yes you can do the following:
List<TabSection> tabList = (from t in content.ChildControls
where t as TabSection != null
select t as TabSection).ToList();
And here's the query method form.
List<Line> parentLineList =
content.ChildControls.OfType<TabSections>()
.SelectMany(t => t.ChildControls.OfType<Paragraph>())
.SelectMany(p => p.ChildControls.OfType<Line>())
.ToList();

Categories