Mehfuz's WebLog

Live crazy, think different!

Sponsors

December 2007 - Posts

LinqExtender 1.2 is out now

Since, the first release of LinqExtender, I found quite a bit download and feedback from community around. I did plenty of changes and tried to make it as simple as possible for  creating custom providers  without knowing a bit of reflection and expression parsing of the core framework.

After the release , I was asked by people around that why do we need LINQ when we can do it by method calls. The answer to it is, LINQ  gives another level of abstraction to method call that enables you to set a query domain for developers, by means of strongly type query objects, it's not like exposing the data access layer to the front end developer, but it is like giving them a playground with proper boundary. In other words, front end developers now can query on some specific criteria  that we set by means of query object , still giving them a flexibility of functional programming.

Now on to the release 1.2. it has come with query info retrieval wrapper and some new features ,which could be useful while making custom providers.

I have mentioned in following post, how query data is delegated to Process routine, that will be overridden in the custom provider that developer is working on.

http://weblogs.asp.net/mehfuzh/archive/2007/12/02/linqextender.aspx

Now with new release it looks something like

protected override void Process(LinqExtender.Interface.IModify<T> items, Bucket bucket)

As , you can see that it has Bucket object, which is nothing but a wrapper for holding the query details. Each Bucket has some BucketItem. BucketItem contains info for each property used in the expression  separated by &&.

Typically BucketItem looks like

BucketItem
Name
- Property name, different if the used with OriginalFieldNameAttribute, or less it is same as property name.
Value - value in the query , for which the property is compared. Default value, Null.
Unique - True , if UniqueIdentifierAttribute or its inherited type is used on property.Here, one can Use UniqueIdentifierAttribute directly on property or can use any inherited form like, PrimaryKeyAttribute that inherits the UniqueIdentifierattribute, to reflect value to this property.
RelationType : Enum - Equal , LessThan, LessThatEqual, GreaterThan, GreaterThanEqual. Used to identify which type of logical comparison is used.

Any of the property, which is not used in a query , BucketItem.Value and BucketItem.RelationType will have the default value for it, which is Null and Equal respectively.

Now, Going Back to Bucket it looks like

Bucket
IDictionary<string, BucketItem> Items - List of items for property,  where string is the property name of the query object, BuckItem represents how the Property is treated and used in query.
ItemsToTake - default null , if Take is not specified in query.
ItemsToTake - default 0, if Skip is not specified in query.
UniqueItems - string[], contains the name of property on which UniqueIdentifierAttribute or its derivative is applied.

As, we can see from this release that Linqextender supports most common logical expression rather than just Equal expression.

The new release also supports  "New Type" queries, which i already mentioned in this post

http://weblogs.asp.net/mehfuzh/archive/2007/12/16/anonymous-type-in-linqextender.aspx

Finally, I have added CTE(Common table expression) generation for OpenLinqToSql (Formerly known as TinyLinqToSql) provider.

Now , queries like the following with Take and Skip

SqlQuery<Book> context = new SqlQuery<Book>();
var query = (from q in _queryContext
             orderby q.LastUpdated ascending
             select q).Take(5).Skip(2);
// this is where the query will execute
foreach(var book in query)
{
 // do something useful 
}

Will generate Sql like...

WITH FilteredList(Id,Author,Title,ISBN,LastUpdated, [RowNumber]) AS(
SELECT Id,Author,Title,ISBN,LastUpdated, Row_number()OVER(ORDER BY 
LastUpdated asc) as [RowNumber] FROM Book 
)Select * from FilteredList WHERE [Rownumber] Between (3) and (7)

Here, Take(5), Skip(2), it will take 5 items starting from 3.

For more, I would suggest to have a look at release page of LinqExtender

OpenLinqToSql provider is made to exercise the LinqExtender engine , it is provided with the LinqExtender source and with NUnit test class in LinqExtender project itself. There is another project named Linq.Flickr, where I have originally started working on with Linq provider and then made LinqExtender, this is currently a separate project. This shows another  possible implementation of LinqExtender for service end points.

Happy Holidays!!!

kick it on DotNetKicks.com
Anonymous Type in LinqExtender

It is now possible for LinqExtender implemented providers to have anonymous type in the select query.

For example, consider the following

SqlContext<Book> context = new SqlContext<Book>();

var query = (from q in context
            orderby q.LastUpdated descending
            select new { q.ISBN, q.Title}).Take(1);

var book = query.single();

// do something useful

Console.WriteLine (book.ISBN   + "  " + book.Title);

This sample done using TinyLinqToSql custom provider made on LinqExtender. Here I have some books in database and i want the top 1 , latest book out of it, also I need only two items, ISBN and Title, which I just need to show to in my current scope, without declaring any formal type, in this case the anonymous type can be useful and can be done in the above way.

By the time , I am writing this post , I was having some problem with codeplex , for uploading the latest code of LinqExtender. Hope , it will be done , when you are reading this post.

Also, I have uploaded a new version Linq.Flickr , with latest LinqExtender, so you can have the taste of anonymous type in there as well. Though this is out of scope of the post, but need to say that, now you can get photos with order by Date_Posted/ Date_Taken  asc/dsc respectively. Flickr API also supports, other two properties Relevance and Interestingness, but these two only support sort by ascending , therefore , I omitted this half feature, hope they will come with both way order for these two parameters.

No need to say, you can download Linq.Flickr at www.codeplex.com/linqflickr and LinqExtender and TinyLinqToSql at www.codeplex.com/linqextender

Also, I found this cool post of Scott Gutherie for anonymous type, you might need to look at it as well.

http://weblogs.asp.net/scottgu/archive/2007/05/15/new-orcas-language-feature-anonymous-types.aspx

Finally, an anon but cool guy from community named Reski Mills helped me implement this anon type real fast, thanks man!

Enjoy!!

kick it on DotNetKicks.com

LinqExtender 1.01 released

I have released the new version of LinqExtender,  it now support orderby queries

Like I can easily do

var query = from q in context
            where q.Id == 1
            orderby q.Id descending 
            select q;

Also, I have uploaded a tiny linq to sql project named OpenLinqToSql which is built on LinqExtender and can be downloaded from LinqExtender release page

To start working with OpenLinqToSql, all is needed.

First create a object that represents the entity class.For example , i have created a Book table in database , which looks like

CREATE TABLE [dbo].[Book](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Author] [nvarchar](255) NOT NULL,
    [Title] [nvarchar](255) NOT NULL,
    [ISBN] [nvarchar](50) NOT NULL,
    [LastUpdated] datetime NOT NULL

)

For which the representation of object is

class Book : QueryObjectBase
    {
        [LinqVisible, Identity]
        public int? Id { get; set; }
        [LinqVisible]
        public string Author { get; set; }
        [LinqVisible]
        public string Title { get; set; }
        [LinqVisible]
        public string ISBN { get; set; }
        [LinqVisible]
        public DateTime? LastUpdated {get; set;} 

        public override bool IsNew
        {
            get
            {
                return Id == null;
            }
        }
    }

Here to note that, in order to use a property in query expression, LinqVisibleattribute is used. Also, Non string properties, should be made Nullable.

Finally, I can do the following to get things going

SqlQuery<Book> context = new SqlQuery<Book>();

Write the query.

var query = from q in context
            orderby q.Id descending
            select q;

The OpenLinqToSql can talk with SQLCE databases as well. Also, this is just an tiny project that helps to understand how to make providers using LinqExtender, but for real flavor , use the LinqToSql that comes with .net 3.5

Thanks

kick it on DotNetKicks.com
IOrderedQueryable VS IQueryable

We have seen that , while making general LINQ query provider , we have to implement IQueryable along with IQueryProvider.

But what about the following query.

var query = (from ph in context.Photos
             where ph.User == User && ph.PhotoSize == PhotoSize.Medium
 && ph.SearchText == "pocketpc, windows mobile" && 
ph.SearchMode == SearchMode.TagsOnly orderby PhotoOrder.Date_Posted descending
             select ph ).Take(10).Skip(0);

As, this query has orderby clause, this will require IOrderedQueryable instead of IQueryable, or less it will end up with build error.

Now, digging deeper, what is the methodcall for orderby "item" descending/ascending 

Simple order by , like orderby ph.id / orderby ph.id ascending, the internal method call is OrderBy(ph=>ph.id)

Query

var query = from ph in context.Photos where ph.user = "jcl"
 order by ph.Date_Taken select ph;

but if we use, orderby p.id descending , the internal  method call will be made as  OrderByDescending(ph => ph.id).Therefore, in CreateQuery<T>, we have to check for OrderByDescending and OrderBy method separately to process data accordingly.

Which could be

MethodCallExpression curentMethodcall = _expression as MethodCallExpression;

_asc = curentMethodcall.Method.Name == CallType.ORDERBYDESC ? false : true;

ProcessExpression(curentMethodcall.Arguments[1], _dummyPhotoObject);

And during ProcessExpression , the expression breakdown will be

UnaryExpression

    LamdaExpression

        Memberexpresion ( for p = > p.id) or direct ConstantExpression (for p=> "Dake_take")

Source : LinqExtender 

Hope this is useful

kick it on DotNetKicks.com

Posted: Dec 06 2007, 12:27 AM by mehfuzh | with 1 comment(s) |
Filed under: , , ,
LinqExtender

The greatest capability for LINQ is extensibility, My Linq.Flickr api shows how to create , add and quey photos from flickr , without knowing a bit of complexity that is underlying. But, there can be many other need for custom query providers like, Linq to facebook, Linq to youtube, etc. So, creating all these , could be very easy and fun, if there is a common framework that will sit between core Linq and custom provider and let developers to focus only on the application specific logic, not on the query internals and thus it will help developers to make their own providers up and running, in no time.

This is where, it comes a toolkit called LinqExtender  that will gear you up for creating custom provider, with zero complexity.

To start off with LinqExtender, you can either use the VSI installer or  LinqExtender.dll.zip, both of which are referenced in release page of the project.Also, following lines will show , what is needed to start developing custom providers.

--

Create a query object, on which the query will be made , by inheriting QueryObjectBase and overriding the IsNew property , which is used to track , if the object is newly added to the collection or not and this will be tracked during , add/ update of query obejcts,

For example, for the following code , the IsNew property will have value "true"

MyProvider context = new MyProvider ();

context.Add(MyObject);

context.SubmitChange();

Code sample of CustomQuery object, in this case MyObject

public class MyObject : QueryObjectBase
{
    public override bool IsNew
    {
        get
        {
            //TOOD : Add your own Is New logic.
            return true;
        }
    }

}

Now, Create the custom query provider by inheriting Query<T> and overriding some methods of it. In this case the code sample looks like

public class MyProvider : Query<MyObject>
{
    protected override void AddItem(MyObject item)
    {
        // TOOD : Implenment data access logic, 
        //  Sample
        // IFlickr flickr = new DataAccess();
        // flicrk.Add(item);
    }

    protected override void RemoveItem(MyObject item)
    {
        // TODO : Implement data access logic
        //Sample
        // IFlickr flickr = new DataAccess();
        // flicrk.Delete(item);

    }
    protected override void Process(LinqExtender.Interface.IQuery<MyObject> items, 
    MyObject bucket, int itemsToTake, int itemsToSkip, bool isParamCall)
    {
        // TODO :  populate collection on basis of bucket object.

        // Sample
        // IFlickr flickr = new DataAccess();
        // IList<Photo> list =  flicrk.SearchPhoto(bucket.SearchText, bucket.User, itemsToSkip, ItemsToTake);
        // items.AddRange (list);
    }
}

Here to note that bucket variable in Process method, is filled up the query value that is made by user . In the case of Linq.Flickr , when user does a photo query in the following way

var query = (from ph in context.Photos
             where ph.User =="jcl"&& ph.PhotoSize == PhotoSize.Medium 
             && ph.SearchText == "pocketpc" 
             select ph).Take(10).Skip(0);

Inside Process the bucket will have the following values

bucket.SearchText = "pocketpc"
bucket.PhotoSize = PhotoSize.Medium
bucket.User = jcl

In the query you can also see that for Take and Skip , itemsToTake and ItemsToSkip will be filled up respectively and IsParamCall = true , if the query has no Where cause.At the end of the method items variable, needs to be filled up with the result, in this case, list of photos. Therefore, at the end of Process , items.AddRange or items.Add should be used to reflect the result back to query.

Finally, The AddItem/ RemoveItem method is called , when user adds / removes an item, then make SubmitChanges() call.

--

This is a short introduction to LinqExtender, in coming weeks, I will write more walkthroughs with working sample. For now, to see the real implementation , take a look at Linq.Flickr project.

Enjoy!

Starting with 1.1 version rather working with main object refernce in AddItem , RemoveItem and Process , a new wrapper name Bucket is introduced to deal with query parameters to have a unified and extensible way of dealing with user query details. Please check the codeplex project page for more Info. Also, see the prograssion of posts made with this blog as well.

kick it on DotNetKicks.com
Posted: Dec 02 2007, 10:26 PM by mehfuzh | with 16 comment(s) |
Filed under: , ,
More Posts