1

I have a 2 tier web application. DataAccess and WebSite.

So in my dataContext.cs on the DataAccess tier I added the wrapper...

  //The autogenreated context when I made the linq2sql class
  public static MyDataContext DataContext
    {
        get
        {
            //We are in a web app, use a request scope
            if (HttpContext.Current != null)
            {
                if (HttpContext.Current.Items["dc"] == null)
                {
                    MyDataContext dc = new MyDataContext ();
                    HttpContext.Current.Items["dc"] = dc;
                    return dc;
                }
                else
                    return (MyDataContext )HttpContext.Current.Items["dc"];
            }
            else
            {
                if (dataContext == null)
                    dataContext = new MyDataContext ();



                return dataContext;
            }
        }
    }

    //the method I added to the autogenreated contex in 
    //an attempt to wrap the profiler around it
    public static MyDataContext Get()
    {
        var sqlConnection = new MyDataContext().Connection;
        var profiledConnection = new StackExchange.Profiling.Data.ProfiledDbConnection(sqlConnection, MiniProfiler.Current);

        return new MyDataContext(profiledConnection);
    }

So this is what the profileConnection looks like when it gets called but before the return New MyDataContext(porofiledConnection)

enter image description here

and in my business logic also in the DataAccess tier I made sure that the db context is all created with db = MyDataContext.Get() in stead of db = new MyDataContext();

public class MyOrders(){
  private static  MyDataContext db = MyDataContext.Get();

  public static List<model> GetOrderHistory(){
      var = db.MyStoredProcedure(args) //Inspecting here before execution
      //proces result and return list of model
      }

 }

Now, on some pages I used to get SQL lines and I could click on them and inspect them. But after I browsed the site it just shows this - no SQL lines any more? Like this page just randomly shows me SQL duplication- But if I reload it is gone.

enter image description here

And on this page that I never ran with the profiler before that has loading time issues I cannot identify the SQL it used.

enter image description here

Did I miss something? Is the SQL cached? I always want to see the SQL even if Linq2Sql caches it or whatever. What did I do wrong?

Piotr Kula
  • 9,597
  • 8
  • 59
  • 85
  • a: are you sure that it is *doing* data access? And if it is: b : did you get the data-context via the utility method you show at the top of the page? is it possible that there is some other code that is creating data-contexts? – Marc Gravell Feb 07 '13 at 15:37
  • what I mean is: is it possible any code is simply doing its own `new MyDataContext(...)` ? Although I must say: creating a data-context just to get the connection is risky - and not even guaranteed to work: a data-context has odd rules about when it disposes the connection if it thinks it owns it. Personally, I'd be fetching the connection-string myself **outside** of the data-context, and then configuring the two connections (direct and wrapped), and finally create a data-context by passing in the profiled connection – Marc Gravell Feb 07 '13 at 16:00
  • Just a guess, try to create your data context not by using other's context connection: like `var profiledConnection = new ProfiledDbConnection(new SqlConnection(ConnectionString), MiniProfiler.Current);`. Another thing - why do you need a **static** data context in your `MyProducts` class? – Oleks Feb 07 '13 at 16:05
  • There is only one `dbml` that has all SP's and only SP's. We do not actually select data using linq. Does that affect it? I am just interested how long the SP takes to execute cause it is on a remote server. I updated the question a bit with more details – Piotr Kula Feb 07 '13 at 16:17
  • @Alex well I did that. Got conString from web.config and new SqlConnection. First page laod showed me `!` duplciate SQL.. I pressed F5 - No more SQL Times? I know from debug it does still get called twice! I checked the db and it is still using the profiled connection on all refreshes?! PS- All my calsses there are static.. is that bad? – Piotr Kula Feb 07 '13 at 16:25
  • Data context [shouldn't be static](http://stackoverflow.com/q/4081071/102112). Also your static `DataContext` property doesn't use a profiled connection. – Oleks Feb 07 '13 at 16:32
  • OK Well I figured something out. If i stop my dev-env-server and re run the project the very first page shows me 1 box - with the SQL I am looking for! ON the very first refresh it comes up with several boxes and timmings but no more SQL times? I stop devenv. re run the project same thine again... huh? – Piotr Kula Feb 07 '13 at 16:33
  • Oh Krikey! @Alex Ye I took out the static datacontext and create it in each call as a private member... It works every single time now. Blooming Berg! ? Why?! Whats the difference. You wanna post answer? – Piotr Kula Feb 07 '13 at 16:39

1 Answers1

2

You have a static data context in your MyOrders class. DataContext has an internal cache inside to track changes of entities and avoid round trip to database in one business transaction. Keeping it as static, means internal cache will be increasing for the time being and is not released properly. This may be the reason of disappeared queries in profiler. Also you may face a problem when multiple users will access the same context from multiple threads, and probably memory leaks.

A note from MSDN:

In general, a DataContext instance is designed to last for one "unit of work" however your application defines that term. A DataContext is lightweight and is not expensive to create. A typical LINQ to SQL application creates DataContext instances at method scope or as a member of short-lived classes that represent a logical set of related database operations.

one more:

Do not try to reuse instances of DataContext. Each DataContext maintains state (including an identity cache) for one particular edit/query session. To obtain new instances based on the current state of the database, use a new DataContext.

More details you can find in the Rick Strahl's article Linq to SQL DataContext Lifetime Management.

Oleks
  • 31,955
  • 11
  • 77
  • 132
  • 1
    Thank you very much. I did not realise that I made quite a serious issue by making that static. I have moved it to single transactions now and the profiler works great. Thank you for you time +1 +beer – Piotr Kula Feb 07 '13 at 18:49