October 29, 2012 Haskell, Languages 3 comments
October 29, 2012 Haskell, Languages 3 comments
“Haskell is an advanced purely-functional programming language. An open-source product of more than twenty years of cutting-edge research, it allows rapid development of robust, concise, correct software.” This official definition is only missing one point: Haskell is mind-blowing programming language.
First of all, let’s start with realizing that Haskell is all about purity as opposite to many other functional languages, which do a lot of compromises, like Scala. It could be due to the fact that this language was created by a group of highly educated people, or better to say researches. I think their intent was exactly to create language which would be some kind of definition of a pure functional language.
As per Joel Spolsky, when answering similar question on SO:
“In a pure functional language, you can’t do anything that has a side effect.
A side effect would mean that evaluating an expression changes some internal state that would later cause evaluating the same expression to have a different result. In a pure functional language you can evaluate the same expression as often as you want with the same arguments, and it would always return the same value, because there is no state to change.
For example, a pure functional language cannot have an assignment operator or do input/output, although for practical purposes, even pure functional languages often call impure libraries to do I/O.”
Personally I found Haskell to be the most exciting programming language among all I’ve ever touched. It has many interesting paradigms and features. Most of them are present in other languages, some are not. I would like to briefly go through some of them.
In Haskell there is no function that can accept more than one parameter. What?
Well, of course you can write function
add a b = a + b
But, under the hood it is always translated into 2 functions. One of them is responsible for taking parameter a and applying (+) to result of second function. Second function is there to take first function and apply it on b.
This allows for partially applied functions, which is completely cool stuff.
map ( * 2) [1,2,3]
In above code ( * 2) is actually partially applied function. We are only supplying one parameter instead of two, expected by the * function. So the result of what we get is a function like (x * 2), accepting parameter x.
This function is then applied to the list [1,2,3] one by one, thus we get: [2,4,6].
As another example, we can extract partially applied function from our add to create function, which always adds 1.
addOne x = add 1
So it can be used like addOne 5 to produce 6.
Lazy evaluation isn’t anything new for C# developer. You can think about it as about differed execution in LINQ. Zipping is not something cool, but rather one of the common features of functional languages, but I just wanted to include it here. Below is function every8, which demonstrates mentioned things as well as ranges and recursion.
module Every8thStartingWithSumOfXandY where
everyThird x = x:everyThird(x+3)
everyFifth y = [y,(y+5) ..]
every8 x y = zipWith (+) (everyThird (x)) (everyFifth (y))
You can later use this code to get [4,12,20,28], like below:
take 4 (every8 1 3)
This code below allows you two have a list, which consists with items which are less than 3:
[x | x <- [1,2,3,4,5,6], x < 3]
For example we can match on head and tail of list to perform reverse of list:
rev (h:t) = rev t ++ [h]
Combining pattern matching and list comprehensions we can effectively write quick sort in one line:
qSort (m:r) = qSort [x | x <- r, x < m] ++ [m] ++ qSort [x | x <- r, x >= m]
When I wrote this, I was so much amazed if not shocked about how much Haskell is concise and powerful in expressing complex things. I used to write quick sort many times in C++ back in my university days during programming competitions and even it was easy it never took me one minute or one line to write. (Of course, there are performance considerations regarding two implementations, but we are not talking about them now.)
Don’t be mislead. A lot of other trivial things in Haskell are painful and difficult to implement. To somehow overcome such complexities concept of monads was introduced in functional languages. With them chain of operations can be executed allowing to bypass some data (or state if you will). “Haskell is overly abstract and seems to complicate the simplest tasks, but once you see how monads unify some of the most difficult concepts in programming: backtracking, continuations, error propagation, state management, and parsing, among many others, you can begin to appreciate how elegant monads really are. But to people not familiar with those topics and their difficulty and who have never seen monadic code, monads are just weird math crap.” said Tac-TIcs. Well, for me they are still very difficult even I can read and understand code with their usage. I’ve prepared some other piece of code, which will probably not bring much light on monads, but it shows usage of build-in Nothing and Just. Defining own monads is hard, and worth separate blog post.
module Main where
look key [] = Nothing
look key ((k, val):rest)
| key == k = Just val
| otherwise = look key rest
al = [(1, []), (2, [(22, "something deep inside")]), (3, [(33, "else")])]
Which can be used like this:
look 2 al >>= look 22
So you can basically work around Haskell’s restrictions and call methods one by one, using this smarty-looking operator “>>=”. Haskell made easy things hard and then introduced Monads to make those hard things easy again. Now you can write code with sugar do-syntaxes.
I’m too new to Haskell to talk about some advanced features and to write programs which are over 10 lines of code. But from what I’ve tried I definitely like the language. This is language for your weekend’s fun. Play with it!
I hope you liked this short Haskell journey.
October 22, 2012 Book Reviews 3 comments
It took me less than one week to reread “The Pragmatic Programmer”.
I like beginning of the book the most, because it introduces pragmatic programmer and I like to think about myself as about such type of programmer.
So who are pragmatic programmers?
Pragmatic programmers are guys with willing to outperform, to stand out of the crowd, always trying to see bigger picture in order to produce higher quality code and to bring more value to customers. They learn a lot, they read technical blogs. You are also pragmatic, as very likely you share similar opinions about doing our job.
We don’t stop on achieved, we continue improving. We don’t just do our tasks, we make sure we do the right thing. We have a vision on our career and on what we want from our professional lives. We don’t complain, we solve problems. Cats don’t eat our source code, and we don’t live with broken window. We keep an eye on what is happening so no one can silently boil us as stupid frogs.
As per book pragmatic programmer is early adopter, inquisitive, critical thinker, realistic and jack of all trades.
This book is critically outdated when it comes to technologies or tools, because it was written IT centuries ago, in 1999. But it is astonishing how up to date it is about all other things.
I strongly recommend reading this book.
I find ideas expressed in book close to my understanding of software craftsmanship and I have my things to remember to become successful developer. In book you will find 70 tips, not just 8 as I have in my post!
I think this book is great because it inspires, and thus I would like to read it once again.
October 17, 2012 CodeAndBeer, DevMeeting No comments
Last week I’ve failed in organizing internal “Code & Beer” event.
So what I did was just short invite stating that I will be there after working day and whoever wants can come and join. I bought some beer and snacks and mentioned about this as well. At least it should have been a good reason for some to join.
Idea behind this was to learn some new concepts from functional programming, which day-to-day language doesn’t support or encourage explicitly.
As I try to introduce myself to some of the programming languages (including functional), I thought it would be wonderful idea to do this in circle of people who share same attitude to programming.
I didn’t have high expectation to number of attendees. I thought that maybe 5 will join, but even less came. A good dozen of people who promised that they will attend had good excuses. 2 people is not enough for effective code & beer session. Not enough laugh and not enough diversity. But no one of us wasted our time, not sure about those who didn’t join though.
I tried small and it went even smaller, maybe if I try bigger it will be at least small? Who knows. But I’m afraid that there is not enough interested developers in my company so it should be something behind company’s walls.
September 24, 2012 Conferences No comments
On September 14, 2012 I attended conference for .NET developers here in Vienna, called Professional .NET 2012.
I’m very glad that company has sent me to this conference. Well, it was not any kind of exclusive and expensive conference somewhere abroad, but rather excellent money for value event for employees, who like to improve their professional skills. When I just started I asked about going to Oslo for NDC, which is awesome conference. For new developer it was bit too over budget and I understand it – who knows, maybe in reality I’m crap-code writer, which shall be fired the next morning.
Conference took place in some hotel, and from what I understood, not cheap one. So accordingly it resulted in great tasty lunch. This is always a big plus for any conference. Despite it was called “Professional .NET” I have seen a lot of young people which didn’t seem to have years of experience at all. If I were student I wouldn’t take much out of that day.
Intro and 2 side talks were in German, so I cannot say anything about those, for me it was boring. All other sessions were in English.
Two special presenters were invited and they were core for the conference.
Ayende Rahien just turned all things upside-down. Whatever you learnt from any smart patterns books older than few years is just not acceptable. Everything could be written in very simple manner with depth averaging 4. True or false?
Personally I liked very much the way Ayende presented stuff and how he talked about things and also that he made people think. Even flow of his speech was like some continuing brainstorm. What I didn’t like completely is that he is very concentrated only on one side of the problem, talking like all software is just about reading data from database. Yes, I say something against known Ayende, because I’m sure he shows only one side of the coin. Besides, he likes to blame other people, so why not other people blame him a bit.
If you don’t know Ayende, for sure you have heard about his projects. Oren (his real name) has written Rhino Mocks, RavenDB, NhibernateProfier and contributed to tons of open source projects.
Sebastien Lambla was another special guest. To be honest, I’ve never heard about him before (but I realize now that I read his posts time-to-time). Apparently he has contributed a lot to open source and community, as people, who attended with me knew about him. You maybe heard about OpenWrap or OpenRasta. I just went though this interview with him, to understand more about what he does. Steve Ballmer, you should finally respond him with Microsoft’s vision on open-source!
It was interesting conference, but not a revolution.
September 3, 2012 Languages, Scala 3 comments
Back in university I had few classes dedicated to Scala programming language. Sometimes suddenly things come back to us.
If you never heard about Scala, here is my very short introduction.
Scala was created as bridge between object oriented and functional languages so that it can run on Java Virtual Machine (JVM) and be fully interoperable with Java classes. As Martin Odersky, creator of language, said “I wanted to show that the two paradigms can be unified and that something new and powerful could result from that combination.”
Scala doesn’t force to write in functional style, however it does have all standard features one would expect from functional programming language. The more you prefer OOP, the more likely that your Scala code will look like Java code. If someone starts with functional languages he or she might get impression that Scala isn’t functional language at all. Personally, if I wanted to learn functional programming I would rather go for Haskell which will “force you to eat the whole functional programming burrito”, as Bruce A. Tate, author of “7 languages in 7 weeks” says.
Scala allows for very laconic syntaxes. Sometimes it is way to much of different syntaxes, sometimes syntax is quaint, for example operator “::=” for adding elements to the list, but once you played enough with language you will be able to write shorter pieces of code than what it would take in most conventional languages.
Here is how you could calculate total sum of string lengths in a list:
val listOfStrings = List("a", "ab", "abc", "abcd") val totLength = (0 /: listOfStrings) { (length, item) => length + item.length() } println(totLength)
I also wrote generation of permutations in in lexicographic order:
object PermutationGenerator extends App { var perm = Array[Char]('a', 'b', 'c', 'd') printPerm(1, perm) for (i <- 2 to factorial(perm.length)) { perm = nextPermutation(perm) printPerm(i, perm) } def factorial(n: Int): Int = n match { case 0 => 1 case x if x > 0 => n * factorial(n - 1) } def printPerm(i: Int, a: Array[Char]) { print(i + ": ") a.foreach(c => print(c)) println() } def swap(a: Array[Char], i: Int, j: Int) { val tmp = a(i) a(i) = a(j) a(j) = tmp } def nextPermutation(a: Array[Char]): Array[Char] = { val k = (a zip a.tail) lastIndexWhere { case (x, y) => x < y } val l = a lastIndexWhere { c => a(k) < c } swap(a, l, k) return a.take(k + 1) ++ a.takeRight(a.length - k - 1).reverse } }
Code above isn’t functional or imperative completely but rather some combination. Scala is different from other languages, because it allows for such flexibility. There are languages which make easy things hard and hard thing easy. In Scala it is up to you. For example, to avoid swap method (mutable operations) I could have wrote this “obvious” statement:
return (a.take(k) :+ a(l)) ++ ((a.takeRight(a.length - k - 1).take(l - k - 1) :+ a(k)) ++ a.takeRight(a.length - l - 1)).reverse
Few days ago I also wrote one application to continuously traverse web site and find there some specific links and then send e-mail with complete list of them. But to be honest I gave up debugging it and finding problems, even Scala has more or less accepted integration in eclipse IDE. App was rewritten in C#. My cheating was supposed to win T-shirt to my wife. Surprisingly the site went down next day. My guess is I was not the only one smart-ass to do traversing of the site.
I only took few baby steps, but from what I know now I feel deep sympathy to this language.
Links:
Have you every programmed in Scala? How was it?
I imagine that it was fun, but would like to hear from you.
August 5, 2012 DevMeeting, Presentation, Success 2 comments
A long time passed since I’ve delivered a technical presentation. Mainly because I now live in another country and establishing myself in a new company.
Well “establishing” is loudly said. I’m just software developer. Probably it worth to write separate post on my experiences in this company, since it is very much different from one I worked in Ukraine and I’m sure from most other companies there. I think I had much better perspectives as speaker before I moved (at least those short-term perspectives).
I talked about OData protocol, starting with introduction (read blog posts OData and OData service with WCF and data in memory) and finishing with its applicability to a project we do. Thanks to this presentation I crossed some imaginary mental barrier to more frequent presentations and sharing knowledge, something that I like, and something that I started to take solid steps back in Ukraine.
Now I’m starting it from the beginning.
Presentation I delivered was rather not official and only team wide. It was first I ever delivered in English, so I was limited in number of language tricks which I can use, and probably it impacted quality. Also I didn’t want to make it look like I’m smart-ass, thus I used pace and tone of a normal working meeting. Well, to be honest, I even didn’t know how to behave in this new environment. But from what I see guys liked my presentation, so this gives me a bright spark of enthusiasm to continue sharing interesting stuff.
There are few pitfalls with continuing, some of them pleasing. For example, developers here on average are more experienced and it would be more difficult to surprise them with something. It means that I would need to prepare more in depth topics, which of course requires more time to prepare. But, in the end, it is great that I work with more experienced programmers than me. On the other hand, I’m afraid that most of guys I know here are not willing to spend their spare time to form or join some community of software developers, and I can understand them.
Since I already mentioned about community, I have some ideas about organizing something cool here in Vienna/Austria, for foreigner developers, like me. Will blog about it soon.
July 22, 2012 Book Reviews, WCF 2 comments
To be honest, for me this was the most exhausted reading since years. I started reading this book probably year or even more ago. Always coming back to it in hope that at some point of time it will grasp me into normal pace of reading, so I will be able to finish it. But it was not the case.
Though I finished the “Programming WCF Services”, I’m bit disappointed. I thought that the book will serve me with deep insight into advanced topics in easy to consume manner. Instead it jumped from extreme basics to intermediate and to advanced, but always with chunks of code, which were either boring or repeating or difficult to understand by simple reading. When I was about to try something out articles from internet were more helpful for me then code from book.
The book is good in what it does, but now I think about it more like about cookbook and not like about book you read from beginning to the end. It was my mistake to read it like that.
I feel myself comfortable with WCF. Reading this book was to strengthen my knowledge in WCF and to open tough things I didn’t know. I’m afraid that I did not met what I expected. Of course no one can remember all innumerous extension points or tricky security configuration or other wide range of stuff possible with WCF. Probably author of the book knows everything he wrote by heart. I wish I have super memory, but I often forget a lot of things I read about. Pity! If you know basics and understand core principles it should not be a problem to figure out what you need with couple of MSDN pages and some googling. I hope I will manage my further assignments even without knowing all possible combinations of configurations of WCF, even I look stupid not being able to shot people with immediate WCF solutions/answers/ideas.
One more lesson learned: It is better to play more with things you what to learn about than to obdurately read comprehensive book about those things.
July 8, 2012 IoLanguage, Languages 6 comments
I would expect that most of you never heard about such programming language as Io. Very likely programmers would associate Io with “input-output”, but Io language has nothing special to do with it and has no cool in-out features.
Io is extremely tiny language which runs on supermall virtual machine, even your micro-oven can handle. Having that said I don’t mean that Io is not powerful.
Io is prototypical object-oriented language with dynamic typing. For me, as C# guy, it was not easy to “feel” the language. I could very quickly understand syntaxes and mechanisms of language. It will not take for you longer than 20 minutes to start writing simple code, either. I was understanding what I was trying out, but I didn’t feel myself comfortable with realizing that anything can be changed in this language on the fly which could affect all of the prototypes of changed object. Note that there is no difference between class and object, or better to say, there are no classes in Io. If you define method on some object it is ultimately inherited to the clones. It worth to mention that in Io every operation is message. “Hello world” application which would look like:
Should be understood like: “send message “println” to the string object”.
Here is bit more code (sheep example cloned from this post):
Sheep := Object clone Sheep legCount := 4 MutantSheep := Sheep clone MutantSheep legCount = 7 dolly := MutantSheep clone MutantSheep growMoreLegs := method(n, legCount = legCount + n) dolly growMoreLegs(2)
The coolest thing about Io is its concurrency model, at least I think so.
Io uses coroutines, actors, yielding and future stuff. If you don’t know what it is about. Here is a bit of explanation. Coroutines in Io are user threads, built on top of kernel threads, which allows for quick switching of contexts and more flexibility in general. For simplicity think about coroutines as about threads. Any object can be sent message asynchronously, by adding @ symbol before the message name. This message is then places in object’s message queue for processing. Object would hold coroutine (thread) for processing those messages. Objects holding coroutine are called Actors. Effectively any object in Io can become Actor. When you call some methods asynchronously, result can be saved into so called “future”, value of which is resolved before it is used. You can switch between actors using “yield”. To demonstrate this, I prepared this small piece of code, which prints numbers 0,1,2,3 one by one:
oddPrinter := Object clone evenPrinter := Object clone oddPrinter print := method(1 println; yield; 3 println; ) evenPrinter print := method(0 println; yield; 2 println; yield) oddPrinter @print; evenPrinter @print;
If you found this to be interesting I recommend you to read Io Guide. There you will find many other interesting features of the Io language, which I didn’t mention.
Here are some links:
You may be wondering why I’m writing and learning something about old, small language, which even doesn’t have normal ecosystem.
I’m trying to learn more programming concepts and play with different languages. Recently I was even blamed for writing “enterprise-y code” and suggested to see how code looks like in other programming language communities. Well… of course it is valid and good suggestion, but not that I never thought about it. In my year plan post I mentioned that I would like to learn one more programming language and to start with something I picked up interesting book called “7 languages in 7 weeks”. So far I read and tried Ruby, Io and Prolog. Scala, Erlang, Clojure and Haskell are next in a row. After I’m done with book I will pick one language (not compulsory from list) and extend my knowledge in it. Of course there will be a review on the book.
I would like to share some experiences of working with Microsoft AppFabric Cache for Windows Server.
AppFabricCache is distributed cache solution from Microsoft. It has very simple API and would take you 10-20 minutes to start playing with. As I worked with it for about one month I would say that product itself is very good, but probably not enough mature. There are couple of common problems and I would like to share those. But before let’s get started!
If distributed cache concept is something new for you, don’t be scary. It is quite simple. For example, you’ve got some data in your database, and you have web service on top of it which is frequently accessed. Under high load you would decide to run many web instances of your project to scale up. But at some point of time database will become your bottleneck, so as solution you will add caching mechanism on the back-end of those services. You would want same cached objects to be available on each of the web instances for that you might want to copy them to different servers for short latency & high availability. So that’s it, you came up with distributed cache solution. Instead of writing your own you can leverage one of the existing.
You can easily download AppFabricCache from here. Or install it with Web Platform Installer.
Installation process is straight forward. If you installing it to just try, I wouldn’t even go for SQL server provider, but rather use XML provider and choose some local shared folder for it. (Provider is underlying persistent storage as far as I understand it.)
After installation you should get additional PowerShell console called “Caching Administration Windows PowerShell”.
So you can start your cache using: “Start-CacheCluster” command.
Alternatively you can install AppFabric Caching Amin Tool from CodePlex, which would allow you easily do lot of things though the UI. It will show PowerShell output, so you can learn commands from there as well.
Usually you would want to create named cache. I created NamedCacheForBlog, as can be seen above.
Let’s now create simple application. You would need to add couple of references:
Add some configuration to your app/web.config
<section name="dataCacheClient" type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core" allowLocation="true" allowDefinition="Everywhere"/> <!-- and then somewhere in configuration... --> <dataCacheClient requestTimeout="5000" channelOpenTimeout="10000" maxConnectionsToServer="20"> <localCache isEnabled="true" sync="TimeoutBased" ttlValue="300" objectCount="10000"/> <hosts> <!--Local app fabric cache--> <host name="localhost" cachePort="22233"/> <!-- In real world it could be something like this: <host name="service1" cachePort="22233"/> <host name="service2" cachePort="22233"/> <host name="service3" cachePort="22233"/> --> </hosts> <transportProperties connectionBufferSize="131072" maxBufferPoolSize="268435456" maxBufferSize="134217728" maxOutputDelay="2" channelInitializationTimeout="60000" receiveTimeout="600000"/> </dataCacheClient>
Note, that above configuration is not the minimal one, but rather more realistic and sensible. If you are about to use AppFabric Cache in production I definitely recommend you to read this MSDN page carefully.
Now you need to get DataCache object and use it. Minimalistic, but wrong, way of doing it would be:
public DataCache GetDataCacheMinimalistic() { var factory = new DataCacheFactory(); return factory.GetCache("NamedCacheForBlog"); }
Above code would read configuration from config and return you DataCache object.
Using DataCache is extremely easy:
object blogPostGoesToCache; string blogPostId; dataCache.Add(blogPostId, blogPostGoesToCache); var blogPostFromCache = dataCache.Get(blogPostId); object updatedBlogPost; dataCache.Put(blogPostId, updatedBlogPost);
In real world you would probably write some wrapper over DataCache or create some Utility class. There are couple of reasons for this. First of all DataCacheFactory instance creation is very expensive, so it is better to keep one. Another obvious reason is much more flexibility over what you can do in case of failures and in general. And this is very important. Turns out that AppFabricCache is not extremely stable and can be easily impacted. One of the workarounds is to write some “re-try” mechanism, so if your wrapping method fails you retry (immediately or after X ms).
Here is how I would write initialization code:
private DataCacheFactory _dataCacheFactory; private DataCache _dataCache; private DataCache DataCache { get { if (_dataCache == null) { InitDataCache(); } return _dataCache; } set { _dataCache = value; } } private bool InitDataCache() { try { // We try to avoid creating many DataCacheFactory-ies if (_dataCacheFactory == null) { // Disable tracing to avoid informational/verbose messages DataCacheClientLogManager.ChangeLogLevel(TraceLevel.Off); // Use configuration from the application configuration file _dataCacheFactory = new DataCacheFactory(); } DataCache = _dataCacheFactory.GetCache("NamedCacheForBlog"); return true; } catch (DataCacheException) { _dataCache = null; throw; } }
DataCache property is not exposed, instead it is used in wrapping methods:
public void Put(string key, object value, TimeSpan ttl) { try { DataCache.Put(key, value, ttl); } catch (DataCacheException ex) { ReTryDataCacheOperation(() => DataCache.Put(key, value, ttl), ex); } }
ReTryDataCacheOperation performs retry logic I mentioned before:
private object ReTryDataCacheOperation(Func<object> dataCacheOperation, DataCacheException prevException) { try { // We add retry, as it may happen, // that AppFabric cache is temporary unavailable: // See: http://msdn.microsoft.com/en-us/library/ff637716.aspx // Maybe adding more checks like: prevException.ErrorCode == DataCacheErrorCode.RetryLater // This ensures that once we access prop DataCache, new client will be generated _dataCache = null; Thread.Sleep(100); var result = dataCacheOperation.Invoke(); //We can add some logging here, notifying that retry succeeded return result; } catch (DataCacheException) { _dataCache = null; throw; } }
You can go further and improve retry logic to allow for many retries and different intervals between retries and then put all that stuff into configuration.
So, why the hell all this retry logic is needed?
Well, when you open MSDN page for AppFabric Common Exceptions be sure RetryLater is the most common one. To know what exactly happened you need to verify ErrorCode.
So far I’ve see this sub-errors of the RetryLater:
There was a contention on the store. – This one is quite frequent one. Could happen when someone is playing some concurrent mess with cache. Problem is that any client can affect the whole cluster.
The connection was terminated, possibly due to server or network problems or serialized Object size is greater than MaxBufferSize on server. Result of the request is unknown. – This usually has nothing to do with object size. Even if configuration is correct and you save small objects you can still get this error. Retry mechanism is good for this one.
One or more specified cache servers are unavailable, which could be caused by busy network or servers. – Have no idea how frequent this one could be, but it can happen.
No specific SubStatus. – Amazing one!
AppFabricCache is very nice distributed cache solution from Microsoft. It has a lot of features. Of course not described here, as you can read it elsewhere, say here. But to be able to go live with it you should be ready for AppFabricCache not being extremely stable & reliable, so you better put some retry mechanisms in place.
To be honest if I was one to make decision if to use this dcache, I would go for another one. But who knows, maybe other are not much better… I’ve never tried other distributed caches.
Thank you, and hope this is of some help.
May 20, 2012 C#, OData, Web 3 comments
In previous blog post I briefly touched OData protocol by showing quick usage of OData feed and then implemented ever simple WCF data service with using Entity Framework.
Now, let’s imagine that we have some data in memory and would like to expose it. Is it hard or easy?
If you can represent your data as IQueryable then, for most cases, you are fine. There is an extension method to IEnumerable called AsQueryable, so as long as your data can be accessed as IEnumerable you can make it IQueryable.
Now, let’s create some sample data:
private IList<Sport> _sports = new List<Sport>(); private IList<League> _leagues = new List<League>(); private void Populate() { _sports = new List<Sport>(); _leagues = new List<League>(); _sports.Add(new Sport() { Id = 1, Name = "Swimming"}); _sports.Add(new Sport() { Id = 2, Name = "Skiing"}); var sport = new Sport() { Id = 3, Name = "Football"}; var league = new League() { Id = 1, Name = "EURO2012", Region = "Poland&Ukraine" }; sport.AddLeague(league); var league1 = new League() { Id = 2, Name = "UK Premier League", Region = "UK" }; sport.AddLeague(league1); _sports.Add(sport); var league2 = new League() { Id = 3, Name = "Austria Premier League", Region = "Austria" }; _leagues.Add(league); _leagues.Add(league1); _leagues.Add(league2); _sports.Add(new Sport() { Id = 4, Name = "Tennis"}); _sports.Add(new Sport() { Id = 5, Name = "Volleyball"}); }
Absolutely nothing smart or difficult there, but at least to give you an idea about dataset we have.
To expose sports and leagues we would need to add public properties to our data service implementation like below:
public IQueryable<Sport> Sports { get { return _sports.AsQueryable(); } } public IQueryable<League> Leagues { get { return _leagues.AsQueryable(); } }
Another important thing about exposing data is that you have to indicate key for your entities with DataServiceKey attribute.
To make our service bit more realistic I’m going to add caching as well.
public class SportsWcfDataService : DataService<SportsData> { public static void InitializeService(DataServiceConfiguration config) { config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; // To know if there are issues with your data model config.UseVerboseErrors = true; } protected override void HandleException(HandleExceptionArgs args) { // Put breakpoint here to see possible problems while accessing data base.HandleException(args); } protected override SportsData CreateDataSource() { return SportsData.Instance; } protected override void OnStartProcessingRequest(ProcessRequestArgs args) { base.OnStartProcessingRequest(args); var cache = HttpContext.Current.Response.Cache; cache.SetCacheability(HttpCacheability.ServerAndPrivate); cache.SetExpires(HttpContext.Current.Timestamp.AddSeconds(120)); cache.VaryByHeaders["Accept"] = true; cache.VaryByHeaders["Accept-Charset"] = true; cache.VaryByHeaders["Accept-Encoding"] = true; cache.VaryByParams["*"] = true; } } public class SportsData { static readonly SportsData _instance = new SportsData(); public static SportsData Instance { get { return _instance; } } private SportsData() { Populate(); } private void Populate() { // Population of data // Above in this post } private IList<Sport> _sports = new List<Sport>(); public IQueryable<Sport> Sports { get { return _sports.AsQueryable(); } } private IList<League> _leagues = new List<League>(); public IQueryable<League> Leagues { get { return _leagues.AsQueryable(); } } } [DataServiceKey("Id")] public class Sport { public int Id { get; set; } public string Name { get; set; } public void AddLeague(League league) { _leagues.Add(league); } private IList<League> _leagues = new List<League>(); public IEnumerable<League> Leagues { get { return _leagues; } } } [DataServiceKey("Id")] public class League { public int Id { get; set; } public string Name { get; set; } public string Region { get; set; } }
With this URL http://localhost:49936/SportsService.svc/ service can be seen:
<service xml:base="http://localhost:49936/SportsService.svc/"> <workspace> <atom:title>Default</atom:title> <collection href="Sports"><atom:title>Sports</atom:title></collection> <collection href="Leagues"><atom:title>Leagues</atom:title></collection> </workspace> </service>
Now, you can access data via URL or by writing C# Linq queries if connected with client app or LinqPad. Following request:
http://localhost:49936/SportsService.svc/Leagues()?$filter=Name eq ‘EURO2012’&$select=Region
Would produce result containing this:
If you need your data to be updatable, your SportsData would need to implement System.Data.Services.IUpdatable interface.
What if you have very special data source, or you cannot simply keep your data in memory like collections of some data? This could be tricky or very tricky, depending on your data source, of course. But anyway you would need to implement interface IQueryable by hand if not provided by your data source.
Here is step-by-step walkthrough on msdn. Only by size of article you could imagine it is not trivial task to do. But if you managed to do it you can be proud, because you can implement your own Linq provider. (Do you remember NHibernate introducing support of Linq? It was big feature for product, roughly all they did was implementation of IQueryably by their NhQueryable.)
First of all I have to investigate if my team can use it. (Depending on outcome you might see more posts on this topic from me.) And another reason is that it is very exciting topic, about which I knew so little.
Very disappointing to admit that I start to really understand things when I touch them for reason and that reading dozen of blog posts on topic is useless unless I do something meaningful related to matters in those posts.
So, my Dear Reader, if you are reading this post and have read my previous post, but never tried OData I would be really pleased if you invest 10-30 or more minutes of your time to play with OData.