asgerhallas

Hi,

I've been looking at this for several hours now, and can't find a solution. Hopeyou can help:

I have a presenter class which sets the following Query on the view:

Code Block

var query = from c in db.Consultants

select new

{

c.ConsultantId,

c.Initials

};

this.view.Consultants = query;

Now I try to test the presenter in my unit tests and find out if the IQuerable returns the expected results:

Code Block

foreach (var r in mockView.Consultants)

{

Assert.AreEqual(1, r.ConsultantId);

Assert.AreEqual("AHL", r.Initials);

}

But it keeps saying that r has the type object and r.ConsultantId and r.Initials are not to be found. I have tryed several things to try to run the query and get out the results in this anonymous type, but I just can't make it work. Does anybody here have a hint

Kind regards

Asger



Re: LINQ Project General Linq, Iquerable and anonymous types

Niz0r

The var "type" can't pass between functions, it's intended for local scope only, the consequenses are truly dire.





Re: LINQ Project General Linq, Iquerable and anonymous types

asgerhallas

Well, sometimes you just have to write down your problems. An obvious solution is to use reflection:

Code Block

foreach (var consultant in caseView.Consultants)

{

PropertyInfo ConsultantId = consultant.GetType().GetProperty("ConsultantId");

Assert.AreEqual(1, ConsultantId.GetValue(consultant, null));

PropertyInfo Initials = consultant.GetType().GetProperty("Initials");

Assert.AreEqual("AHL ", Initials.GetValue(consultant, null));

}

That works Smile

Better suggestions are of course very welcome!

/Asger





Re: LINQ Project General Linq, Iquerable and anonymous types

Rick Strahl

A better solution is usually to try and cast the result set to a specific type. If it works out that you can map to an existing entity type use that, otherwise you can manually create a result type and set the result to IQueryable<yourCustomType>.

Using Reflection works but as you know it can be very slow in iterative situations. Note that that if you're using databinding operations especially in ASP.NET that object binding uses Reflection internally anyway so you can use var results passed out of a calling method as a datasource.

Another option is that you can cast the var result to something else if you choose. You can 'cast' DataReader or DataTable with just a little work running the command object associated with the query object. In some situations this may actually provide much better performance (especially in databinding situations) although it does work against some of the very concepts that make LINQ so enticing in the first place.

+++ Rick ---





Re: LINQ Project General Linq, Iquerable and anonymous types

Wael Farag

Try to use an exact type as your view.Consultants for example:

Code Block

IEnumerable<Consultant> query = from c in db.Consultants

select new Consultant

{

c.ConsultantId,

c.Initials

};

Where Consultant is the class of the view.Consultants collection






Re: LINQ Project General Linq, Iquerable and anonymous types

asgerhallas

Thank you very much for your answers both of you!

@Rick

A custom type would be good, if it wasn't for the fact that I have to make twenty or thirty of them for this rather large application then. Therefore I really liked the idea for anonymous types, but unfortunately there is no way to cast to a anonymous type. I know there is a work around for this:

Code Block

public T Cast<T> (object obj, T type)

{

return (T)obj;

}

But I can't make that work for a collection!

The cost of reflection seems ok in my particular situation as it is unit tests and I don't have to iterate over the collection. The foreach in my code is there just because I can't figure out how to retrieve just a single row from a Queryable which returns a collection

The DataReader and DataTable idea sound very good. I will look into that. I'm fairly new to .NET (but not new to programming Smile ), so there is many aspects of it I didn't even know existed.

Thank you very much for your answer.

/Asger





Re: LINQ Project General Linq, Iquerable and anonymous types

asgerhallas

@Wael

My view consultants need to be an IQueryable so I can use it easy with databinding in the view. I am using that a lot. If I made an exact type and executed the query and just returned the result to the view, I guess I would still be able to databind, but I would again end up with twenty types just for the query-results, and the databinding would still do reflection.

I just really wish that the compiler could infer an anonymous type based on an IQueryable from another scope. Or that you could name an anonymous type and cast and IEnumerable to it.

Thank you very muh for your answer.

/Asger





Re: LINQ Project General Linq, Iquerable and anonymous types

WilliamStacey

There is kinda a hacky way to do it. You can return array of anonymous types as an object[]. Then as you enumerate the array, you can "Cast()" the object to a new *compatible anonymous type in local scope.

private void button2_Click(object sender, EventArgs e)

{

object[] oa = GetEmployees();

foreach (object item in oa)

{

var emp = Cast(item, new {FirstName="", LastName=""});

Console.WriteLine(emp.FirstName + " " + emp.LastName);

}

}

private object[] GetEmployees()

{

using (ServerDBDataContext db = new ServerDBDataContext())

{

// Get array of anonymous types.

var q = from emp in db.Employees

select new

{

emp.FirstName,

emp.LastName

};

return q.ToArray();

}

}

public T Cast<T>(object obj, T type)

{

return (T)obj;

}





Re: LINQ Project General Linq, Iquerable and anonymous types

Keith Farmer

The .FirstOrDefault() extension will return the first item (or default(T)) from a sequence

There is also a .Cast() extension already. If you wanted to rig a simple way to specify T at runtime:

Code Block

public static IEnumerable Cast(this IEnumerable seq, T dummy)

{

return seq.Cast();

}

... then call as seq.Cast(someDummyObjectOfTypeT), letting T be inferred. You could create one for IQueryable as well.

Also, if you wanted to use your Cast method:

Code Block

public T Cast<T> (object obj, T type)

{

return (T)obj;

}

public static IEnumerable<T> Cast<T>(this IEnumerable<T> seq, T type)

{

foreach (var item in seq)

{

yield return Cast(item, type);

}

}






Re: LINQ Project General Linq, Iquerable and anonymous types

Wael Farag

Facts are:

  • var is used for anonymous types
  • Anonymous types cannot be used outside the code block, ie cannot be returned nor passed as parameters
  • IQueryable Interface , which is the return for Linq to SQL query can be used as an input collection for further queries. the LINQ to SQL will sum-up all the queryes and generate the final SQL statement at the first itiration of the query
Example 1

//Original Query

var queryA = from c in db.Consultants select c;

//Second query

var queryB = from n in queryA

where n.ConsultantId >= 3

select new

{

n.ConsultantId,

n.Initials

};

//Now the Query actually executes

foreach( p in queryB)

{

........

}

So, for your extensive use of anonymous types, I think you are projecting the same query in different places, i.e.

Selecting part of the Consultants in one place and selecting other parts in other place and so on.

To simplify your work, create a general query in a method the return IQUeryable where T is the large set of Fields and the biggist number of returned rows

Then in every place and before databinding create a query on that variable the customizes your needs.

Example 2

IQueryable<Consultants> GetConsultants()

{

//Create the DB context class

//Original Query

return from c in db.Consultants select c;

}

.... elce place

//Second query

var queryB = from n in GetConsultants()

where n.ConsultantId >= 3

select new

{

n.ConsultantId,

n.Initials

};

//Now the Query actually executes

foreach( p in queryB)

{

........

}

Hope that helps, Best Regards






Re: LINQ Project General Linq, Iquerable and anonymous types

Keith Farmer

Anonymous types are simply one use of var (one where var is required). They can of course be used with non-anonymous types.






Re: LINQ Project General Linq, Iquerable and anonymous types

Wael Farag

Of couarse Keith, Just I Focused on the case where var cannot be used other than local variable

Thanks