Basic LinqToSql question: Why won't this compile? - c#

I've been introducing myself to LinqToSQL lately through a poorly-made project at work. I'm curious as to why this works:
var territories = db.Territories.Where(t => t.PendingUserCount > 0);
But this results in a compilation error:
var territories = db.Territories;
if (someCondition)
territories = territories.Where(t => t.PendingUserCount > 0);
// Cannot implicitly convert 'System.Linq.IQueryable<Territory> to System.Data.Linq.Table<Territory>
I've also tried to call db.Territories.ToList(), but to no avail.
I'm sure it's just a misunderstanding of how Linq works, but I'd be appreciative if someone could help me out.

db.Territories returns a table object. Hence the 'var' will be of type System.Data.Linq.Table. Later you try (based on some condition) to assign something of type System.Linq.IQueryable to the variable. As .NET is strongly typed, the compiler throws an error.
Variables of type var will be assigned a type when they get assigned first. That's how I try to remember myself.

For this type of cumulative Where, you need to tell the compiler to use IQueryable<T>:
IQueryable<Territory> territories = db.Territories;
if (someCondition)
territories = territories.Where(t => t.PendingUserCount > 0);
... etc

Alternative:
var territories = db.Territories.AsQueryable();
if (someCondition)
territories = territories.Where(t => t.PendingUserCount > 0);

change to this
var territories = db.Territories;
to
IQueryable territories = db.Territories.Where(t => t.PendingUserCount > 0);
The reasoning is that by calling db.Territories, you are getting all the data back, returning it in a linq.table object. Db.Territores.where(... will return an IQueryable object instead.

One of the potentially confusing things about "var" is that its type is determined at compile time, so you can't assign a range of different types to it. People with experience of dynamic languages, like Python, sometimes get confused by this, at first.

Your var territories is typed as a System.Data.Linq.Table<Territory> initially and then you are trying to assign the results of a Where clause (which is of type System.Linq.IQueryable<Territory>) to it.
Remember that the compiler infers the type of a var at assignment so once it is assigned the type cannot be changed.
Try something like this:
System.Linq.IQueryable<Territory> territories;
if (someCondition)
territories = db.Territories.Where(t => t.PendingUserCount > 0);

Because you've typed "var" as a Table<Territory> and then try to reassign it as a IQueryable<Territory>.
This is equivalent to saying
var i = 0
i = "a string";
EDIT: To clarify, var is implicitly strong typed at compile time not run time, unlike dynamically typed scripting language.

You can't re-assign a var to a different type after you've declared it. So your var declaration has already typed it to System.Data.Linq.Table.
It's a fire once thing.

You need to use the IQueryable tyupe as others have suggested:
also this linq query maybe also work:
var query = from territories in db.Territories
where territories.SomeProperty == SomeCondition
where territories.PendingUserCount > 0
select territories;

Related

List to IEnumerable in a Async method

I have a method:
public Task<IEnumerable<MyDetails>> HandleAsync(...)
Within this method, I simply build a list of items.
IEnumerable<MyDetails> myDetails = new List<MyDetails> {
new MyDetails{ Name = 'John' },
new MyDetails{ Name = 'James' },
new MyDetails{ Name = 'Anne' },
};
And then return the result.
return Task.FromResult(insuraceTypeDetails);
In a code review, I'm being asked to use var instead of IEnumerable<MyDetails>
However, when attempting that, I get an error on my return:
Cannot convert type Threading.Tasks.Task<List> to
Threading.Tasks.Task<IEnumerable>
I thought this would be fine, but the compiler will not allow it. Can I use var here? Or am I correctly explicitly telling the compiler what we need?
In a code review, I'm being asked to use var instead of IEnumerable<MyDetails>
var will infer the type the variable from the intialization, in this cast a List<MyDetails>. But as you have discovered, you need the variable to be an IEnumerable<MyDetails> to match the return type.
You could do something goofy like convert it to an IEnumerable:
return Task.FromResult(insuraceTypeDetails.AsEnumerable());
or do an explicit cast:
return Task.FromResult((IEnumbrable<MyDetails>)insuraceTypeDetails);
but those are just working around a dogmatic coding style. There's absolutely nothing wrong with explicitly declaring the variable type, especially when using the inferred type does not work.
Use IEnumerable<MyDetails> and explain to your colleagues why var is not the right choice here.

return a List< Id:int, Name:string>

I am having a function which return a list of type: List< Id:Name, Name:string >
how do you do specify in C# to return this List Type ?
Here is the code:
public ?????? GetDepartements( int idRegion )
{
var a = (from o in _meilleurPrestaEntities.Departements
where o.de_id_region == idRegion
select new {Id = o.id_departement, Name = o.nom}).ToList();
return a;
}
the return is used as Json result.
thanks
I'd suggest using a key value pair
return List<KeyValuePair<int,string>>()
[Edit] You'll need to modify your code slightly - it should look something like this:
var a = (from o in _meilleurPrestaEntities.Departements
where o.de_id_region == idRegion
select new KeyValuePair<int,string>(o.id_departement,o.nom}).ToList();
You can't. You have a list of anonymous type and you can't specify anonymous type as part of a method return type (or pretty much anywhere else, unless you can use var).
To fix this, you have several options:
Create normal class to represent the return type and use that in your return type.
Use something like List<Tuple<int, string>>.
Return List<dynamic>. This way, you will be able to treat the returned value as usual, but you will get no compile-time checking or IntelliSense.
Return List<object>. This can be useful if you don't need to access the properties in the usual way, but you will only pass the result to something that uses reflection.
I think you have to specify a type and then use that type for your return value and in your select statement.
I don't have VisualStudio open to try it, but I think you can actually return dynamic in this case. Or you could use ExpandoObject.
However, as others have mentioned, the "better" way is to use something like Tuple or KeyValuePair, or don't be lazy and just make an actual model for what you will return to the view (in other words, a "View Model").

What is the exact use of var keyword? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use of var keyword in C#
After discussion with colleagues regarding the use of the 'var' keyword in C# 3 I wondered what people's opinions were on the appropriate uses of type inference via var?
For example I rather lazily used var in questionable circumstances, e.g.:-
foreach(var item in someList) { // ... } // Type of 'item' not clear.
var something = someObject.SomeProperty; // Type of 'something' not clear.
var something = someMethod(); // Type of 'something' not clear.
More legitimate uses of var are as follows:-
var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.
Interestingly LINQ seems to be a bit of a grey area, e.g.:-
var results = from r in dataContext.SomeTable
select r; // Not *entirely clear* what results will be here.
It's clear what results will be in that it will be a type which implements IEnumerable, however it isn't entirely obvious in the same way a var declaring a new object is.
It's even worse when it comes to LINQ to objects, e.g.:-
var results = from item in someList
where item != 3
select item;
This is no better than the equivilent foreach(var item in someList) { // ... } equivilent.
There is a real concern about type safety here - for example if we were to place the results of that query into an overloaded method that accepted IEnumerable<int> and IEnumerable<double> the caller might inadvertently pass in the wrong type.
Personally I find the circumstances you describe far from questionable, since there is no point in repeating yourself unless you specifically want the static type of a variable to be different than the static type of the expression used to initialize the variable. For example:
IEnumerable<int> foo = new List<int>(); // It's IEnumerable on purpose
Furthermore, there are absolutely no type safety concerns with var. The point is not that the variable can be of "any" type. It is of a very specific type, but you simply do not care to spell that type out.
I'm only using it as a place holder until I'm sure which datatypes I'm using.
Sure this is a short answer but I think it's pretty close that when you should use the var keyword.
the var keyword is used as shorthand in the language, but isn't a .NET type. The compiler must know the type of the variable to use the var keyword - so it is type-safe.
I personally only use it if the type name is also used in the assignment and the name is possible too long to duplicate in the code.
var dictionary = new Dictionary<string, string>();
It is also used for anonymous types (but still, the compiler must know the signature of the anonymous type).
var fred = new { Age = 23, Name = "Fred" };
This method is used commonly in the select clause of LINQ queries.
Just an "abstraction" or "syntax sugar" to be able to write a code without specifying first the type (this is no your first cases)
In second case: LINQ queries, instead, to rapresent some unknown, dynamic, not concrete, if you wish, type.
could be:
var results = from item in someList
where item != 3
select item; //item a class instance
could be
var results = from item in someList
where item != 3
select item.ItemName; //string property of that class
could be
var results = from item in someList
where item != 3
select new {item.ItemName, item.ID}; //unknown type dynamically generated, that conains the string and integer, like result
As far as I know var remains strong typed. The compiler calculated what the proper type should be. In fact it has no real meaning.
It is only a trick to reduce the number of manipulations. For instance when you change a type in one class, this can result in a cascade of modification. But its only a way to migrate work from the programmer to the compiler.
For instance your Linq query will result in a type IEnumerable<TA>. When you change some class so the result will be IEnumerable<TB> there is no need to change this part of the code.

IEnumerable<T> assignment

I have two objects declared as IEnumerable<DateTime> xVal and IEnumerable<double> yVal.
Then some where is my program I have:
var xVals = from p in result where p.chemical == "Benzene" select p.SampDate_Name;
var yVals = from p in result where p.chemical == "Benzene" select p.PCL;
Then I am trying to the following assignment:
xVal = xVals as IEnumerable<DateTime>;
yVal = yVals as IEnumerable<double>;
And the above code sets xVal and yVal to null.
Could anybody explain what is wrong here? I would very much appreciate the help.
Thanks.
One thing is certain: The input is not null. So xVals and yVals are non-null as debugged by me. I am also able to loop through them to get the content of each.
I will try the other suggestions when I get back and post my findings. Thanks a lot folks for your replies.
The problem here was that LINQ is executed lazy, It will be executed when you do either foreach or ToList/ToArray/ToDictionary. The two linq queries in my code were not executed before the assignment was done. Consequently xVal and yVal were set to null.
Thanks for all the help.
The as keyword will set the output to null if the input was null or the cast could not be carried out.
If you used xVal = (IEnumerable<DateTime>)xVals you would probably get an exception saying that it could not be cast.
MSDN description for as keyword
If you have a generic collection, to get it to IEnumerable, try .AsEnumerable(). So your new code...
xVal = xVals.AsEnumerable();
yVal = yVals.AsEnumerable();
The as keyword doesn't actually do a cast, but does conversions between related reference types. So if you have a concrete type, you could treat assign it to a new variable with a type of the base class using as. If the types are not compatible, then as will return null. This is a good way to do type checking without having to worry about exceptions. Instead you can perform a null check on the result of the conversion.
It's hard to tell what types p.SampDate_Name and p.PCL are, but I would guess strings? If so you can add the cast to the select statement.
var xVals = from p in result where p.chemical == "Benzene" select DateTime.Parse(p.SampDate_Name);
var yVals = from p in result where p.chemical == "Benzene" select Double.Parse(p.PCL);

How get propery value of an dynamic type?

[update]
I'm sorry, i should tag this question
as MVC-2, I pass result of query into
view's model, so i must specify type
of my model in View's header
defintion. I declare it like this:
Inherits="System.Web.Mvc.ViewPage<IQueryable<dynamic>>"
how ever nothing changed and none of
answers doesn't work for me :(.
finally i used an ModelView class as
helper to put my query result in it.
:(
[/update]
I have a query like this:
IQueryable<dynamic> result = from d in KiaNetRepository.KiaNetEntities.Discounts
where d.AgentTypeID == agentTypeId
select new { d.Category, d.DiscountValue, d.PriceConfige };
then i retrive value in my view like this:
foreach(var item in result){
Category cat = item.Category; // throws exception 'object' does not contain a definition for 'Category'
//...
}
note that type of query as IQueryable is anonymouse class...
Try to declare names explicitly:
select new { Category = d.Category, DiscountValue = d.DiscountValue, PriceConfige = d.PriceConfige }
If you are not forcing result to be of IQueryeable<dynamic> for any specific reason, I would recommend using var result = .... This will let the compiler make result of type IQueryable<T> with T the type of the anonymous class that you create using new { ... } in the select. There is no necessity for using dynamic from the code that you show here.
If you replace the inappropriate declaration IQueryable<dynamic> by var, sure it works, I've just also tested it.
Your problem is that your foreach loop being in the view page gets compiled into a separate assembly. Since anonymous types are internal the dynamic doesn't see it because of the permissions don't allow it.
Simplest fix is to call ToList() on your query statement and then select each anonymous type and copy parameters to a declared class or expandoobject.

Categories

Resources