October 2007 - Posts
LINQ provider for Flickr gives an easy way to query , add and delete Flickr photos. Here, I will give some sneak preview about how to use the provider to do different operations on Flickr, as if doing queries with SQL objects.
Now, waiting no more, lets see, what can we do with it.
Now, Let's say, i want to get a particular user's ("chschulz") photos with "New york" as search key and I also want only the first page, where each page should have 5 items.
The code snippet for that will be :
// create the context
FlickrContext context = new FlickrContext();
// set the user.
string user = "chschulz";
// do query.
var query = (from ph in context.Photos
where ph.User == user && ph.SearchText == "New York" && ph.PhotoSize == PhotoSize.Thumbnail
select ph).Take(5).Skip(0);
try
{
foreach (Photo p in query)
{
Console.WriteLine(p.Title + "\r\n" + p.Url);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Output
50th Steuben Parade
http://farm2.static.flickr.com/1067/1409243458_776fdd4f53_t.jpg?v=0
50th Steuben Parade
http://farm2.static.flickr.com/1234/1408366057_96c9498f6b_t.jpg?v=0
50th Steuben Parade
http://farm2.static.flickr.com/1236/1408380481_9df2e62351_t.jpg?v=0
50th Steuben Parade
http://farm2.static.flickr.com/1335/1408370401_f4315f2e00_t.jpg?v=0
50th Steuben Parade
http://farm2.static.flickr.com/1383/1408375435_861124b5aa_t.jpg?v=0
One thing to add, by default when we will query without any private/semi-private view mode, result will contain only public photos.
To have Semi-private /private photos, We can set option by ViewMode enum
public enum ViewMode
{
Owner,
Public = 1,
Friends,
Family,
FriendsFamily,
Private
}
Note, There is a value called ViewMode.Owner, when specified , it means "get all my photos". This will get all private/semi-private photos of an authenticated account.Also, ViewMode.Private and ViewMode.Owner, will get the private photos only and all photos of a specified user respectively.
When we will try to view or modify private/semi-private photos, The authentication process will done by API on behalf. The API will automatically , open a new browser(for windows app) / take to the URL, where the user will be prompted for valid credentials and access permission for the app, for which the photos to be viewed/deleted/added. Finally, the user will be taken back to the app, after user closes browser (windows app) / automatically (web app, we have to specify the URL of our app, in the return URL of API configuration page of Flickr).
There is also an enum for specifying Photosize
public enum PhotoSize
{
Square,
Thumbnail,
Small,
Medium,
Original,
Default = Medium (this is set by default)
}
In addition, the most important options for searching are:
- Photo.SearchText : Used for specifying keyword for which Title, Description or tags will be search on.
- Photo.User : The name of the user , of whom the photos will be queried on.
Moving forward, LINQ query for viewing single phtoto for an ID.
FlickrContext context = new FlickrContext();
var query = from ph in context.Photos
where ph.Id == PhotoId && ph.PhotoSize == PhotoSize.Medium
select ph;
Photo photo = query.Single<Photo>();
Next , query syntax for deleting a photo.
FlickrContext context = new FlickrContext();
var query = from ph in context.Photos
where ph.Id == PhotoId
select ph;
Photo photo = query.Single<Photo>();
context.Photos.Remove(photo);
context.SubmitChanges();
Any remove or add operation must follow a FlickrContext.SubmitChanges(). This is where, the action will be posted to Flickr.
Finally, API is never done without a photo add operation. Snippet for that :-
FlickrContext context = new FlickrContext();
context.Photos.Add(
new Photo{ FileName = Path.GetFileName(uploader.Value),
File = uploader.PostedFile.InputStream, ViewMode = ViewMode.Private});
context.SubmitChanges();
Here, we have to either set the Photo.File(Stream) for uploaded file (in web app), or we can only specify Phtoto.FilePath (windows app).
*The above , three examples are taken from Flickr.Web (test) app , which is provided with the LINQ.Flickr API at codeplex.
This is the short briefing of LINQ To Flickr API , which I have recently uploaded in codeplex, please give a look at it and let me know , how can I improve it more.
The API can be downloaded at : LINQ to Flickr API
In my last post , I showed the basics of creating a custom LINQ provider, now moving forward , we just wont query against Name property only, we also may need to query against ID or Age of the Person object.
Therefore, we must fuse a method that will enable to use the query against any property. In simple, we can create a common BinaryExpression processor, that will build up the query object using reflection, which will be used to fetch similar item from the repository. This is, though a fictions Person class and nothing to do with Provider basics, the change is useful for creating any real life project.I sightly modified the PersonContext class from previous post to support query against all properties.
Now, ProcessExpression method will call only ProcessBinaryResult, for any type of Binary expression processing.
ProcessBinaryResult in turn will call ProcessItem, which will take the query (Person) object and will match against its list.For ex, for Equal expression, ProcessItem will have the following code.
PersonContext class with recent changes can be downloaded here. After updating the project(which is attached previously) with the new class, it is possible to use queries like p.Age == 40 , or p.ID = 1, or query against any new properties that has been added to Person class.
In Short, the power of LINQ query is to query against any object , it could be SQL, XML, or custom, and being able to query any property, does make a provider more useful.
Let me know , if it is useful.
In this post, I will show how to create a sample LINQ provider.Creating LINQ provider can be far more complex, but here I will demonstrate the very basic one to start.
This sample is done by using VS2008 Beta 2. I finished of this is post by creating a fictious Person query provider that in turn the gives a glimpse of creating custom LINQ provider for pulling data from source, in a more descriptive and convenient way, rather calling out boring GetBy methods.
So,my fist task , is to declare an entity class.
For simplicity, It contains only three properties ID, Name and Age. The properties are created using Automatic property feature of .net 3.0, That means , i don't need to declare anymore private variable and put them under get / set block. It's now more like declaring property in an interface, the only different is that framework does the rest of the work for me.
Now, To make , custom LINQ provider , a class must implement two interface. IQueryable and IQueryProvider.
IQueryable is the interface that make objects queryable in a LINQ expression. Without it , it is not possible to use objects in queries like this
IQueryProvider is the interface that is pointed to by IQueryable , which is also responsible for creating and executing expressions. IQueryable is also a member of IEnumerable, which enables the query result to be used inside a loop.
Now, in the sample Provider, i have created a PersonConext class that implements the IQueryable <T> (in this case IQueryable <Person>) and IQueryProvider . IQueryable has some IEnumarable implements but the most important implementation is the providver creation and type initialization.
As, i have implemented the provider in the same class that implements IQueryable interface, therefore , PersonContext's provider points to itself(this). But we can move the provider to a different class, in that case the framework need to keep instances of two class, one for IQueryable class and another for IQueryProvider class.So, i guess the solution, is to have them in same class.Next, ElmentType is the item , we are dealing with (in this case Person) and Expression.Constant(this), tells the framework that the expression which is used are with constant values.
IQueryProvider, only have two sets of method , Create<S> that returns IQueryable pointer (this is the entry point for expression intialization) and Execute<TResult> that basically uses the Expression instance to query and extract result out of LINQ query.
IQueryProvider.Execute method is called during the iteration of IEnumerables (query), therefore, provider calls an external source or db to get its result during iterateration process only.
Basically, when we do a LINQ query , internally it does methods calls, so inside Execute method, the expression type will be of MethodCallExpression. and for each arguments of MethodcallExpression(which is also a type of Expression), it needs to be evaluated , untill the leaf is reached.
Now, Each MethodCallExpression, generally starts with an UnaryExpression and ends with an BinaryExpression (If the query has a where clause ) or ParameterExpression (If the query is simple select <something>). In between, there is LamdaExpression ( ex . { p = > p.age > 20 } ), to get the next expression we need to call LamdaExpression.Body in this case, where LamdaExpression.Body in most of the case is BinaryExpression.
BinaryExpression can be of various type ,like, ExpressionType.LessThan , ExpressionType.Equal, etc.
Inside ProcessExpression of the sample provider.This shows an idea about how to parse expressions at different states.

Finally, the right part of the BinaryExpression is of ConstantExpression Type (in this case), but it can be of Unary or Parameter Expression, in more complex situations. In this case, we just need to extract the constant value (age/name/id) to filter Person.
Though, in the end the query graph could much more complex , which is beyond the scope of this post, still the basic structure remains the same. Finally, I have added the sample provider code to download. Feel free to download, hope this will give some pointers to custom providers.
To build custom providers with pleasure use LinqExetender (www.codeplex.com/linqextender). The only toolkit that enables you to do it in style.

More Posts