In order to access an object even after postbacks, you need to put it either in the Session or the ViewState. The ViewState is preserved only between postbacks, not between different pages and it is a Page property, so it is more efficient to use it. The problem with this method is that every object you put in the ViewState must be serializable. So, the quick and dirty path: if you don't have strange custom serializing to do, all you have to do it to decorate the object with the [Serializable] flag, like this:
Say you wouldn't have done this, you would have probably met with the "Class is not marked as Serializable". Duh!. However, in this situation above I have inherited from an object that implements ISerializable. I will get an error "The constructor to deserialize an object of type ... was not found". What that means is that the object must have a constructor that accepts two parameters, a SerializationInfo and a StreamingContext object. So we must add it to the object, like this:
public MyDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { }
public MyDictionary() {}
}
I added the second constructor because when adding a parametrized constructor, the default empty one is no longer inherited. So no more new MyDictionary() unless one adds it.
That does it! Please do check out the entire ISerializable interface documentation, since it requires, besides the constructor, a GetObjectData method, with the same parameters as the constructor, which controls the custom serialization of the object.
Now, you might ask yourself what has the girl in the image with making your own girlfriend. Look closer, it's not a girl (and not a nigth elf either) it's a computer generated image, made from scratch.
Update October 6 2014: New stuff, compare Levenstein vs Sift here:
Algorithm: Levenstein Sift
String 1: String 2:
Result:
Update June 25th 2013: I've decided to play a little with the suggestions in the comments and check for validity. This was spurned by the realization that a lot of people use my algorithm. So, in order to celebrate this, here is the "3B" version of the Sift3 algorithm: It is made in Javascript, this time, as it was easier to test and has the following extra features:
a maxDistance value that tells the algorithm to stop if the strings are already too different.
two pointers c1 and c2, rather than a single pointer c and two offsets
Instead of dividing to 2 the total length of the strings compared, now I divide it with 1.5. Why? Because this way the value is closer to the Levenshtein distance computed per random strings
Happy usage! The variant I posted was totally buggy. I removed it. Just use sift3Distance.
A while ago I wrote an entry here about Sift2, an improvement of Sift, the original and silly string distance algorithm. Now I am publishing Sift3, which is way more accurate and even simpler as an algorithm.
I found out that my algorithm is part of a class of algorithms that solve the Longest Common Substring problem, therefore I calculated the LCS, not the distance, then the distance from the LCS. The result is way more robust, easy to understand and closer to the Levenshtein algorithm both on random strings and user databases. Not to mention that there is no goto in this one.
BTW, if you are looking for an algorithm that detects switched words, this is not it :) This just looks for typos and small regional differences between the strings. I mean, you could normalize the strings, so that words are ordered by some mechanism, then it would work because the words wouldn't be switched :)
I promise to work on a word switching algorithm, but not in the near future. Without further ado, here is the code:
The C# code is a method in an object that has a private member maxOffset. As in Sift2 maxOffset should be around 5 and it represents the range in which to try to find a missing character.
publicfloat Distance(string s1, string s2, int maxOffset) { if (String.IsNullOrEmpty(s1)) { return String.IsNullOrEmpty(s2) ? 0 : s2.Length; } if (String.IsNullOrEmpty(s2)) { return s1.Length; } int c = 0; int offset1 = 0; int offset2 = 0; int lcs = 0; while ((c + offset1 < s1.Length) && (c + offset2 < s2.Length)) { if (s1[c + offset1] == s2[c + offset2]) lcs++; else { offset1 = 0; offset2 = 0; for (int i = 0; i < maxOffset; i++) { if ((c + i < s1.Length) && (s1[c + i] == s2[c])) { offset1 = i; break; } if ((c + i < s2.Length) && (s1[c] == s2[c + i])) { offset2 = i; break; } } } c++; } return (s1.Length + s2.Length)/2 - lcs; }
And here is the T-Sql code. This version is actually an improvement of my original source, gracefully provided by Todd Wolf:
CREATEFUNCTION [DBO].[Sift3distance2] ( @s1 NVARCHAR(3999),@s2 NVARCHAR(3999),@maxOffset INT ) RETURNSFLOAT AS BEGIN DECLARE @s1LEN INT,@s2LEN INT
IF(@s1Pos>0 AND (@s1Dist<=@s2Dist OR @s2Pos<1) AND @s1Dist<@maxOffset) SET @s1Offset=(@s1Pos-@wrkPos)+1 ELSE IF(@s2Pos>0 AND (@s2Dist<@s1Dist OR @s1Pos<1) AND @s2Dist<@maxOffset) SET @s2Offset=(@s2Pos-@wrkPos)+1 END
SET @currPos=@currPos+1 END
RETURN(@s1LEN+@s2LEN)/2.0-@matchCnt END
It doesn't give the same exact results as my own code, yet the result is close enough and the speed is about 20% higher.
Update 2020 - most of the links here are dead, the things they referred to long forgotten. So much for "once you put it on the Internet it never disappears".
Having reached the 200th entry, I really wanted to write something cool, something interesting, something that sticks (and it ain't shit).
I thought of blogging Kartoo, a very nice - albeit slow - visual search engine that shows not only relevant links, but also the context items that link different pages.
But Kartoo is not personal enough, so I switched to YouTube, thought about blogging (yet another) female vocalist nu-metal with goth overtones band like the Italian band Exilia. Or something else, like the Turkish band maNga, or the Spanish Dead Stoned or Demiurgo. But this is a blog, not a video/music site.
Then I thought about programming; there must be something in the three projects I am working on worth blogging about, or at least something important like Don't use the .NET Random class when concerned about security. But then again, the blog is full of (I hope) interesting programming hints.
Reading this article on digg, I began searching the web for this very cool religion called Pastafarianism and I feel that it relates to me in a very spiritual way. In other words, it makes me laugh my ass off!
As you can read in the Wikipedia article, the Flying Spaghetti Monster created the world (or is it the other way around?) in order to prove to idiots that you either think or you believe. There is no middle ground. Thinking requires trusting your observations, emitting theories and then validating them by using observed data. Believing doesn't require anything, therefore being easier to do, and can (and most of the time will) deny your ability to observe, your capacity to reason or to grasp reality and look down on your desire to understand anything that is believed.
Well, seriously now. One cannot believe the world was created by the Spaghetti Monster... Or maybe one can, as long as they accept the obvious fact that the Spaghetti Monster was created by the Invisible Pink Unicorn.
You sometimes need to copy the exact structure of a database to an Sql2000 server, even if the source server is 2005.
Follow these steps:
open 2005 Sql Server Management Studio
right click on the offending database and go to Tasks -> Generate Scripts
do NOT check Script all objects in the selected database
click Next
set Include if NOT EXISTS to False
set Script for Server Version to SQL Server 2000
try to check only the objects and types of objects you actually need
create the script
delete all occurences of "WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)" from the generated script
Now the script should work on an SQL 2000 Server.. For the copying of data, the Server Management Studio has an option called Copy DatabaseExport Data, also in Tasks, that now accepts an Sql 2000 Server as destination.
In the Romanian jargon there is an insult: slave. It appeared ten years or so ago and it stuck. It probably came from Gypsy talk, probably holding more meaning to them, since they were liberated from slavery and into the worst social problem Romania has. But at least the cool ones are not slaves anymore, even if they recreate daily the hated cliche of the typical Gypsy Roma and are stuck in the mentality that work is somehow a shameful act.
But the word is also used by Romanians. You might see young people that have a little business or a scheme to get money quickly use it to refer to the people that are employed somewhere and go to work every day. And they are somehow right, since a lot of the rich people in Romania, business owners, top managers, land owners, etc. are uneducated folks. Instead of going to school, they chose to fight, risk, learn in the school of life. And it shows. They have a lot of money and no manners. They have a lot of opportunities, but don't really use them. They are no longer rude people with no money, they have money now, but are stuck into being the same people they started with. Kind of like the joke where the anus wanted to be the manager of the body.
How about the slave, then? The guy that goes to school, goes through all the (mechanical) motions of learning, passing exams, getting a job, living a "normal" life? Well, we are mostly wasting our time. The money we get are what we need to live, maybe even enough to get a car or, if one is lucky, an apartment. People like us spend their entire lives surviving and dreaming about what we would do if we had more money. Meanwhile, we lose 8 hours a day working, 3 preparing and going to work, 7 sleeping, 1 or 2 eating and are left with 4-5 hours in which to do "what we like". If that isn't slavery, I don't know what is, but in all that time we make the system work.
Slimy manager types that themselves work for uneducated bullies that somehow got into fortune work in the system as well. Poor 'unslavy' thieves occasionally steal something, thus making policemen work all day and accept bribes. Businesses run into the political framework maintained by corrupt politicians who themselves obey the laws of economics, which are heavily influenced by the people from other countries, who themselves are only cogs in this great machine we call humanity. And of course, all those good managers that work for great people and all the Gypsies that go to school and work and all those politicians who actually want to make a difference, too.
This is no freedom, we are all slaves. We allow ourselves to be blinded by a value system, be it invented by us or just stolen from someone else, and we live by it. We all choose our swords and then we let ourselves die by them. True freedom is inside, not outside, it's in the dreams, not in their realisation. I might even venture on saying that it's in the quantity of the dreams, not their quality, because that is what enslaves us, dreaming of a single thing, being desperate to achieve it and then to hold on to it.
I need your input, readers dear! I've changed the blog so that when you double click on a word a google window appears that you can expand, close or scroll at your leaisure. Do you like it? Would you like to dblclick and search this blog instead? Or maybe digg or something? Do you hate it? You want it removed? Does it hinder you in any way? Thanks.
I've found this interesting article by John Cronan about using the Abstract Factory pattern to access files, no matter if they are on FTP, HTTP or the local or networked file system. Basically he uses WebRequest.Create rather than any *Stream* class.
Interesting enough, he seems to be the only one providing a solution to the problem of accessing local file system resources when the default access rights do not allow you to, even if the logged on credentials would normally give you the access, thus solving an issue of the FileWebRequest class. Unfortunately he uses P/Invoke, which kind of contradicts the whole "more flexible than thou" approach of the article.
Overall an interesting read which gives you flexibility of file support, while taking away some of the specific advantages like seeking or appending. It's a definitely better approach than StreamReader and the ugly "URI formats are not supported." error.
A bonus for using this method is that it is compatible with the Office 2007/Vista Open Packaging addressing model, by way of the PackWebRequest class.
I've just finished watching "Free Energy - the Race to Zero Point", which is a documentary of sorts listing ideas of ways to produce free energy with open systems, or getting a lot more efficiency than present systems. The speakers are authors of controversial books and editors at magazines names as crackpotty as possible. The narrator himself looks like a Hitchcock wannabe, presenting the end of the world. Heck, the film is not even listed on Imdb, therefore this blog entry. But, even if I am mostly convinced that this is a piece of sensationalist propaganda and not true science, I am left wondering how much (if any) of this is truly real? Did Moray have a device that lit up light bulbs without fuel or batteries? Are the numerous inventors presented there just crackpots or do they have something? I find it difficult to believe that all video proof that was presented in the movies was faked. Why would they? Yet most of all I resonated with the idea that is, unfortunately for this movie, presented by all featured people: economic interests reign supreme and devices that don't need to be connected to power grids, use oil or that can be regulated by established industries are not only avoided, but actively attacked. It does make sense, doesn't it?
Well, I don't. I was first shocked to find out that the 1918 "Spanish" Flu pandemic killed 50 million people and I found out about it only in my twenties. Now I see that the pandemics are recurring events, there are lists with the virus strains and where they originated, while information from before 1900 is unreliable since medicine was not really.
Check out this link that shows a history of flu strains and the three flu pandemics from the last century.
While listening to my favourite songs on Pandora, I heard a song that I really enjoyed. The band was The Provenance, from Gothenburg, Sweden. and I immediately started looking for more on the Internet. Here is one of the best songs I've heard in a while, with a video that could have been way better. The music, though, is worth it.
They have a site, but not very updated and, since they just released their fourth album but only joined YouTube in October 2006, I guess they are not really Internet people. So let's us lend them a little hand, shall we? Official Web Site - Actually, their site is dead, their domain for sale. MySpace site - ugh, it seems that the band has been... well... disbanded. Their last blog entry says as much: "bye". YouTube user site
Of course, sooner or later YouTube blocked this video. Let's try something else:
It seems there is a fashion of combining English and Japanese in popular music in Japan, but this is really ridiculous. Just check out the lyrics: "Not a Chinaman 'cause I ain't from China, man... I am Japan, man.". Damn that's funny :))
Enough with this! Geeks are not supposed to move, even use their hands to push something so small as a mouse. Moving a mouse all day builds muscle and you know that is bad! So check out the OCZ Neural Impulse Actuator at work. A head band, a wire, no movement. Geeky! I want one of those!
In other words: those curly bracket things in SQL. What? curly brackets in SQL? Yes! Imagine that :)
The idea is that most database systems adhere to the ODBC standard, at least ODBC 1.0. That means that, when you communicated with a database, you can send so called ODBC escape sequences that are translated into the SQL engine native objects.
Quick example: SELECT {d '2007-03-15'} will work in all ODBC 1.0 compliant DBMSs, including Microsoft SQL Server, MySql, PostgreSQL, Oracle, etc. and select a date object from 15 of March 2007, no matter the server configured country or language.
Interested yet? You can read the ODBC Programmer's Reference for more details. Short story shorter, here are the working and interesting parts (to me) of the ODBC escape sequences: select {d '2007-02-13' } select {t '22:20:30' } select {ts '2007-02-13 22:20:30' } select {fn curdate()} select {fn curtime()} select {fn User()} select {fn Database()} select {fn week(getdate())} select {fn quarter(getdate())} select {fn monthname(getdate())} select {fn dayname(getdate())} select {fn curdate()} select {fn dayofweek(getdate())} select {fn dayofyear(getdate())} select {guid '12345678-1234-1234-1234-123456789012'}