Hacking Bangkok Blog

Tech and Living in Thailand's City of Angels

The Hacking Bangkok blog covers I.T. and technology in general, and my experiences working and living in the Kingdom of Thailand. Bangkok has a very long Thai name, which starts with Krung thep - City of Angels.
Bangkok sunset from my bedroom balcony

Thursday, July 16, 2009

Succumbing To The Gaming Bug: Half-Life 2 and My Sort-of Gaming PC

Back in April, I was trawling the Gizmodo site to avoid doing actual work one weekend, and read about some "insane" deal on PC games from game-developer Valve (who I'd barely heard of). The deal was for a package of games, delivered via Valve's online-download service/gaming-community site/software, Steam. The package - called the Orange Box - was up for $10 (or 10€ if you're in Euroland!), and included Half-Life 2, Half-Life 2 Episodes 1 & 2, a mini-episode called "The Lost Coast", plus "Portal", and Team Fortress 2 (a month-pass to the multi-player version).

Full disclaimer - before reading the Giz article, I had only vaguely heard of Valve and Steam, had never heard of Half-Life (or the sequal, HL2), or Portal. The last PC game I played was Unreal Tournament, back in 2001 or so. I was just never a gamer - other than UT (which I didn't play that much anyway), I really hadn't been into games since the days of Joust, and the original arcade vector-graphic Star Wars (and Battle Zone for that matter). And if you're too young to remember those, well, I played Star Wars in the arcades in the mid-80s. Heck, the last game I really loved was Missile Command, from the early 1980s. Doh!


So anyway - it was a boring weekend, and for 10 bucks, I figured I would bite. I bought the pack, and download "Half-Life 2" first. And then promptly forgot about it for two weeks.

Eventually, I fired it up on my two-year-old Thinkpad T60 (Core2Duo 2.0 GHz, ATI Mobility Radeon x1400 discrete graphics with 128 MB VRAM, 3 GB DDR RAM), and started playing on a Thursday night about 9 pm. And from the opening scene, on the train into City 17, I was pretty hooked.

I had no idea what the game was about - didn't bother to read up on it first - so it came as a bit of a shock to me when I noticed my bedroom getting lighter, and realized the friggin sun was coming up! It was after 5 am. Doh!!!

Over the next week, I spent waaay too many hours finally "winning" (if you can call the wierd ending "winning"). Some of the puzzles took a long time to solve, and I decided early on not to look up anything on the web, so I died a lot of stupid deaths figuring things out. Half-Life 2 is, bar none, the best computer-game I've ever played. Even on a laptop that was decidedly not made for gaming (lucky for me, HL2 is from 2004, so my circa-2007 Thinkpad and graphics card did a decent job of keeping the frame-rate high).

But for playing the episodes, and portal (and for watching downloaded movies & shows on the HDTV in my bedroom), something a little beefier was needed. There is a ton of info on the web on every component of a "gaming system". I read the excellent "$800 Killer Gaming PC" article on ExtremeTech, although I didn't go with their system. I wanted something that didn't look like a gaming PC (or a PC at all, really) that would fit in my bedroom, and pull double-duty as a Windows Media Center. Plus, it didn't need to be super-high-end: it's hooked up to a 720p HDTV, which has a mas resolution of 1366x768. And, like most techies, I have a box of old components and stuff I could salvage, to cut costs. So here's what I made:













The parts I scavenged from my box-o-junk (meaning, I didn't have to buy!):
  • 2 x 160 GB 7200 RPM SATA-II drives out of an IBM x-series server.
  • LG DVD r/w drive, which spent some time in that same IBM server - and so had a black faceplate already slapped on it from last time I re-used it.
  • LinkSys WUSB11 WiFi adapter (which dates waaaay back!)
  • Very thin IR remote control + USB receiver (from some tuner-card I don't remember)
  • Cheap wireless keyboard with pointing stick, which has great range anyway (like, more than 10 feet)
  • Windows 7 Ultimate RC, which I had already downloaded. It's good until next April or something, and free until then!
Stuff I bought from Pantip Plaza, the nearby giant computer/gadgets mall:
  • Gigabyte EG45M motherboard
  • Intel Core2Duo 2.8 GHz dual-core CPU (45 nm lithography)
  • ATI Radeon HD4870 graphics card (512 MB version) from HIS
  • 4 GB of DDR2 RAM
  • OCZ Silencer 500W power supply
  • SilverStone SST-SG01-F case
Total cost: 20,500 Thai Baht (about $595 at the time I bought it).

I almost opted for the all-aluminum version of the SilverStone case - it's lighter and allegedly dissipates heat better - but it was about $40 more than the steel one I got, and I'm not going to be moving this thing around much anyway. Another compromise was the Core2Duo, rather than a Core i7; the i7 chips are a lot more expensive, and (more importantly) the motherboards that support it are a lot pricier too. Instead, I put money into the graphics card.

The Radeon HD4870 is a pretty high-end card, but I got it for about 5,500 baht (~ $160 USD), probably because the newer HD4890 card is out. The 4890 was close to double the price, but maybe 20% faster in the reviews I read. And like I said - I'm generally playing at 128x720, or maybe 1680x1050 if I plug it into my "work" monitor, so at $160, it was a no-brainer. Plus it supports DirectX 10, Microsoft's new 3D video tech.

Probably the most interesting thing (or at least, surprising because it was interesting!) was the lowly power-supply. It had this high-end "feeling" (coating?), all the cables ran through mesh-tubing to keep them from getting tangled, and it provides power to the USB ports even when the computer itself is off. This is great for charging an iPhone or, say, my Touch Diamond overnight. Plus, it really is silent - from more than a foot away, you literally can't hear it (or the case-fans either - kudos to SilverStone for great ventilation design and silent fans).

I didn't take screen-caps, and photographing a TV with a digital camera leaves something to be desired, but Half-Life 2 (especially Episode 2, and the Lost Coast) and Portal look just amazing, with all settings cranked to "high" and anti-aliasing on. Later, I bought "Crysis" (again, using Steam's online store), and that also runs smoothly at 1280x720 with settings at "high". The Gigabyte micro-ATX board supports up to a quad-core "Core2Extreme" CPU, so there's some room for upgrading. The saddest thing is that Portal (while fun) and Crysis (beautiful) aren't nearly as fun as HL2. Later, I read that HL2 was one of the highest-rated games of all time, so maybe my expectations are high now. I'll check out "Left4Dead" at some point too (L4D 2 is coming out this fall also...).

This is a photo of HL2 Episode 2, in the beginning, with in-game "girlfriend" or whatever Alyx is supposed to be:


You'll just have to trust me that it looks much better in real life, especially moving with perfectly fluid motion (that BenQ TV only refreshes at 60 Hz, and HL is rendering faster than that).

For all the gamers out there (at least, any gamers that find my blog, hahah), this is probably old, old, OLD info - even Crysis isn't really a new game - but for me, being immersed in Half-Life 2 was really eye-opening. It's like starring in your own movie, with special effects that Lucas and Spielberg could only dream of when I was a kid. Now, if Valve would just hurry up and finish Half-Life Episode 3, (or even HL3?) then I'd have a chance to really feed my addiction again!

Thursday, May 7, 2009

Some Phone-cam Shots From Turatao Park

I'm sending this from my phone, with it's *very* sketchy EDGE connection, while sitting in an open-air reggae bar on a beach at Koh Lipe. So, I've got my fingers crossed that the pics will make it through at all.

My back is totally sunburnt, but the all-day snorkeling trip was great - went to two smaller islands, plus three other dive/snorkel spots. The fact that I can access email and (in limited, slow fashion) the web, while riding in a wooden longtail boat off the coast of Thailand still amazes me, when I stop complaining about the crappy bandwidth for a minute!

Last nite, I tried playing "Half Life 2: Episode 1", with the trackpoint (pointing stick) on Thinkpad - let's just say, for some things, you *really* need a mouse or trackball. I died about 11 times taking refugees to the train station.

There's some updated info on the never-ending 3G saga in Thailand (hint: delayed!!), I'll post an update when I have a real keyboard.

Wednesday, May 6, 2009

Breakfast on the Beach at Koh Lipe

This was the view from my breakfast table, I'm at Koh Lipe (an island off the coast of southern Thailand)l I'm on that boat RIGHT NOW trying to send this before I lose EDGE connectivity. Going snorkeling today, diving tomorrow!

Thailand is just amazing.

Sunday, April 26, 2009

Commercial Fusion Powerplants - Finally Less Than 30 Years Away?


ITER - "Maybe in 2050"

For as long as I can remember (and a lot longer, actually), nuclear fusion as an energy source has been touted as "30 years away" from reality. Other than a very short few weeks twenty years ago, when two scientists (Pons and Fleischmann) announced they they had achieved room-temperature fusion - which turned out to be a dud - fusion for power has been pretty much an R&D effort only.

Heck - instead of getting closer, a working fusion reactor that puts out more power than it uses up has seemed to actually recede into the future; the global consortium of countries that finally decided to build a test reactor is planning to flip the switch on it sometime after 2018. The consortium, the International Thermonuclear Experimental Reactor (ITER), is building their beast (see the rendering above) in France. Their fast-track plan (meaning, "if all goes well"), would lead to the first commercial fusion plant starting to put out some juice around the year 2050. Yawn!

Full power to lasers, Scotty!
Not that I'm knocking their project - having fusion power in 2050 beats the crap out of "never", but yowza, this project was actually started back in 1985, and they just broke ground last year (in 2008). So I wouldn't hold your breath.

Slightly smaller in scale than ITER's tokamak is America's "National Ignition Facility" (seen posing as a Death Star under construction in photo), a DOE project.


While NIT is more aimed at modeling mini-explosions using boucoup lasers (192 world-beating lasers that all fire simultaneously), they also think they'll beat ITER to the "break-even" punch by years, possibly by 2012. Going from there to a commercial reactor is still a loongggg way, though. Call it 2030 or so.

Enter, private enterprise. Much like SpaceX and Scaled Composites have shaken up the space business, it seems there are a few companies working on commercial fusion power. And I'm not talking about complete frauds, like the infamous "Steorn Energy" (which put an ad in The Economist a few years ago declaring they'd invented a perpetual motion machine...). And some of these companies are raising millions in capital - no mean feat in the teeth of a global recession, if they can pull it off. Others raised millions over the past few years.

Just in the past few weeks, I've read about a few different companies all working on fusion. Helion Energy, which built the plasma fusion prototype shown in the photo at right (photo from Fast Company's website), is looking for $20 million right now. Granted, their prototype looks like it came straight out of Dr. Frankenstein's lab, but if the full-scale model they're hoping to build works, I'm guessing they plan to have something commercial before 2050!! (According to the Fast Company article, they hope to have a commercial plant running by 2022 or so).

Another company is the very secretive Tri Alpha Energy (their site is currently "under construction", although the internet archive shows it from last year with the simple message, "TRI ALPHA ENERGY, Inc. is a company dedicated to energy research". According to Wikepedia, Tri Alpha is working on a type of beam-collision fusion, also referred to in one article as a "plasma electric generator". They raised a cool $40 million in 2007, and haven't uttered a public peep about the fusion research since - although they did announce some sort of solar-powered electric-car charging station last year (so, I really have no idea if they're covering all bets or what?)

There are a few other companies out there - General Fusion and Electron Power Systems - which have also gotten some press. And finally - this year, on the 20th anniversary of the original conference where Pons & Fleischmann made their ill-fated announcement - a scientist at the U.S. Navy's Space and Naval Warfare Systems Center (SPAWAR) announced - wait for it! - that she had, in fact, found strong evidence of cold fusion. Only, she was too clever to call it that - now it's "low energy nuclear reactions", since "cold fusion" has that "oh crap, this is bogus" ring to it.

So - we've got the long, longggg term international effort, the medium-term U.S. national effort, and some scrappy start-ups all either cutting metal, or getting ready to test out hardware. Is fusion's time finally here, or at least less than 30 years away?

I think it is. With global climate change providing part of the impetus, and a finite (if large) amount of oil that has spiked above $100/barrel in the past, there's definitely incentive like never before to pull it off. And I don't think we'll be waiting until 2050, honestly.

Wednesday, April 22, 2009

x86 Smartphones - Still Inevitable, and Almost Here!

In a blog-post last November, I wrote about what I think is the inevitability of x86 (or x64) smartphones . I wanted to follow-up on that post with a quick look at what's happened in the five months since, and give a few more reasons why I still think that IA (Intel-architecture) chips will be the brains of most high-end smartphones within five years.

Right now, chips designed to run
ARM's risc-based instruction set (usually just called "ARM" CPUs, even though they're made by a variety of companies) power every high-end smartphone that's in mass production: Apple's iPhone, the HTC Touch and Touch 2 series, Nokia's S60-based assorted models, the about-to-be-released Palm Pre, and the HTC Android handsets (G1 and G2, respectively) all use ARM CPUs. Companies like Marvell and Panasonic make the actual chips themselves. For a time, even Intel licensed ARM, for use in their "StrongARM" processors that powered early Windows Mobile PocketPCs like the Compaq iPaq.

In the past few months, Intel has shown off a prototype smartphone-like device, made by LG, which uses Intel's Moorestown platform. Moorestown (which uses a new "Atom" CPU) is one of many code-names for different chips and chipsets that Intel is working on, a lot of which are targeting the low-power market. While Intel talks a lot about "MIDs" (mobile internet device), these things haven't really taken off, and now Intel has put the circuitry for 3G wireless networks (e.g., cellphone communications) into new low-power system-on-a-chip (SOC) designs. They're showing off Atom processors that can "idle" at 0.65 watts (650 milliwatts), which is still a lot more than an ARM processor, but the next-gen of these chips will (according to Intel) idle at less than 100 milliwatts, which puts them in striking range of ARM chips. According to eWeek , LG will ship an x86 smartphone next year (2010).

So on the one hand, we've got x86 chips from Intel and Via (which makes the low-power-consumption "Nano" cpu) trending to lower and lower power-consumption, and on the other hand, we've got battery technology. Now, I know that batteries have been the dog of tech for a long time - the technological millstone around our mobile gadgets collective necks - but it
is improving. The energy density (measured in Watt-hours per kilogram, or "Wh/Kg") of lithium-ion (Lion) batteries has roughly tripled since 1995. So for a same-weight battery, you get three times more juice. If you look at a graph of the average energy density over time - see the graph on page 4 of "Trends in energy and power supply of mobile phones" (PDF) - it's pretty clear that batteries are following their own very slow version of Moore's law.

There has been a rash of news over the past two or three years about dramatic improvements to the energy density of Lion batteries; most of these have involved changing the makeup of the cathode and anode, or using nanotechnology to change their microscopic "shape". Some of these improvements really qualify as breakthroughs - we're talking three to ten times the current energy density. It looks like lion batteries will, in about five years time, store at least triple the power they do now, and maybe a lot more.


And what's the biggest single advantage of the ARM chips used now? They're power-sippers, using half or less, of the power of even Intel's Moorestown CPU (which isn't even out yet). And the companies that make ARM chips will no doubt try to improve their performance. But we're rapidly approaching the point where a battery the same size as the ones used in smartphones today, will power an x86-based smartphone for just as long as they power ARM chips today, and maybe
close to as long as the ARM chips they'll be competing with. Let's call it 2013 or so. So, what will be the advantage, then, of the x86 smartphone? Some of these I talked about in my other post - things like using existing device-drivers, not needing to re-compile existing desktop software, and the massive base of software developers who write apps for PCs, Macs, and the most popular Linux hardware (which is x86). When x86 is knocking on your market-segment, history has shown that "close" is "close enough".

Another advantage will come from what I think might be a new popular form-factor for computers: I think we'll start to see modular computers, where the CPU and a touch-screen (along with a few tens of GB of storage) are in your smartphone, and then you'll just pop that into a "docking bay" that has a full-sized keyboard, and a 15" monitor along with a bunch more storage (say, a TB or so), which you'll use as a laptop when you want that form factor. The GPU in the smartphone will probably be powerful enough for playing back HD movies, but for gaming, maybe your docking station has a discrete graphics card and another multi-core CPU to beef it up.


In other words - I think it's at least possible (not sure how probable!) that our mobile phones are going to become our computers, and that keyboards, screens, storage and 3D-graphics processing all become periphals. You won't need to "sync" your phone to your PC anymore, because your phone will be the PC. Plug it into your TV's HDMI port to watch movies you've downloaded, or even better, stream them via Bluetooth 3 (assuming you have some Bluetooth-to-HDMI plugged into your TV). If you're on a plane, or waiting in line at the post office (because some things never change), you can watch the same movie on the 3.5" touchscreen. Whatever OS you're running, my guess is it will have two totally different UI "modes", a mobile-centric one, and a "laptop" centric one. So when you're using it as a notebook, you can run Windows 8 (coming in 2012) or your favorite Mac OSX or Linux distro, and when you're out and about, you'll use something more like Android's UI.

Not everything I predicted is going to come to pass exactly like I've laid out here (how I wish I were that good!), but the overall trends of x86 chips needing ever less power, and batteries providing ever more power, are going to eventually mean we're all carrying around Intel or AMD computers and calling them "phones".


*Note - image via Flikr, taken at Intel's developer forum in 2008. My guess is, most of the developers are guys, based on what's on the screen!

Bar Camp Bangkok Returns: BarCamp Bangkok 3 (Rise of the Geeks!)

For anyone who read the first few posts in this blog last year, you might remember that in August I wrote about the first BarCamp Bangkok. It was a two-day event, held on the (beautiful) campus of Chulalongkorn University. I actually posted a second blog entry from my phone, via email, where I gave a mini-wrap-up of my experiences on day one.

BarCamp is actually a user-generated content symposium, not a camp to learn how to make drinks, despite the name! Many of the people who show up come with a prepared presentation on their favorite I.T.-related topic, and at the beginning of the day, they post their topic on a wall. The topics with the most votes are get a room to present. There were upwards of eight or ten presentations going simultaneously last year, which sometimes meant choosing between hearing Google's team discuss Google Apps, or sitting in on the "How to date Japanese Girls - Tips from a Japanese Girl" (which was insanely popular with the Thai guys, natch!)

Oh - for anyone wondering about BarCamp 2, that was held in Vietnam. I would loved to have gone; Franz Nitz, the friend I went to BarCamp at Chula with, did go to the one in Vietnam - I'll have to find out from him how it stacked up! Since he has a Google news-alert set up on his name, I'm betting he'll find this post, and let me know ;-)

BarCamp Bangkok 3 (hit the link for the official site) will be held on May 23-24, 2009 at Sripatum University. The Sripatum website does have a map, but the entire site is in Thai (and completely in Flash), so I'm posting a Google Map of the location here:

View Larger Map

Or just view the map in another tab/browser.

I'm definitely planning on going again, this time for both days. A friend from the U.S. (but who is actually German) is hopefully visiting during that time, and since he's in I.T. also, we'll hopefully both go, and report back here on how it goes. Last year there were great presentations from both big shops, like Google and Mozilla (where I got a great Firefox sticker for my ThinkPad), as well as smaller companies and individuals. Even Franz gave a presentation on creating an Agoda affiliate website (which I'm betting he'll do again this year!)

Anyone else planning on attending? Leave a comment below if you've got a great topic to present, or a topic you're hoping to see.

Saturday, April 4, 2009

Maybe There Is A God - Terminator 4 Is Almost Here

This is a (somewhat blurry) pic of a 'Terminator 4: Salvation' display in front of the entrance to a theater I go to near my condo. I was really doubtful about another installment of the Terminator franchise after the mess of 'Rise of the Machines', but when I heard Christian Bale was playing John Connor, I suspended my doubts.

I'm sending this blog post out from my trusty Touch Diamond, which has served pretty well over the past 10 months. Still, I'm betting this will be a big year for android (and possibly the first viable x86 smartphone, given that "Moorestown"-based LG prototype Intel has been showing around).

Tuesday, March 31, 2009

Adventures With Linq-to-SQL: The Update Dilemma


I haven't written a post that goes into much (any?) detail on what I am working on over here, so this is that post. Since December, I've been working on a set of applications for a recruiting company, to replace the apps that they're using now (which I also wrote, about three years ago mostly). The old version, while it works, has some design flaws (some of which I inherited by way of using the database that held the previous never-finished attempt to create the app, built by some local programmers), some of which were inherent in using Windows .Net forms, and some of which resulted in my (over-) reliance on DataSets for storing object data.

So the new version of the app is an almost-complete rewrite; it uses SQL 2008 (or SQL 2005) rather than SQL 2000, but the bigger changes are that I'm using WPF for the UI, and Linq-to-SQL for almost 100% of the data access layer. Linq is beguilingly easy to use. Instead of writing code along the lines of, "If Not IsDBNull(ContactDataSet.Tables(i).Rows(j).Item("Name"))", I can just write, "myContact.Name" and get a string value. Linq objects are strongly-typed (granted, you can create strongly-typed datasets as well), and once you lean the very simple to use Linq query syntax, you can fetch objects out of the database with very little code, and no t-sql at all. Inserting new objects into the database is equally easy, and I love that columns with default values in the database can be set to automatically-sync their values back to the object on inserts or updates.

It's only when you go to update an existing object that you start finding out why people have so much trouble with Linq: because if you fetched an object with one "DataContext", which you shoud promptly discard (the typical pattern of usage is, "Using myDC as New MyDataContextClassname() ... CRUD... End Using), and then update it, and then create a new instance of your DataContext, trying to save it becomes annoying. By default, for the new DataContext instance to save changes to your item, you need to attach it, with a call to the context's .Attach() method. And there the fun starts!

Trying to attach an object you loaded from a different context will, unless you do some extra work, throw an exception. You'll get an error along the likes of "Attempt to attach an object that is not new, or loaded by a different context." Now, my app uses a lot the "deferred loading" in Linq, which means that a linq object has properties that represent other linq objects, or collections of those objects, which aren't loaded until they're requested by something. So, a contact object like MyContact (an instance of Contact, which is pulled from a Contacts table, for example) might have properties called "Company_Id" (from FK column of the same name), and another property called "Company". The "Company" property is actually of type EntityRef(Of Company). Or, if the relationship from Contacts -> Companies in your database is one-to-many, then MyContact probably has a property called "Companies", which returns (natch!) a collection of the Company objects to which it's related via the PK-FK relationship. The "Companies" property of MyContact is actually of type EntitySet(Of Company) in this case. If you reference MyContact.Company, you will get a Company object if there is one, and so on, so you probably don't even see the EntityRef stuff until later. When you try to update your contact!

Either way, either in using WPF databinding or in code-behind, this design makes it really easy to get to related objects and collections of them. So in WPF, if I have a bunch of elements bound to MyContact, I might have an element whose content property (or whatever property) is set to "{Binding Path=Company.CompanyName}", or even "{Binding Path=Company.Country.CountryName}". During binding, the "Company" property is called automatically, which then loads (if it's not already loaded) the Company object, or for the second example there, it will actually fetch a Country object that's linked to the Company object that is in turn linked to MyContact. All with no code! See ma, no hands!!

The problem is that now, MyContact has its "Company" property set. If you dig a little, you'll see that in the .dbml file (the Linq-to-sql class and mapping file), that the Company property is, as I mentioned, of type EntityRef(Of Company), and that it's just a public property wrapper for the private member _Company. And variables of type EntityRef have a property called .HasLoadedOrAssignedValue, which is boolean, and .Entity, which essentially refers to some object (of type Company, for this example) in the same DataContext. You see, DataContext has one "object" for each table that you've added to your .dbml file, which represents a table of those objects. When my XAML (or code-behind) calls the .Company propert of MyContact, the DataContext that MyContact belongs to duly loads that company object into it's Companies table, and points the private member MyContact._Company.Entity so that it refers to that company.

Now - after binding is done, and I've disposed of my datacontext like a good boy - I still have access to that Company object, via MyContact. I can even create a new object, "MyCompany", and set it equal to MyContact.Company, and then have my way with it. But when I update MyContact, instantiate a new datacontext (again, "Using NewDc as New MyDataContextName().."), and call NewDc.Attach(MyContact), it will fail. MyContact has those EntityRefs that refer to objects (like Company) that are in a datacontext I already disposed of. Even though the object is there, and accessible. I'm going to confess that I'm not sure why, fundamentally, the Linq team couldn't have come up with a built-in solution, something like "MyContact.Detach" (to clear out it's entity-refs and entity-sets). But anyway.

There are multiple ways around the dilemma. First, keep in mind that, in order to perform concurrency checks (that is, to ensure one user isn't overwriting another user's changes), Linq will either check the old values against the current ones, or (if you're using a rowversion/timestamp column), it will just check that. For simplicity, I added rowversion columns to all my tables containing editable records.

Okay, I said there were ways to save your data.

(1) You can pass the .Attach method both the current state of your object, plus it's original state. Of course, that original state is only available from the already-disposed datacontext you used to load it (if it wasn't disposed, you could call, "myDC.Contacts.GetOriginalEntityState(MyContact)" which returns the Contact object with all the properties set to their original values, when you pulled it from the database). You could also just keep a copy of every object that you plan to change, so you have the old copy to pass to .Attach() - I did play around with this, and didn't have much success. Also, it's annoying (to me) to have to manually keep an extra copy of objects I'm about to change, just to update them.

(2) You could turn off DeferredLoading on your datacontext, thus killing one of the great benefits (in my opinion) using linq in the first place. I never really considered mucking with changing the deferred loading on the fly, but that might be viable for some people. You can also set ObjectTrackingEnabled to False, but you can read on Rick Strahl's blog why this is usually pointless (in short, you can't get to linked objects at all).

(3) You could do what I did when prototyping this project, which was to keep a single DataContext in an object, and open, insert and update every object using that datacontext (this turns out to be the opposite of what the MSDN documentation recommends, maybe because it's keeping a database connection open, I'm not sure). Anyway - the datacontext objects are meant to be used then disposed.

(4) You could use some elegant feature or method in Linq that I don't know of yet - and if you do know of it, please leave me a comment below!!!

Or (5), you can write you own .Detach methods, which is what I did.

This might not be an ideal solution for many people (possibly even for me!), but it has the advantage that (a) it works, and (b) I already did it. Linq's classes are all generated as partial classes, so you can extend them willy-nilly in another partial class (normally in the file that's created if you right-click the .dbml file in VS solution explorer, and choose "View Code"). I created a new public method, "Save()", for each of the types of objects that users will edit (i.e., Contact, Company, Appointment, and so on). I also wrote two private methods for each, "Detach()" and "RestoreContext()".

If the property is not an EntitySet, but just an singular EntityRef (so, one company, not a collection), you can just assign null/nothing to property's .Entity propety, like so: Me._Company.Entity = Nothing. Now, in a few places in my app, I might want to get at that object again without having to load it (again) from the database. In fact, if I call my .Save() method, which first calls my .Detach() , then any WPF fields that were bound to properties of the company (like in the binding examples I gave above) will suddenly go blank after the save. You could set the binding mode to one-time, but maybe I want the user to be able to actually see more properties of the company in a pop-up box or something. So my solution was pretty straight-forward: I added private variable declarations in my partial classes. I declare two kinds of things, depending on my object:

Private CompanyEntity As Company
Private HobbyEntitySet As EntitySet(Of Hobby)

Note that I don't really have a list of hobbies, just using it as an example. So anyway, in my Detach() method, I put:
If Me._Company.HasLoadedOrAssignedValue() Then CompanyEntity = Me._Company.Entity

And finally, the public .RestoreContext() method I wrote just reverses the process - it sets Me._Company = CompanyEntity, then sets CompanyEntity back to nothing/null. I don't always need to restore the context - if the user clicked, "Save & Close", for example, I just call the .Save method on my object. If I'm saving some changes, but keeping the object (MyContact) around, I just call .Save, and then .RestoreContext().

If the property IS an EntitySet, I use the same principle.
The auto-generated linq classes do already have (private) methods for these EntitySet(Of T) properties. These methods are in the main .rbml file, and are called "detach_xxxxx" and "attach_xxxxx" which are called whenever you do something like, "MyContact.Companies.Remove(SomeCompany)" or "MyContact.Companies.Add(SomeCompany)" (assuming a one-to-many with Companies, obviously). When you instantiate a new Company - which happens whenever you load one from the DB, or attach it to a context, or declare one (eg., "Dim c As New Contact) - the generated linq code assigns attach_xxxxx and detach_xxxxx as the functions called whenever you add or remove a Company, say, to or from the .Companies list. And so I've seen posts on the web where people wrote .Detach() methods in a partial class (which is where I got the idea!), and they loop through each attached object, calling .Remove on each, like so: "For each c As Company in Me.Companies.... Me.Remove(c)... Next", or the equivalent in C#. Maybe that's what I should have done, but....

Being a bit lazy, I went for the rather quicker and dirtier one-line solution:
Me._Hobbies = New EntitySet(Of Hobby)

You can optionally specify those attach_xxxxx and detach_xxxxx functions, like this:
Me._Hobbies = New EntitySet(Of Hobby)(AddressOf Me.attach_Hobbies, AddressOf Me.detach_Hobbies)

If you know you're about to dispose of the object, or if you know you won't be calling "MyContact.Hobbies.Add(SomeNewHobby)", then you don't really need to worry about specifying the callbacks. I only needed to do that for one object, the rest never have things added/removed like that.

And again, because I sometimes want to keep those collections of objects in the EntitySets around (maybe I have a ComboBox bound to it or something), I use private vars to hold the original values, and assign them back again in .RestoreContext.

So, for the Company and Hobbies example, the total code in the partial "Contact" class might look like this:

Private CompanyEntity As Company
Private HobbyEntitySet As EntitySet(Of Hobby)

Private Sub Detach()
If Me._Company.HasLoadedOrAssignedValue() Then CompanyEntity = Me._Company.Entity
Me._Company.Entity = Nothing
HobbyEntitySet = Me._Hobbies
Me._Hobbies = New EntitySet(Of Hobby)
End Sub

Public Sub Save(ByVal User As String)
Using db As New MyDataContext
Me.Detach()
If Me.ContactID = 0 Then
Me.CreatedBy = User
db.Contacts.InsertOnSubmit(Me)
Else
db.Contacts.Attach(Me, True)
Me.recmodifiedBy = User
Me.recmodifiedDate = Date.Now
End If Try
db.SubmitChanges()
Catch e As ChangeConflictException
'handle concurrency conflict here, and use .Refresh and .SubmitChanges() as needed.
End Try
End Using
End Sub

Public Sub RestoreContext()
Me._Hobbies = HobbyEntitySet
Me._Company.Entity = CompanyEntity
HobbyEntitySet = Nothing
CompanyEntity = Nothing
End Sub

For now, this is working for me, although if I run into any wierdness, I'll post about that later. Many thanks to all the great Linq-to-SQL blogs I've read, which led me to ultimately implement this hack-like solution. Like I said - if you know of a more elegent solution, let me know, thanks! Also, apologies for any typos in the code above that I've missed...

So hopefully most of my posts won't be this techie, unless I get a lot of positive feedback (which seems unlikely!!). Do people prefer the pictures of cows maybe?

Sunday, March 22, 2009

Visiting the Chokchai Ranch & Farm

This isn't exactly (or, say, remotely) tech-related unless you count "lack of". I'm sending this from my phone, at the Chokchai Farm, a sizeable dairy and beef cattle farm 90 minuyes outside Bangkok. Watching a sort of mini-rodeo right now, and the photo is Yui milking her first cow.

I'll write a real post - on WPF and linq-to-sql in a day or so, plus some updates on x86 smartphone developments (hint: LG is building one based on "Moorestown").

Until then, enjoy the cow photo!