Tuesday, November 18, 2008

Hosting a window from one process inside another

Every time this topic comes up, I seem to have lost my bookmarks on it. So, here's a blog entry so I won't lose them again...

Under Windows it is possible to visually "dock" the main window of one process inside a Window belonging to another process. You get the visual effect of one program, but there are still two completely separate exes involved.

I once used this to "host" an EXE inside Internet Explorer. We wrote a little tiny ActiveX (this was in the dark ages before managed code). All the ActiveX did was start our EXE, and then "dock" the EXE's main window inside the client area of the ActiveX. It looked like our EXE was the ActiveX - but our EXE had no idea that any of this was going on. It just doing its thing, running as an independent process.

The secret is the Windows API function SetParent. You can use it to set a window from process A as the parent of the main window of process B.

I haven't done this for a while. As I recall you need to make another call to make the hosted window look like a borderless child window (SetWindowLong IIRC) and I think I also had to detect resising of the "host" and programatically resize the child.

Here are some links on the subject, following a rather brief Google:

http://geekswithblogs.net/gyoung/archive/2006/04/26/76521.aspx

http://www.codeguru.com/forum/showthread.php?threadid=234862

http://www.codeproject.com/KB/miscctrl/winwordcontrol.aspx

I'm fairly sure I learnt this technique from something on Microsoft's site, in about 2000. But this post says they are no longer recommending it (at least, not for hosting Office apps) so perhaps that explains why I can't find the original MS post.

Monday, November 03, 2008

LINQ to SQL Presentation

Here is a copy of the presentation I have at the 2008 Christchurch Code Camp. (zipped ppt)

One of the key points of the presentation was to cover what LINQ to SQL includes, both out-of-the-box, and with the additions that we have been able to build on top of it at Optimation. I put together the list that follows from two sources: Ayende's list of 25 things your OR Mapper must do; plus other things that we found useful. Ayende's points are in normal font; my additions to his is are shown in italics.

Out of the box, you get:

CRUD and querying
Transactions
(Bi-directional) associations
Lazy loading
Polymorphic queries (single-table inheritance only)
"Dirty Tracking" with ability to return full change set
Loading properties without loading whole object
Identity Map
Concurrency Control
Acceptable debuggability
Safe multi-threading (1 datacontext = 1 user on 1 thread is the general rule of thumb)
Well-defined exception policy
Lifecycle events (create/update etc)
Composite primary keys
Automatic dependency ordering when saving changes
Paging support (via Skip/Take)
Aggregation support (group/max/min etc)
Original value tracking
Property change notifications
Runtime SQL logging
Ability to generate database from object model
Persistence by reachabilty
Enhanced "reflection" via LINQ to SQL MetaModel

With our add-ons to LINQ to SQL you (or at least we ;-) also get

Undo (both to "as fetched" and "current DB state")
Flexible eager load
Unit testability
Test: is this object new?
Check mapping against DB
In-memory savepoints (like DB savepoints, but for in-memory entities which haven't been saved yet)
Proper serialization of entities (none of the usual LINQ to SQL serialization restrictions)
Clone trees of related entities (clone parent with children)
Delete-any-object (even if is a new unsaved one; automatically sever relationships to other objects)
Get data context from object (based on this with only very minor changes)
Get reachable objects (approximates "find me all objects in the datacontext)

You get only limited support for:

Caching at unit-of-work (datacontext) level
Custom field types (limited to built-in types, enums, xml, .Parse()-able strings and binary ISerializable. Here is the valuable and hard-to-find reference page)

You get no support at all for:

Caching at application-wide level (other than that which is done for you by SQL Server itself)
Cache invalidation policies
Update batching
Cascading update/delete in object model (must rely on DB to do this instead, if you want it)




All in all, its a fairly strong list. Stronger, I suspect, than many people expect.

As for the rest of the presentation, some of it will make sense from written slides, and some won't ;-) A couple of notes here might help:
  • The solution to comments on entity properties, and refreshing the designer, can be found here. It looks real good, although I haven't got round to trying it yet myself.

  • Using the "mapping checker" code. These three points will help if you want to use it: LinqUtil.GetModel is our wrapper for MappingSource.GetModel() - see later slides for details; LinqUtil.IsMappedType() is our wrapper for calling IsEntity on a metaType returned from the MetaModel; and Uow.All(type) is our wrapper for DataContext.GetTable(type). Simply copy the code, replacing our wrappers as noted above.


That's all for now. As noted in the presentation, please do comment below or email me.

Sunday, November 02, 2008

Future of LINQ to SQL

Yesterday, I did a presentation on LINQ to SQL.  At about the time I was talking about how great it was, Microsoft was announcing that LINQ to SQL will not be their recommended solution in .NET 4!  They will be recommending LINQ to Entities instead.
Here, in no particular order, are some intial thoughts:
  1. Sorry I wasn't well-informed enough to mention this at the presentation!  It seems like the news hit the net after I left for the Code Camp.  I did hear there'd been speculation from outside Microsoft, but I mistakenly dismissed it as an over-reaction to the recent emphasis on Entity Framework.
  2. The news is not as bad as it sounds.  The best post on the topic seems to be this one: http://damieng.com/blog/2008/10/31/linq-to-sql-next-steps.  Read that post now, if you have not done so already.  Basically, LINQ to SQL will still be available and there will even be improvements and bug fixes.  In particular "we [Microsoft] are going to make sure LINQ to SQL continues to operate as it should. This doesn’t just mean making sure what we had works in .NET 4.0 but also fixing a number of issues that have arisen as people pick it up for more advanced projects and put it into production environments".
  3. To successfully execute this strategy, Microsoft will have to bring the best of LINQ to SQL to LINQ to Entities - in particular, they will have to bring lightness, speed and simplicity to cases where the mapping is simple and relatively direct.  I hope the recent addition of Andrew Peters to the team will help in that regard, due to his experience on Mindscapes' LightSpeed ORM.   
  4. I think it will be very important for LINQ to Entities to expose the equivalent of LINQ's MetaModel - complete with the ability to use it to implement workarounds, as I demonstrated in my presentation.  (We use the MetaAccessors to do all kinds of things). We've been able to use it plug virtually all the "holes" we've found in LINQ to SQL, and a similar capability is a must in LINQ to Entities if it is to become the favoured product.
  5. Microsoft: to make this kind of announcement, about a product that has been out for less than 12 months, is not a good look!  (LINQ to SQL's production release was roughtly 11 months ago).  This is particularly true in the area of data access, where there were already plenty of jokes about a long history of technical changes - ODBC, RDO, DAO, ADO, OLEDB, now ADO.NET.
  6. For projects you start today, with .NET 3.5, I believe the advice I gave in the presentation is still accurate.  For simple mapping consider products like LINQ to SQL and LightSpeed; for complex mapping consider products like LINQ to Entities and nHibernate.   If Microsoft achieves the goals mentioned above, my advice might change for new projects that are started after .NET 4 is released.