Monthly Archives: October 2013

How EF6 Enables Mocking DbSets more easily

There’s an interesting change in EF6 that simplifies unit testing when EF is in the way and you don’t want to engage it at all.

EF6 DbSet gained new features. The team had to decide if they would make a breaking change to the existing IDbSet interface or leave that be and just change DbSet. They chose

the latter route. In doing so, they also ensured that we could use the DbSet directly for testing by adding a new constructor.

Here’ you can see the different constructors and how they affect our ability to test.

EF5 DbSet Constructor

The DbSet constructor is tied to a DbContext by way of the InternalQuery that is used internally in the constructor.

internal DbSet(InternalSet<TEntity> internalSet)
   : base((IInternalQuery<TEntity>) internalSet)
 {
   this._internalSet = internalSet;
 }

In  EF5, we also have IDbSet (DbSet derives from this) (and IObjectSet which was introduced in EF4) . These interfaces contain the set operations (Add, Update, Remove and some additional methods through other interfaces) and can be implemented without forcing any ties to EF’s DbContext.

That’s what we’ve used in the past to create fake DbSets for testing scenarios.

EF6 DbSet Constructors

The internal constructor is still there.

    internal DbSet(InternalSet<TEntity> internalSet)
      : base((IInternalQuery<TEntity>) internalSet)
    {
      this._internalSet = internalSet;
    }

But now there is another constructor. It’s protected and only uses an set interface, but not the query interface. This allows mocking frameworks to get access to DbSet and at the same time, benefit from some of the methods added to DbSet for EF6.

 

  /// <summary>
  /// Creates an instance of a <see cref="T:System.Data.Entity.DbSet`1"/> when called from the constructor of a derived
  ///             type that will be used as a test double for DbSets. Methods and properties that will be used by the
  ///             test double must be implemented by the test double except AsNoTracking, AsStreaming, an Include where
  ///             the default implementation is a no-op.
  /// 
  /// </summary>
  protected DbSet()
    : this((InternalSet<TEntity>) null)
  {
  }

Even if you wanted to create your own fakes (or test doubles) in EF6, you can do that with DbSet now, not IDbSet. IDbSet is still there for backwards compatibility.

There are two detailed documents on MSDN for using EF6 to create Test Doubles and to use with Mocking Frameworks.

You also might find the meeting notes about this change interesting. I sure do! šŸ™‚

I am curious to revisit my work with Telerik’s JustMock. I built some tests with EF5 and JustMock in my Automated Testing for Fraidy Cats course on Pluralsight. When using the paid version, everything just works. But when using JustMock Lite, the free version, it was not able to grok DbSets and you still needed to implement your own fake. I’ll be checking to see if the new DbSet implementation allows the free version of JustMock to mock DbSets on it’s own now.

//update about 20 minutes after initial post. The limitation of JustMock Lite is that it doesn’t support ReturnsCollection which is what you want to emulate the return of a DbSet. So if you’re not willing to pay for your tools, you can use the free version (which has a ton of features) and do a little extra work (create your own test double for DbSet which you can see how to do in MSDN doc I linked to above.

Testing Out the Connection Resiliency Feature into EF6

A few days ago I wrote a blog post about gaining a better understanding of the new connection resiliency feature of EF6. The feature is implemented using an implementation of a new class, IDbExecutionStrategy.

The SQl Server provider thatā€™s bundled with EF6 has a strategy aimed at Windows Azure SQL Database (aka SQL Azure) that is designed to retry a command if a transient connection error is thrown. My blog post listed the transient error messages.

I wanted to see this in action but itā€™s not simple to make a transient error occur. There was a blog post with sample code for creating a deadlock, but then Glenn Condron on the EF team suggested just throwing the error by leveraging the new EF6 ability to intercept commands & queries headed to the database. It can also intercept data coming back.

A few people have asked how I did this, so Iā€™ll share my setup here.

I played with that a bit and realized that the SqlAzureExecutionStrategy required more than just the correct error code to trigger the retries. It needs a SQLException to throw that error. And a little more banging led me to realize that you canā€™t just instantiate a SqlException, it has to be done via reflection.

But I donā€™t give up easily. I found some helpful examples for doing this though it still wasnā€™t simple. Maybe things have changed, but I finally tweaked teh sample code enough to get what I needed.

Still, I was unsuccessful because EF was first doing itā€™s initialization tasks and the SqlAzureExecutionStrategy was not responding to errors thrown by those commands. I had to filter those commands out. Then finally, it worked!

There may be an easier way. I know Glenn does this differently. What I have worked out is witnessing the retries but since thatā€™s all I watned to see, Iā€™m not worried about having one of those retries be successful. I know that in the real world, as itā€™s retrying and the transient connection kicks back in, one of those retries will get through.

So to test out the feature you need four puzzle pieces.

1) Intercept the (non initialization/migration) command

2) Use DbConfiguration to make sure the interception is happening

3) Use DbConfiguration to set up the SqlAzureExecutionStrategy

4) Run an integration test that will attempt one or more queries on the database via EF.

Step 1) Intercept the command and throw the correct error

For this I created a new class, TransientFailureCausingCommandInterceptor, that inherits from IDbCommandInterceptor. There are a number of methods to override. The only one Iā€™m interested in is ReaderExecutingā€¦i.e. a read command is about to execute.

 public class TransientFailureCausingCommandInterceptor : IDbCommandInterceptor
 {
    public void ReaderExecuting(
      DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
    }
    etcā€¦

In the command , I filter out commands that are for the database initialization and migration work, in case they are executing.

For any other commands, I write out some info to Debug so I know that a query is about to execute, then I use my helper class to create a fake SQL Exception that throws one of the transient error codes that SqlAzureExecutionStrategy looks for: 10053.

  public void ReaderExecuting(
      DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
      if (!(command.CommandText.Contains("serverproperty") 
        || command.CommandText.Contains("_MigrationHistory")))
      {
        Debug.WriteLine("throwing fake exception from interceptor");
        throw SqlExceptionFaker.Error10053;

      }
    }

The SqlExceptionFaker is the magic for throwing a SqlException. It is a twist onĀ  this example I found from Microsoft MVP, Chris Pietschmann. I found some other ways of doing this but , in my opinion, Chrisā€™ was the best of the solutions that I found.

using System.Collections;
using System.Data.SqlClient;
using System.Runtime.Serialization;

namespace SqlExceptions
{
  public static class SqlExceptionFaker
  {
    private static SqlException _error10053;

    public static SqlException Error10053
    {
      get
      {
        if (_error10053 == null)
        {
          _error10053 = Generate(SqlExceptionNumber.TransportLevelReceiving);
        }
        return _error10053;
      }

    }
    public enum SqlExceptionNumber : int
    {
      TimeoutExpired = -2,
      EncryptionNotSupported = 20, 
      LoginError = 64,
      ConnectionInitialization = 233,
      TransportLevelReceiving = 10053,
      TransportLevelSending = 10054, 
      EstablishingConnection = 10060,
      ProcessingRequest = 40143, 
      ServiceBusy = 40501, 
      DatabaseOrServerNotAvailable = 40613
    }

    public static SqlException Generate(SqlExceptionNumber errorNumber)
    {
      return SqlExceptionFaker.Generate((int) errorNumber);
    }

    public static SqlException Generate(int errorNumber)
    {
      var ex = (SqlException) FormatterServices.GetUninitializedObject(typeof (SqlException));

      var errors = GenerateSqlErrorCollection(errorNumber);
      SetPrivateFieldValue(ex, "_errors", errors);
      return ex;
    }

    private static SqlErrorCollection GenerateSqlErrorCollection(int errorNumber)
    {
      var t = typeof (SqlErrorCollection);
      var col = (SqlErrorCollection) FormatterServices.GetUninitializedObject(t);
      SetPrivateFieldValue(col, "errors", new ArrayList());
      var sqlError = GenerateSqlError(errorNumber);
      var method = t.GetMethod(
        "Add",
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance );
      method.Invoke(col, new object[] {sqlError});
      return col;
    }

    private static SqlError GenerateSqlError(int errorNumber)
    {
      var sqlError = (SqlError) FormatterServices.GetUninitializedObject(typeof (SqlError));

      SetPrivateFieldValue(sqlError, "number", errorNumber);
      SetPrivateFieldValue(sqlError, "message", errorNumber.ToString());
      SetPrivateFieldValue(sqlError, "procedure", string.Empty);
      SetPrivateFieldValue(sqlError, "server", string.Empty);
      SetPrivateFieldValue(sqlError, "source", string.Empty);
      SetPrivateFieldValue(sqlError, "win32ErrorCode", errorNumber);

      return sqlError;
    }

    private static void SetPrivateFieldValue(object obj, string field, object val)
    {
      var member = obj.GetType().GetField(
        field,
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
        );
      member.SetValue(obj, val);
    }
  }
}

Phew!

Step 2) Force the context to use this interceptor

This happens in the lovely new DbConfiguration class. Read more about it here.

public class CustomDbConfiguration : DbConfiguration
{
  public CustomDbConfiguration()
  {
   AddInterceptor(new CasinoModel.TransientFailureCausingCommandInterceptor());
   }
}

Step 3) Make sure your DbConfiguraiton class is wired up in app/web.config in the EntityConnection section:

 <entityFramework codeConfigurationType="DataLayer.DbConfigurations.CustomDbConfiguration,CasinoModel">
  . . .
 </entityFramework>

 

Step 4) Test

This is a test that works with my model. Notice that my test specifies a connection string. That ensures that my context is using the SQL Azure connection I set up in my config file.

   [TestMethod, TestCategory("Connection Resiliency")]
    public void CanHitSqlAzureDbWithTransientFailure()
    {
      int slotcount = 0;
      using (var context = new CasinoSlotsModel(connectionStringName: "CasinoHotelsAzure"))
      {
        foreach (var casino in context.Casinos)
        {
          context.Entry(casino).Collection(c => c.SlotMachines).Load();
          slotcount += casino.SlotMachines.Count;
        }
      }
      Assert.AreNotEqual(0, slotcount);
    }

The test fails because an exception was thrown ā€“ the SqlException that I faked. Thatā€™s because an error is getting thrown. When I check the output

The SqlException caused a series of exceptions in response. Notice the nice message from EntityException: ā€œconsider using a SqlAzureExecutionStrategyā€.

Result Message:
Test method AutomatedTests.UnitTest1.CanHitSqlAzureDbWithTransientFailure threw exception:

System.Data.DataException: An exception occurred while initializing the database. See the InnerException for details. —> System.Data.Entity.Core.EntityException: An exception has been raised that is likely due to a transient failure. If you are connecting to a SQL Azure database consider using SqlAzureExecutionStrategy. —>

System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. —>

System.Data.SqlClient.SqlException: Exception of type ‘System.Data.SqlClient.SqlException’ was thrown.

Looking at the failed testā€™s OUTPUT I see the text spit out by the ReaderExecuting method:

image

The method was only hit once, so I see my message only once.

Step 5) Add in the SqlAzureConnectionStretegy to the DbConfiguration file:

 public CustomDbConfiguration()
  {

    AddInterceptor(new CasinoModel.TransientFailureCausingCommandInterceptor());
    SetExecutionStrategy
      (SqlProviderServices.ProviderInvariantName, () => new SqlAzureExecutionStrategy());
   }

Using the default settings of SqlAzureExecutionStrategy will cause 5 retries.

Step 6) Run the test again:

The test hangs for a lot longer than fails. Why longer? The retries! I get 6 messages. The first is the initial problem and the other 5 are for each of the 5 retries.

image

Why does it still fail? Because my setup doesnā€™t ā€œturn offā€ the error. Thatā€™s fine. I just want to see that it does actually retry.

The exception is different this time. RetryLimitExceededException, max retries (5) , etcā€¦

Result Message:
Test method AutomatedTests.UnitTest1.CanHitSqlAzureDbWithTransientFailure threw exception:

System.Data.DataException: An exception occurred while initializing the database. See the InnerException for details. —> System.Data.Entity.Infrastructure.RetryLimitExceededException: Maximum number of retries (5) exceeded while executing database operations with ‘SqlAzureExecutionStrategy’. See inner exception for the most recent failure. —>

System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. —>

System.Data.SqlClient.SqlException: Exception of type ‘System.Data.SqlClient.SqlException’ was thrown.

Step 7) Modify the connection retries

Next Iā€™ll change the default of the SqlAzureExecutionStrategy to retry only 3 times.

(SqlProviderServices.ProviderInvariantName, () => new SqlAzureExecutionStrategy(3,new TimeSpan(15)));

Look at the output after I run the test again. Only 3 retries then it gives up.

image
So thatā€™s it. Iā€™m content to see this feature in action.

I was also happy to see a comment in the previous blog post from a developer who has seen the benefits of this feature already in their production environment.

EF6 Connection Resiliency for SQL Azure* – When does it actually do it’s thing?

*Windows Azure SQL Database makes the blog post title just too darned long!

Followup post: Testing outĀ EF6 Connection Resiliency

Iā€™ve been messing around with the DbExecutionStrategy types in EF6 and trying to force the strategy to kick in.

I spent a horrid amount of time going down the wrong path so thought I would elaborate on the one Iā€™ve been banging on: SqlAzureExecutionStrategy.

I thought that by disconnecting my network connection at the right moment I would be able to see this work. But it turned out that my results were no different in EF5 or with EF6 using itā€™s DefaulSqlExecutionStrategy (which does not retry).

I finally looked yet again at the description and at some older articles on connection retries for SQL Azure and finally honed in on a critical phrase:

transient failure

A transient failure is one that will most likely correct itself pretty quickly.

Looking at the code for the SqlAzureExecutionStrategy,Ā  you can see the following comment:

/// This execution strategy will retry the operation on <see cref="T:System.TimeoutException"/> 
/// and <see cref="T:System.Data.SqlClient.SqlException"/>
/// if the <see cref="P:System.Data.SqlClient.SqlException.Errors"/> contains any of the following error numbers:
/// 40613, 40501, 40197, 10929, 10928, 10060, 10054, 10053, 233, 64 and 20

Focusing on these errors led me to a number of articles aimed at dealing with this same list of transient failure.

Here is a code sample from the Windows Server AppFabric Customer Advisory Team that contains brief descriptions of the errors:

// SQL Error Code: 40197
// The service has encountered an error processing your request. Please try again.
case 40197:
// SQL Error Code: 40501
// The service is currently busy. Retry the request after 10 seconds.
case 40501:
// SQL Error Code: 10053
// A transport-level error has occurred when receiving results from the server.
// An established connection was aborted by the software in your host machine.
case 10053:
// SQL Error Code: 10054
// A transport-level error has occurred when sending the request to the server.
// (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
case 10054:
// SQL Error Code: 10060
// A network-related or instance-specific error occurred while establishing a connection to SQL Server.
// The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server
// is configured to allow remote connections. (provider: TCP Provider, error: 0 - A connection attempt failed
// because the connected party did not properly respond after a period of time, or established connection failed
// because connected host has failed to respond.)"}
case 10060:
// SQL Error Code: 40613
// Database XXXX on server YYYY is not currently available. Please retry the connection later. If the problem persists, contact customer
// support, and provide them the session tracing ID of ZZZZZ.
case 40613:
// SQL Error Code: 40143
// The service has encountered an error processing your request. Please try again.
case 40143:
// SQL Error Code: 233
// The client was unable to establish a connection because of an error during connection initialization process before login.
// Possible causes include the following: the client tried to connect to an unsupported version of SQL Server; the server was too busy
// to accept new connections; or there was a resource limitation (insufficient memory or maximum allowed connections) on the server.
// (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
case 233:
// SQL Error Code: 64
// A connection was successfully established with the server, but then an error occurred during the login process.
// (provider: TCP Provider, error: 0 - The specified network name is no longer available.)
case 64:
// DBNETLIB Error Code: 20
// The instance of SQL Server you attempted to connect to does not support encryption.
case (int)ProcessNetLibErrorCode.EncryptionNotSupported:
  return true;

A TechNet wiki article on handling transient failures from Windows Azure SQL Database, warns:

One thing thatā€™s tricky about retry logic is actually inducing a transient error for testing.

Oh, now they tell me! (I am a pitbull and tried so many things already).

Their solution is to intentionally cause a deadlock.

So the SqlAzureExecutionStrategy builds in the same retry logic that until now weā€™ve had to hand code (ala the example in the TechNet article or the Customer Advisory Team code sample.

I have no question that it will work. I just really like to demonstrate before and after when I can rather than just regurgitate what Iā€™ve read somewhere. šŸ™‚

Followup post:Ā Testing outĀ EF6 Connection Resiliency

The somewhat super secret MSDN docs on EF6

Along with all of the great info on entityframework.codeplex.com, the MSDN Library has a bunch of documents targeting EF6, currently listed as ā€œFuture Versionā€. There is a ā€œFuture Version of EFā€ page but it doesnā€™t have links to these articles. And Iā€™ve found some of these to be more current than their related specs on Codeplex.

Iā€™ve only ever found them accidentally via GoogleBing or when bugging someone on the EF team and they send me a link. Since I havenā€™t found a single location with these links, I am really just selfishly creating this list for myself.

Keep in mind that I may have missed some!

Coding for Domain-Driven Design: Tips for Data-Focused Devs

In honor of the 10th Anniversay of Eric Evanā€™s book: Domain Driven Design, Tackling Complexity in the Heart of Software (Addison-Wesley Professional, 2003), Iā€™ve written a 3-part series for my MSDN Data Points column.

August 2013: Data Points: Coding for Domain-Driven Design: Tips for Data-Focused Devs

Domain Driven Design can help handle complex behaviors when building software. But for data-driven devs, the change in perspective isnā€™t always easy. Julie Lerman shares some pointers that helped her get comfortable with DDD.

September 2013:Data Points: Coding for Domain-Driven Design: Tips for Data-Focused Devs, Part 2

In the second column in her series on Domain Driven Design, Julie Lerman shares more tips for data-first developers who are interested in benefiting from some of the coding patterns of DDD.

October 2013: Data Points: Coding for Domain-Driven Design: Tips for Data-Focused Devs, Part 3

Julie Lerman explores two important technical patterns of Domain Driven Design (DDD) coding–unidirectional relationships and the importance of balancing tasks between an aggregate root and a repository–and how they apply to the Object Relational Mapper (ORM), Entity Framework.

My Long-Running, Not-Yet-Complete, Investigation into a New Haswell Ultrabook

(I’m updating this post frequently as I learn more about these machines or about ones I haven’t looked at well enough yet)

Dec 18 update:

The search is over! Iā€™m in Love!

Well, the Samsung Ativ Book 9 PlusĀ  (8GB RAM, 256GB SSD) arrived late one night last week. The poor Fedex driver showed up at my house at 9pm and still had 15 deliveries to go after mine. I gave him a piece of home-made apple pie for the rest of his journey. Iā€™ve now had the Samsung for 5 days and yesterday I cancelled the not-yet-shipped-after 4 weeks Dell XPS13. I was already in love with the Samsung so there seems to be no point in doing a comparison.

Itā€™s light (3 pounds), quiet (unless Iā€™m stressing it out), much faster than my Thinkpad (I did some geekbench comparisons) and I just love looking at the battery status and seeing ā€œ5 hours leftā€ ā€œ7 hours leftā€. I love the keyboard and after struggling with the thinkpadā€™s eraser mouse and touchpad for so many years, I took to the Samsungā€™s touchpad ā€œlike a duck to waterā€. I had to do a bit of finagling to get my RDP setup to handle its super duper high res but am now using it as my full time machine with the ehinkpad nearby in case I forgot to install or copy anything.

I will definitely write a blog post at some point.

Amazon now has these available now on a pretty steady basis.

Dec 4 update:

Dell started selling the XPS13 a few days after my last update so I ordered that although it wouldnā€™t be shipping for over 4 weeks from when I ordered! Then Samsungā€™s shipping time went down to 1-3 days so I called to order one on Nov 20th. But I was told that the pre-orders were going out and they wouldnā€™t be able to ship one to me until Dec 13. I went ahead and placed the order. Was frustrated to see them shipping on Amazon with no wait about a week later but such is life. But I was excited a few days later to get an email that it shipped. The box arrived today. It was suspiciously lightā€¦much less than 3 pounds. All they had shipped was the free laptop sleeve that is part of their p.r. I have no idea when Iā€™ll get either laptop and itā€™s driving me batty (blame A.D.D.). When I ordered the Dell, they had a promo for free shipping, free returns and no restocking. This means I get to try it out and if itā€™s not the one, it wonā€™t have cost me anything (money, that is). Samsung was close with free shipping and no re-stocking fee. It is the only way I can get a hands-on look at these since they are definitely not available in our local Best Buy or Staples. And they wonā€™t be for a while. We are a minor market. I couldnā€™t even find the 4GB/128SSD version of the Ativ at our BestBuy. So the wait continues. Iā€™m guessing the Samsung will be the winner. Getting it to me weeks before the Dell would have helped dramatically because I would have grown fond of it by then. In the meantime, I have some friends who grabbed the Ativ on Amazon and are loving it. Today, it looks like the window of Amazon having those on hand is gone. Better wait in line behind me! šŸ™‚

November 16 update:

Samsung ATIV Pro book 9 is announced but not on amazon anymore and not shipping from Samsung for at least a month. Dell XPS 13 is now orderable from their website but not shipping for another month. I have reconsidered MacBook Air but I really really really want touch! I have looked more closely at the Yoga Pro 2 but am reading enough negative stuff about it that itā€™s still a no (and Iā€™m a long time thinkpad tablet /laptop user). I have reconsidered the Acer S7 but still want FKeys (even though other dev friends are okay with it). I have checked back with Toshiba Kira but they seem to be clueless about the reported fan noise complaints. I got hands on with the Surface Pro 2 but decided that I canā€™t use Visual Studio on that tiny screen when Iā€™m presenting at conferences etc. I do want to do this before the end of the year (think: taxes). I thought I would pre-order the XPS13 and just return it if I donā€™t like it (current promo says no restocking fee) but the chat support was unable to 100% confirm key info about order/invoice/shipping dates that would affect this promo and I remembered that I donā€™t want to depend on Dell support anyway). Iā€™ve re-checked other options (e.g. Asus, Sony) and still donā€™t want them. Iā€™ve learned that there are issues with Windows 8 and the new fancy hi res screens but expect them to get resolved. I have had a thousand repeated recommendations on twitter from kind people who donā€™t realize Iā€™ve spent about 40 hours obsessing over this already and have considered everything they are suggesting already. So Iā€™m going to try to set it aside and wait a little longer. Todayā€™s thought is that the Samsung will win. But Iā€™m fickle and a crazy Libra so weā€™ll just have to seeā€¦)

Anyone who follows me on twitter may be familiar with my ridiculous, drawn out, indecisive process when i have to buy new gear. Itā€™s time for a new laptop. Iā€™ve been thinking about it for months. Because of this I have the added problem of forgetting what I liked or didnā€™t like about certain machines.

Hereā€™s what I know I want:

  • Intel Haswell chip for long battery..most likely i7, but i5 could suffice
  • Light! I am hoping for under 3 pounds.
  • Min 8GB RAM
  • Min 256 GB Drive
  • Quiet because even though I record my Pluralsight & other videos on my desktop, I need to have my laptop running at the same time.
  • In my hands and ready to head off to conferences with me at the end of this month!

I do production code and video recording and run VMs on my desktop. Everything else on my laptop including pick it up and go when I travel. So I donā€™t need quad core heavy duty on the laptop.

What Iā€™ve looked at seriously:

 

Acer Aspire S7-392-9890 13.3-Inch Touchscreen Ultrabook

This is under 3 pounds. It claims a 7 hr battery life. According to a number of friends, the previous version (Ivy Bridge) has a lot of fan noise. Perhaps the Haswell version is quieter, but there is a possible showstopper for me: no F keys. The number keys serve as number and FKeys meaning that you have to do learn new key combos to Run or Debug an app in Visual Studio etc etc. Or to use Zoomit. I just donā€™t know if I want to make that commitment.

Showstopper: No F Keys

 

Toshiba KIRAbook 13 i7 Touchscreen Laptop

Cori Drew loves hers even though she threw it across the room (accidentally as she was wandering around looking for wifi because hers has a faulty wifi card or something like that). But, itā€™s got amazing resolution ā€“ to compete with Macā€™s Retina display, is very light, very high end and very well built. Plus she says the customer service is fantastic. Butā€¦.here we go againā€¦.the fan is crazy noisy. Crazy noisy like in a room full of developers, all eyes will suddently be on her becaus eof the fan. Many reviews complain about this as well. This just wonā€™t work for recording.

Showstopper: Head turning fan noise

 

Samsung ATIV Book 9 NP900X3E-K01US 13.3-Inch Full HD Premium Ultrabook

Everything Iā€™m looking for and 2.6 pounds, but this excellent Engadget review mentions the fan noise:

The ATIV Book 9 Plus pipes up quickly — heck, it sometimes makes noise when it’s sitting idle. But that noise never rises above a quiet sigh. In fact, we didn’t even notice it until we paused Pandora and started to work without any background noise.

ā€œQuiet sighā€ā€¦.I have worked hard to reduce the noise in my office for recording. I donā€™t know how loud a quiet sigh is but since itā€™s loud enough to write a whole paragraph about, Iā€™m guessing louder than I want.

Showstopper: Fan noise?Ā  SCREECH: wait, forget the fan noise, only 4GB RAM Max??Ā  128GB drive? Not upgradable? Pfft!

 

The 8GB/256SSD is now listed on Samsungā€™s site:http://www.samsung.com/us/computer/pcs/NP940X3G-K04USĀ  You can pre-order but it says ā€œships in 3-4 weeksā€ (Iā€™m writing this on Nov 16)

Amazon has a place h older page but itā€™s not yet orderable: http://www.amazon.com/Samsung-NP940X3G-K04US-13-3-Inch-Laptop-Mineral/dp/B00F6EOB8C

Apple MacBook Air MD760LL/A 13.3-Inch Laptop (NEWEST VERSION)

Yes, a macbook! Many friends use MacBook Pro with Windows & Visual Studio development. But the 2013 MbA has a haswell chip and can come configured with 8GB RAM and up to a 512GB drive. It doesnā€™t have the Retina display but that was one of those features I didnā€™t know I needed. Itā€™s under 3 pounds. I could get a Pro with Retina display for another 1/2 lb but a quad core mac book pro is a 4.5 lb 15ā€ computer. Thatā€™s about what I have now (though obviously much nicer, longer battery life and more powerful). But size matters, too! šŸ™‚

Cons are no touch screen. I use my touch screen a lot on my laptop. I would miss it madly.

Iā€™m going to be near the local Apple reseller today and will try them out. Iā€™m hoping theyā€™ll have Airs and Pros with Win8 installed on them.

Dell XPS 12 Convertible Ultrabook

Iā€™d ignored this because itā€™s weird looking but thatā€™s silly.Very high end, great graphics, 8+ hrs of battery.

Itā€™s also 3.35 pounds, which I know is negligible and still a lot less than the 4.75 lbs of my thinkpad when I have the extra battery in it (which is always when Iā€™m travelling)

Sony VAIO Pro SVP13215PXB 13.3-Inch Core i7 Touchscreen Ultrabook

Forgot that I had looked into this , perfect in every way but:

showstopper: fan noise (http://forum.notebookreview.com/sony-owners-lounge-forum/720737-official-vaio-pro-13-owners-lounge-svp13-2013-a-88.html) & http://forum.notebookreview.com/sony/726097-sony-vaio-pro-13-fan-noise-return.html

šŸ™

ThinkPad X1 Carbon Touch

(I can hear Scott Hanselman now, ā€œ’all that research and you missed my blog post review?ā€.

ā€œstarting at 3.4 lbsā€ so I wasnā€™t really looking at it. Plus in the comments of Scottā€™s post, another owner says ā€œOne other thing that really bothers me is that the fan is running at a quite noisy level ā€“ constantlyā€. šŸ™

Currently they are built with 3rd generation chips. Looks like Haswell machines won’t be out until January 2014.

Am I asking too much?

Am I being too much of a stickler about the noise? Head-turning loud (Kirabook) is really impossible for me for recording. Maybe the Samsung Kivaā€™s ā€œquite sighā€ is not going to be a bad thing after all. I just need some more feedback on that. I just donā€™t want to buy something, make the effort of setting it up and then decided I donā€™t like it.

Coming soon but not soon enough for my pre-conference hopeful deadline:

Not to be overlooked is the new Surface 2 Pro. It will also be light, fast, long battery life, touch screen etc. But I really wanted to have something before I head off to conferences at the end of this month so thatā€™s not doable unless I keep waiting and lug my thinkpad around for more trips. And I want to hear what my friends say about it before I buy one.

Dell: Precision M3800 workstation: 4.5 lbs ā€¦NOPE

Dell XPS 13 UltrabookĀ  about 3 lbs, but still ā€œcoming soonā€¦ā€

Availability and PricingĀ  (source Oct 2 press release)
The Dell Venue 7, Venue 8, Venue 8 Pro, and new XPS 15 will be available from October 18 on www.dell.com in the United States and select countries around the world. The Venue 11 Pro, XPS 11 and the updated XPS 13 with touch will be available in November. Starting prices are as follows:

  • New XPS 15: $1,499.99
  • XPS 11: $999.99
  • New XPS 13: $999.99