views:

487

answers:

4

I'd like to implement MVC while using LINQ (specifically, LINQ-to-entities). The way I would do this is have the Controller generate (or call something which generates) the result-set using LINQ, then return that to the View to display the data. The problem is, if I do:

return (from o in myTable select o);

All the columns are read from the database, even the ones (potentially dozens) I don't want. And - more importantly - I can't do something like this:

return (from o in myTable select new { o.column });

because there is no way to make anonymous types type-safe! I know for sure there is no nice, clean way of doing this in 3.5 (this is not clean...), but what about 4.0? Is there anything planned, or even proposed? Without something like duck-typing-for-LINQ, or type-safe anonymous return values (it seems to me the compiler should certainly be capable of that), it appears to be nearly impossible to cleanly separate the Controller from the View.

+2  A: 

Anonymous types are primarily designed to be used within a method. They are not suitable for communication between methods.

If you need to pass a set of data between two functions the best way is to create a new type wrapping the data or use a loser grouping like Tuple<T1,T2> or KeyValuePair<TKey,TValue>

JaredPar
with the exception of a reflection based scenario, in which case there are a couple of good uses for them (in the MVC framework html helpers for example)
NickLarsen
@Jared: Except that with LINQ, that's not true at all - LINQ-objects are certainly meant to be passed around, but you just can't do it in C# due to language limitations. It *can* be done in VB.net, however.
BlueRaja - Danny Pflughoeft
@BlueRaja, sorry that's incorrect. They **can** be passed around in either language as `System.Object`. They cannot be strongly passed around in either language as anonymous types are well anonymous. They can't be defined directly in any place that would show up in metadata. In VB.net (and C# 4.0) you can work around this by accessing them in a weakly typed fashion but that is not what the OP is asking for.
JaredPar
+4  A: 

Use a view model layer. Your view has to know what it is going to display. I guess its possible to create a view that just formats a multi-dimensional array of data, but that isn't exactly the best reason to go with an MVC solution. You can however populate a view model with an anonymous object for consumption in your view.

NickLarsen
A: 

Since no one even attempted to answer my question, I will answer it myself..

It turns out, C# 4.0 supports duck-typing - they call it dynamic typing. However, in using dynamic types to return anonymous types, we lose the benefits of strong types:

  • Compile-time type-checking
  • Performance
  • Intellisense

I've opened a feature request to have strongly-typed anonymous return types here - if you think this would be a useful addition to C# 5, follow the link and let the .Net team know!

BlueRaja - Danny Pflughoeft
+1  A: 

How about this?

I assume that you have an entity class for your table 'myTable' (let's call it 'MyTableEntity'), so why don't you instantiate a new MyTableEntity object and use object initializer to fill only those columns you want?

return (from o in myTable select new MyTableEntity { AColumn = o.column });

This will not translate to a SELECT * as you asked, but you'll still have a way to pass a strongly-typed object to a view.

You have to be careful to just make use of the initialized properties inside the view and that's it.

Does this makes sense for you?

emzero
That's a good idea - I'll try it out at work when I get a chance (not for a few days at least)
BlueRaja - Danny Pflughoeft