views:

22

answers:

2

How do I get the trace string for a query like this:

var product = _context.Products.Where( p => p.Category == "Windows" )
                               .SingleOrDefault();

// I can't do this since product is not an ObjectQuery instance
// product.ToTraceString();
+2  A: 

Different answer for different problem.

You can't call ToTraceString() on this:

var product = _context.Products.Where( p => p.Category == "Windows" )
                               .SingleOrDefault();

You can do this:

var q = _context.Products.Where( p => p.Category == "Windows" )
var ts = ((ObjectQuery)q).ToTraceString();
var product = q.SingleOrDefault();

... but it's not 100% accurate. The MSSQL EF provider will use a TOP 2 for Single which this will miss.

You can come close with this:

var q = _context.Products.Where( p => p.Category == "Windows" )
var ts = ((ObjectQuery)q.Take(2)).ToTraceString();
var product = q.SingleOrDefault();

...which should get you the right SQL but requires knowledge of the implementation.

Original question misrepresented the problem. My original answer was:

var ts = (product as ObjectQuery).ToTraceString();
Craig Stuntz
That won't work.
Water Cooler v2
It certainly does, with the code you've shown (although I should have used a `()` cast, but that's off-topic. Perhaps the code in your question is not your real code? Also, I can probably give you better help if you post a comment more precise than "That won't work."
Craig Stuntz
Sorry about the vague comment. I meant to say that the cast will not work. Where, unless you're using the ObjectQuery version of the Where method, which in the above case, I am not, will not work. The IQuerable.Where is what is being used above and that will return an IQueryable<T>, which can't be cast into an ObjectQuery.
Water Cooler v2
You say "it won't work." And yet, I just did it. Have you tried it yourself, or are you guessing?
Craig Stuntz
I'd actually tried it before making the original post. May be I am missing something.
Water Cooler v2
I think so, because, having looked, I see casts to `ObjectQuery` with the `Where(expression)` overload in my production code. E.g., this is production code: `var bcs = ((ObjectQuery<BillingCode>)Context.BillingCodes.Where(bc => ids.Contains(bc.Id))).Include("Payer");`
Craig Stuntz
I think you are right. I missed indicating something very vital in my original post. I am updating it now.
Water Cooler v2
That **completely** changes your question! Sigh....
Craig Stuntz
Thanks. I'd read that in Julia Lerman's book as well but because it wasn't the precise solution, which I think there isn't any in v4 of the Entity Framework, I didn't adopt it. Also, there are other scenarios I think I can't get the trace string for, like objectContext.ExecuteStoreCommand, or for an update operation.
Water Cooler v2
+1  A: 

This is what you need to do:

string trace = ((ObjectQuery)_context.Products
                           .Where(p => p.Category == "Windows")).ToTraceString();

Compiler will not accept a cast from Product EntityObject to ObjectQuery but IQueryable<Product> is castable to ObjectQuery, so basically you just need to get rid of that .SingleOrDefault() method before trying to see the trace string.

Morteza Manavi
@Morteza, he's changed his question now, and this (which is the same, more or less, as my first answer) will not give him the actual SQL used in `SingleOrDefault`. See my updated answer.
Craig Stuntz
@Craig: You are right, but I think this is still good enough, IMHO if he *Really* wants to see the actual submitted SQL, then he should look into *Profiler* instead of mock the SQL with Take() method.
Morteza Manavi
i agree with that.
Craig Stuntz
+1 to your answer for the tip on "TOP 2 on Single method", good to know!
Morteza Manavi