Doing a Cast Within a LINQ Query - c#

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();

Related

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

How to do a LINQ query with Split operation

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();

The type arguments for method 'System.Linq.Queryable.SelectMany System.Linq.IQueryable

While editing my Repository class an Error pops out
var applicantList = (from a in context.Profiles
join app in context.APPLICANTs
on a.PROFILE_ID equals app.Profile_id into joined
from j in joined.DefaultIfEmpty()//.OrderBy(v => v.APPLICANT_ID)
select j //<-- this is APPLICANTs type
).Take(1000);
applicantdata = applicantList
.SelectMany(c => c.APPLICANTs) //this line added
.AsQueryable().OrderBy(v => v.APPLICANT_ID).ToList();
if (applicantdata.Any())
{
Cache.Set("applicants", applicantdata, 30);
}
}
return applicantdata;
Im having an exception at
.SelectMany(c => c.APPLICANTs) //this line added
saying that :
The type arguments for method 'System.Linq.Queryable.SelectMany(System.Linq.IQueryable, System.Linq.Expressions.Expression>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
SelectMany accepts a collection of object which each of them have a collection property inside.
You selected APPLICANTs collection at the first statement and running a SelectMany on it doesn't seem to be meaningful.
Checkout these links to understand the SelectMany better.
http://msdn.microsoft.com/en-us/library/bb534336.aspx
Difference Between Select and SelectMany
SelectMany is used for 'flattening' a list of lists. You don't have a list of lists here. You have a list of anonymous joined rows.
It's a bit difficult to infer what you're querying for, but if you're looking to get the related rows (the APPLICANTs rows), you can use this:
var applicantList = (from a in context.Profiles
join app in context.APPLICANTs
on a.PROFILE_ID equals app.Profile_id
select app).Take(1000)

Convert.Int64 Is Not Reconized LINQ To Entities

I am getting the following exception:
LINQ to Entities does not recognize the method 'Int64 ToInt64(System.String)' method, and this method cannot be translated into a store expression.
I had long.Parse(ProjectID.ToString()) and I see the suggestion was to use Convert.ToInt64 but I am still getting the same exception
string projID = ProjectFileID.ToString();
var d = (from f in context.FileInfo
where f.ID == Convert.ToInt64(projID)
select (f));
Just do the conversion outside the query, so you compare the results directly to a variable of type long:
// TODO: Error handling
long projID = Convert.ToInt64(ProjectFileID.ToString());
var d = (from f in context.FileInfo
where f.ID == projID
select (f));
Also, given that you're calling ToString() on ProjectFileID, can you maybe just cast it instead, since it certainly seems like it's an int or something along those lines.
The reason is that it tries to do the conversion inside the query itself and the behind the scenes SQL has no definition for that Extension. The workaround is doing the conversion to long outside of the query (to a temp variable) and passing that in to the LINQ.

LINQ Query Except not working, List<long?> vs. List<long>

What I'm trying to do is narrow the results of a query that I will use to databind later on. I want to get all of the ProgramIds that are used in my gridview, and remove them from the datasource of my dropdownlist (ie, so that a user cannot choose to create and insert an object into the gridview of the same ProgramId as one that already exists)
Here's some code:
var query = from goals in DataContext.Goals
select goals;
var query2 = (from goals in query.AsEnumerable()
select goals.ProgramId).ToList(); //List<long?>
var query3 = (from progs in DataContext.Programs
select progs.ProgramId).ToList(); //List<long>
var cgps = query3.Except(query2);
And I'm getting these errors on var cgps = query3.Except(query2); :
Error 29 'System.Collections.Generic.List' does not contain a definition for 'Except' and the best extension method overload 'System.Linq.ParallelEnumerable.Except(System.Linq.ParallelQuery, System.Collections.Generic.IEnumerable)' has some invalid arguments C:...\Shmeh\Shmeh\Shmeh\this.aspx.cs 24 226 Project
Error 30 Instance argument: cannot convert from 'System.Collections.Generic.List' to 'System.Linq.ParallelQuery' C:...\Shmeh\Shmeh\Shmeh\this.aspx.cs 24 226 Project
If you have any idea how to validly do what I'm trying to do, any help would be greatly appreciated! Thanks!
Except requires that the sequences are both of the same type. Try casting the long list to long?:
var query3 = (from progs in DataContext.Programs
select (long?)progs.ProgramId).ToList(); //List<long?>
You're getting this error because long? is not the same type as long. Except requires both enumerable objects to be of the same type.
What you could do is remove the null values from query2 and convert ProgramId to long
var query2 = (from goals in query.AsEnumerable()
where goals.ProgramId.HasValue
select goals.ProgramId.Value).ToList()
try
var cgps = query3.Cast<long?>().Except(query2);
var cgps = DataContext.Programs.Select(p => p.ProgramId)
.Except(DataContext.Goals.Where(g => g.ProgramId.HasValue).Select(g => g.ProgramId.Value));
I don't know if this will work for you.
var query2 = (from goals in query.AsEnumerable()
select goals.ProgramId).ToList() as List<long?>;
var query3 = (from progs in DataContext.Programs
select (long?)progs.ProgramId).ToList() as List<long?>;
I don't know why he/she deleted their answer, but I'm using this:
dropdownlist.DataSource = (
from progs in DataContext.Programs
where !(from goals in query.AsEnumerable()
select goals.ProgramId)
.Contains(progs.ProgramId)
select progs.Name).ToList();
dropdownlist.DataBind();
Because it doesn't require me to use multiple query variables, although the answer I accepted worked as well with what I had.

Categories