Just I am maintaining a project.It has been written in C# 3.0.Some Implementations return collection as IQueryable.
like
List<BookData> data = new List<BookData>();
...
data.Add(new BookData { ID = "P001", BookTitle = "C# in Depth" });
data.Add(new BookData { ID = "P002", BookTitle = "F# in Depth" });
public IQueryable GetBooks()
{
return data.AsQueryable();
}
The code would have return the collection list. What is the special in returning them
as AsQueryable ?
Without using reflection or casting the returned object, the only methods that are available on the returned collection are those defined by the interface. This would be one way of restricting some types of access to the collection -- for instance, IQueryable doesn't have an add method. Unfortunately this isn't safe in the face of a "hostile" user of your code. If you truly need the collection to be inviolable, a better way is to return a read-only copy of the collection rather than the actual collection cast as a different interface.
Note that I'm assuming a List, as in your example, or some other class that actually implements IQueryable natively. In this case the source object is returned. If the underlying object doesn't implement IQueryable then an IQueryable is returned that proxies the calls to the underlying IEnumerable.
AsQueryable doesn't really do anything when invoked on a plain old collection like a List<T>, so the answer probably depends on another part of the codebase. For example, someone might have defined a GetBooks method to take an IQueryable<Book>, with the intent that the GetBooks method would perform any ordering or filtering in the database via a LINQ provider. But the code you're looking at constructs the set of books as a collection (a List<Book>), not a query. In order for the result to be passed the hypothetical GetBooks method, the collection has to be wrapped in an IQueryable<Book>, even though that wrapper is just going to delegate straight back to the LINQ to Objects methods (rather than translating the GetBooks operations to SQL queries).
Or perhaps the class you're looking at implements an interface where the method you're looking at is declared as returning IQueryable<Book> (for similar reasons to above), so your code is having to wrap the List<Book> to remain compatible with the interface signature.
Related
I am going through a tutorial for asp.net and C# and the author used some code that I am trying to understand. I have an idea of what it does, but I just wanted to make sure.
public IQueryable<Category> GetCategories()
{
var db = new WingtipToys.Models.ProductContext();
IQueryable<Category> query = db.Categories;
return query;
}
I am a little confused by
IQueryable<Category>
as well as the line
IQueryable<Category> query = db.Categories;
What I think it does is that it is a method called GetCategories() that only accepts Category objects. The method defines a new instance productcontext, it then runs some type of query and returns it. I could be close or way off. I just want to make sure.
... method called GetCategories() that only accepts Category objects ...
IQueryable<Category> is a type just like intor string so the method accepts nothing, it judt returns categories in a queryable way (IQueryable).
The IQueryable return type is used to indicate you want C# to pass along any filters that you use on the GetCategories() method to be passed directly to the database. Even though the method is setup to pass all categories back, you can limit them at a higher level. This saves you from having to create multiple methods for each filter you can think of that goes back to the database.
Here is link to a StackOverflow Example about the differences between IEnumerable and IQueryable
So I think the part you're having trouble with is the generic return type in the method signature, it can be a strange syntax if you haven't come across it before.
Your method is returning a type of IQueryable<Category>, so you're going to be returning an object that implements the interface IQueryable<T>, specifically one which is implemented to work specifically with Category objects.
If you wanted to create a list of strings, you'd do something like:
MyStrings = new List<string>();
And if you wanted to create a method to return a list of strings:
public List<string> FetchMyStrings(); // List<string> is your return type.
In your case, you're returning a list of Category objects:
public List<Category> FetchMyCategories(); // List<Category> is your return type.
For some excellent explanations of IQueryable<T>, and why you'd be interested in it, I'd recommend the answers here:
What is the difference between IQueryable<T> and IEnumerable<T>?
The rest of the code seems to initialise a new database connection, and returns a queryable object, allowing you to get at the categories for use elsewhere in your code.
Is the purpose of AsQueryable() just so you can pass around an IEnumerable to methods that might expect IQueryable, or is there a useful reason to represent IEnumerable as IQueryable? For example, is it supposed to be for cases like this:
IEnumerable<Order> orders = orderRepo.GetAll();
// I don't want to create another method that works on IEnumerable,
// so I convert it here.
CountOrders(orders.AsQueryable());
public static int CountOrders(IQueryable<Order> ordersQuery)
{
return ordersQuery.Count();
}
Or does it actually make it do something different:
IEnumerable<Order> orders = orderRepo.GetAll();
IQueryable<Order> ordersQuery = orders.AsQueryable();
IEnumerable<Order> filteredOrders = orders.Where(o => o.CustomerId == 3);
IQueryable<Order> filteredOrdersQuery = ordersQuery.Where(o => o.CustomerId == 3);
// Are these executed in a different way?
int result1 = filteredOrders.Count();
int result2 = filteredOrdersQuery.Count();
Do the IQueryable versions of these extension methods just build up an Expression that ends up doing the same thing once its executed? My main question is, whats a real use case for using AsQueryable?
There are a few main uses.
As mentioned in other answers, you can use it to mock a queryable data source using an in-memory data source so that you can more easily test methods that will eventually be used on a non-enumerable based IQueryable.
You can write helper methods for manipulating collections that can apply to either in-memory sequences or external data sources. If you write your help methods to use IQueryable entirely you can just use AsQueryable on all enumerables to use them. This allows you to avoid writing two separate versions of very generalized helper methods.
It allows you to change the compile time type of a queryable to be an IQueryable, rather than some more derived type. In effect; you'd use it on an IQueryable at the same times that you'd use AsEnumerable on an IEnumerable. You might have an object that implements IQueryable but that also has an instance Select method. If that were the case, and you wanted to use the LINQ Select method, you'd need to change the compile time type of the object to IQueryable. You could just cast it, but by having an AsQueryable method you can take advantage of type inference. This is simply more convenient if the generic argument list is complex, and it is actually necessary if any of the generic arguments are anonymous types.
The most valid case I have for AsQueryable is unit testing. Say I have the following somewhat contrived example
public interface IWidgetRepository
{
IQueryable<Widget> Retrieve();
}
public class WidgetController
{
public IWidgetRepository WidgetRepository {get; set;}
public IQueryable<Widget> Get()
{
return WidgetRepository.Retrieve();
}
}
and I want to write a unit test to make sure the controller passes back the results returned from the repository. It'd look something like this:
[TestMethod]
public void VerifyRepositoryOutputIsReturned()
{
var widget1 = new Widget();
var widget2 = new Widget();
var listOfWidgets = new List<Widget>() {widget1, widget2};
var widgetRepository = new Mock<IWidgetRepository>();
widgetRepository.Setup(r => r.Retrieve())
.Returns(listOfWidgets.AsQueryable());
var controller = new WidgetController();
controller.WidgetRepository = widgetRepository.Object;
var results = controller.Get();
Assert.AreEqual(2, results.Count());
Assert.IsTrue(results.Contains(widget1));
Assert.IsTrue(results.Contains(widget2));
}
where really, all the AsQueryable() method allows me to do is satisfy the compiler when setting up a mock.
I'd be interested where this is used in application code though.
As sanjuro noted, the purpose of AsQueryable() is explained in Using AsQueryable With Linq To Objects And Linq To SQL. In particular, the article states,
This offers an excellent benefits in real word scenarios where you have certain methods on an entity that return an IQueryable of T and some methods return List. But then you have business rule filter that needs to be applied on all the collection regardless if the collection is returned as IQueryable of T or IEnumerable of T. From a performance stand point, you really want to leverage executing the business filter on the database if the collection implements IQueryable otherwise fall back to apply the business filter in memory using Linq to object implementation of delegates.
The purpose of AsQueryable() is greatly explained in this article Using AsQueryable With Linq To Objects And Linq To SQL
From Remarks section of MSDN Queryable.AsQueryable Method:
If the type of source implements IQueryable, AsQueryable(IEnumerable) returns it directly. Otherwise, it returns an IQueryable that executes queries by calling the equivalent query operator methods in Enumerable instead of those in Queryable.
Thats is exactly what is mentioned and used in above article.
In your example, it depends on what is orderRepo.GetAll returning, IEnumerable or IQueryable(Linq to Sql). If it returns IQueryable, the Count() method will be executed on database otherwise it will be executed in memory. Look carefully at example in referenced article.
Interface IQueryable quoting documentation:
The IQueryable interface is intended for implementation by query
providers.
So for someone that intends to make its datastracture queryable in .NET, that datastructure that not necessary can be enumerated or have valid enumerator.
IEnumerator is an interface for iterating and processing stream of data instead.
I have a Class / API that uses an IQueryable<FirstClass> data source however I wish to expose an IQueryable<SecondClass>, where SecondClass is a wrapper class for FirstClass that exposes nearly identical properties, however for various reasons needs to inherit from an unrelated base class. For example:
// My API
void IQueryable<SecondClass> GetCurrentRecords()
{
return from row in dataSource
/* Linq query */
select new SecondClass(row);
}
// User of my API
var results = GetCurrentRecords().Where(row => row.Owner = "Mike");
Now I can make the above compile simply by using AsQueryable however I want to expose a "true" IQueryable that efficiently queries the database based on the API users query.
I know that this isn't trivial (my wrapper IQueryable implementation needs to understand the relationship between the properties of SecondClass and FirstClass), and that it has nothing to do with the Select function, but it seems like it should be possible.
How do I do this?
Note: I know that instead my API could just expose FirstClass along with a helper method to convert FirstClass to SecondClass for when the API user is "done" creating their query, but it feels messy and I don't like the idea of exposing my generated classes in this way. Also I'd like to know how to do the above anyway just from a purely academic standpoint.
Probably, you should return not an IQueriable, but Expression. Then you will be able to modify expression and let LINQ generate a query from a final Expression object. Example is here: http://msdn.microsoft.com/en-us/library/bb882637.aspx
I have an interface called ICatalog as shown below where each ICatalog has a name and a method that will return items based on a Predicate<Item> function.
public interface ICatalog
{
string Name { get; }
IEnumerable<Item> GetItems(Predicate<Item> predicate);
}
A specific implementation of a catalog may be linked to catalogs in various format such as XML, or a SQL database.
With an XML catalog I end up deserializing the entire XML file into memory, so testing each item with the predicate function does does not add a whole lot more overhead as it's already in memory.
Yet with the SQL implementation I'd rather not retrieve the entire contents of the database into memory, and then filter the items with the predicate function. Instead I'd want to find a way to somehow pass the predicate to the SQL server, or somehow convert it to a SQL query.
This seems like a problem that can be solved with Linq, but I'm pretty new to it. Should my interface return IQueryable instead? I'm not concerned right now with how to actually implement a SQL version of my ICatalog. I just want to make sure my interface will allow for it in the future.
Rob has indicated how you might do this (although a more classic LINQ approach might take Expression<Func<Item,bool>>, and possbily return IQueryable<IFamily>).
The good news is that if you want to use the predicate with LINQ-to-Objects (for your xml scenario) you can then just use:
Predicate<Item> func = predicate.Compile();
or (for the other signature):
Func<Item,bool> func = predicate.Compile();
and you have a delegate (func) to test your objects with.
The problem though, is that this is a nightmare to unit test - you can only really integration test it.
The problem is that you can't reliably mock (with LINQ-to-Objects) anything involving complex data-stores; for example, the following will work fine in your unit tests but won't work "for real" against a database:
var foo = GetItems(x => SomeMagicFunction(x.Name));
static bool SomeMagicFunction(string name) { return name.Length > 3; } // why not
The problem is that only some operations can be translated to TSQL. You get the same problem with IQueryable<T> - for example, EF and LINQ-to-SQL support different operations on a query; even just First() behaves differently (EF demands you explicitly order it first, LINQ-to-SQL doesn't).
So in summary:
it can work
but think carefully whether you want to do this; a more classic black box repository / service interface may be more testable
You don't need to go all the way and create an IQueryable implementation
If you declare your GetItems method as:
IEnumerable<IFamily> GetItems(Expression<Predicate<Item>> predicate);
Then your implementing class can inspect the Expression to determine what is being asked.
Have a read of the IQueryable article though, because it explains how to build a expression tree visitor, which you'll need to build a simple version of.
I've been using LINQ extensively in my recent projects, however, I have not been able to find a way of dealing with objects that doesn't either seem sloppy or impractical.
I'll also note that I primarily work with ASP.net.
I hate the idea of exposing the my data context or LINQ returned types to my UI code. I prefer finer grained control over my business objects, and it also seems too tightly coupled to the db to be good practice.
Here are the approaches I've tried ..
Project items into a custom class
dc.TableName.Select(λ => new MyCustomClass(λ.ID, λ.Name, λ.Monkey)).ToList();
This obviously tends to result in a lot of wireup code for creating, updating etc...
Creating a wrapper around returned object
public class MyCustomClass
{
LinqClassName _core;
Internal MyCustomClass(LINQClassName blah)
{
_core = blah;
}
int ID {get { return _core.ID;}}
string Name { get {return _core.Name;} set {_core.Name = value;} }
}
...
dc.TableName.Select(λ => new MyCustomClass(λ)).ToList();
Seems to work pretty well but reattaching for updates seems to be nigh impossible somewhat defeating the purpose.
I also tend to like using LINQ Queries for transformations and such through my code and I'm worried about a speed hit with this method, although I haven't tried it with large enough sets to confirm yet.
Creating a wrapper around returned object while persisting data context
public class MyCustomClass
{
LinqClassName _core;
MyDataContext _dc;
...
}
Persisting the data context within my object greatly simplifies updates but seems like a lot of overhead especially when utilizing session state.
A quick Note: I know the usage of λ is not mathematically correct here - I tend to use it for my bound variable because it stands out visually, and in most lambda statements it is the transformation that is important not the variable - not sure if that makes any sense but blah
Sorry for the extremely long question.
Thanks in advance for your input and Happy New Years!
I create "Map" extension functions on the tables returning from the LINQ queries. The Map function returns a plain old CLR object. For example:
public static MyClrObject Map(this MyLinqObject o)
{
MyClrObject myObject = new MyClrObject()
{
stringValue = o.String,
secondValue = o.Second
};
return myObject;
}
You can then add the Map function to the select list in the LINQ query and have LINQ return the CLR Object like:
return (from t in dc.MyLinqObject
select t.Map()).FirstOrDefault();
If you are returning a list, you can use the ToList to get a List<> back. If you prefer to create your own list types, you need to do two things. First, create a constructor that takes an IEnumerable<> of the underlying type as it's one argument. That constructor should copy the items from the IEnumerable<> collection. Second, create a static extension method to call that constructor from the LINQ query:
public static MyObjectList ToMyObjectList(this IEnumerable<MyObjectList> collection)
{
return new MyObjectList (collection);
}
Once these methods are created, they kind of hide in the background. They don't clutter up the LINQ queries and they don't limit what operations you can perform in teh query.
This blog entry has a more thorough explanation.