The desktop GC implementations in .NET are somewhat less deterministic than the implementations on the Xbox, so even if there were any rules of thumb that specified particular numbers of collections per frame (there aren't, the most likely applicable rule is still "a few as is reasonable") they'd be a little harder to hit.
Your best bet is to program normally -- perhaps a bit conservatively with respect to allocations and GC induction -- and don't spend a whole lot of time worrying about it. If you profile frequently you can determine where bottlenecks start to creep in to your game and address them then. There are plenty of excellent profiling tools for .NET applications, including CLR profiler and WinDBG with SOS.dll (both free, the latter is rather difficult to use though) and ANTS Memory Profiler (non-free, but it's awesome and so are the rest of the Red Gate tools).
You're correct that there are methods in SlimDX that "force" allocations and it hasn't really been a huge deal. It's a tradeoff -- even if SlimDX didn't allocate a heap object (DataBox) in that case, it would still need to allocate a stream object anyway, or some of the memory that backed the stream, otherwise the library would have to either provide a much more difficult-to-use interface to the mapped memory or worse, would have to jump through some extra marshalling hoops that would probably more negatively impact performance more frequently.
However, if you do find a scenario where the heap allocations performed by SlimDX are a performance issue, please file a bug. The developers (I don't work on it any more) would be happy to address it, I'm sure.
One thing that has me stumped is object promotions. Gen 0 GCs will
supposedly finish within a millisecond or two, but if I'm
understanding correctly, it's the gen 1 and 2 promotions that start to
hurt. I'm not too sure how I can predict/prevent these.
The higher the generation, the more expensive it is. You don't want to predict or avoid the actual collections -- it's usually impractical to try. What you want to do is avoid the scenarios that create undue pressure on the collector and allow the heuristics used by the implementation to do their thing. This means don't try to outsmart the collector by forcing a
GC.Collect() now and then, et cetera. Microsoft has a lot of documentation about the collector and its behavior, this page is a good start. Rico Mariani also writes about GC issues frequently, for example, this is pretty interesting.