MiniProfiler, LLBLGen 3.5 and SelfServicing

Posts   
 
    
Posts: 1251
Joined: 10-Mar-2006
# Posted on: 30-Dec-2012 20:46:46   

Is it possible to easily get MiniProfiler working with LLBLGen 3.5 and self servicing?

I have read this, stack overflow, etc... http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=20252&HighLight=1

Seems all these were dealing with older versions of LLBLGen, issues with miniprofiler and such. Is there a resolution yet?

On a side note, I have and use OrmProfiler.com product, but it would be nice to have this information 'on the webpage'.

Thoughts?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 30-Dec-2012 22:18:05   

It should work with LLBLGen v3.5. The only issue I know is for MvcMiniProfiler v1.9+ and the fix is posted in the link you provided (http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=20252&StartAtMessage=0&#114187 ). Also the Miha's article is updated with that fix: http://blog.rthand.com/post/2011/07/24/Integrating-MvcMiniProfiler-and-LLBLGenPro.aspx

I'm using it with no problems with LLBLGen v3.5. If you have problems please post the relevant information: - LLBLGen runtime library version. - MVCMiniProfiler version - Info about the error (exception info, compile error, etc).

(Edit) I see you are using SelfServicing so the given code in the Miha's article won't work with you. Let me try to cook it for you.. I will post again...

David Elizondo | LLBLGen Support Team
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 01-Jan-2013 12:54:26   

Ok, I have it working with LLBLGen v3.5 with SelfServicing and MvcMiniProfiler 2.0.2.0. This is what you have to do:

  1. Create a custom DynamicQueryEngine in your DAL generated project:
using System.Data.Common;
using SD.LLBLGen.Pro.DQE.SqlServer;
using StackExchange.Profiling;
using StackExchange.Profiling.Data;

namespace [YourRootNamespace]
{
    public class DynamicQueryEngineProfiled : DynamicQueryEngine
    {
        protected override DbCommand CreateCommand() 
        { 
            DbCommand cmd = base.CreateCommand(); 
            return new ProfiledDbCommand(cmd, null, MiniProfiler.Current); 
        }
    }
}

  1. Create a partial class file for CommonDaoBase and write this:
using SD.LLBLGen.Pro.ORMSupportClasses;
using StackExchange.Profiling;
using StackExchange.Profiling.Data;

namespace [YourRootNamespace].DaoClasses
{
    public partial class CommonDaoBase
    {
        public override System.Data.Common.DbConnection DetermineConnectionToUse(ITransaction containingTransaction)
        {
            var cnn = base.DetermineConnectionToUse(containingTransaction);
            return new ProfiledDbConnection(cnn, MiniProfiler.Current);
        }
    }
}
  1. Now you have to tell CommonDaoBase to use your custom DQE. This is the easiest way: open CommonDaoBase.cs and change the constructor to this:
public CommonDaoBase(InheritanceHierarchyType typeOfInheritance, string entityName, IEntityFactory entityFactory)
    : base(InheritanceInfoProviderSingleton.GetInstance(), new DynamicQueryEngineProfiled(), typeOfInheritance, entityName, entityFactory)
{
}

That's it, now use MiniProfiler as mentioned in the docs (http://miniprofiler.com). Example:

public ActionResult List()
{
    var profiler = MiniProfiler.Current; 
    using (profiler.Step("Fetching customers..."))
    {
        var customers = new CustomerCollection();
        customers.GetMulti(null);

        ViewData.Model = customers.ToList();
    }

    return View();
}

Make sure to start/stop the profiler, and that the handler is added to your config: global.asax

protected void Application_BeginRequest()
{
    if (Request.IsLocal)
    {
        MiniProfiler.Start();
    }
}

protected void Application_EndRequest()
{
    MiniProfiler.Stop();
}

web.config

<system.webServer>
  <modules runAllManagedModulesForAllRequests="false"/>
  <handlers>
    <add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
  </handlers>  
</system.webServer>

Note that at Step 3 there is a little problem: when you regenerate code that will be overwritten. To overcome that, you could change the template for CommonDaoBase so the custom DQE is emitted always in the constructor. You can write your own version of the template/binding and then move it up in the template bindings precedence at the Generate Code wizard. This is explained in the SDK docs.

Hope helpful wink

David Elizondo | LLBLGen Support Team
Posts: 1251
Joined: 10-Mar-2006
# Posted on: 01-Jan-2013 17:36:31   

Very helpful!!!

Otis, how about a little class change so we can more easily enable this scenario without having the custom template?

Daelmo - thanks again.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 02-Jan-2013 10:12:05   

Not sure, our own profiler does a great job.

If you really want a profiler to be injected, a little custom template will do fine, it's a simple change to a template which is barely changing.

The thing is that we can't provide extension points for every profiler out there. Miniprofiler should just overwrite the dbproviderfactory table, so they wouldn't be intrusive at all.

Perhaps in the future we'll refactor the DQE creation method into a virtual method but when/if, that's not known.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1251
Joined: 10-Mar-2006
# Posted on: 02-Jan-2013 14:51:33   

This was not about your profiler being good or bad, I like it. The issue is there is this 'mini profiler' that is already built that throws basic timing and such on a webpage so you can easily see slowness on a PER PAGE view.

Your profiler works on more of a per application view. So, it is easier to spot slowness with something like mini- profiler...at which time I would probably use your profiler to drill into the actual problem.

I would recommend your profiler to anyone!

Anything that keeps me from modifying the base templates and having to deal with that during upgrade cycle is a bonus to me at the expense of a virtual method, seems an easy win.

Thanks for considering at some point.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 02-Jan-2013 18:35:12   

It's not that easy: The thing that needs changing I guess is whether the DQE is created in the CTor, or it is created through a virtual method which is overridden in the template. That way you can override it in a partial class of the DAO classes. This still sucks though as you need to override the method in all DAO classes (as the DQE instantiation method is in the commondaobase) So that still requires a template you have to provide so you can generate the override into all dao classes. Not a lot gained, IMHO.

It might be better to create commands from a connection, if available (which is usually the case). This simply only requires to override DetermineConnectionToUse in commondaobase, and no own dqe is needed, so no template change is needed either.

We'll see if we can make that change to v4's runtime.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1251
Joined: 10-Mar-2006
# Posted on: 02-Jan-2013 19:49:27   

Thanks for your help.

Without opening a new thread....what would you say if I were to convert to an adapter model instead of self servicing.

1) Could I use an adapter and ss generated DAL at the same time - maybe generating one in a different namespace - so I could convert code over an area at a time?

2) What pitfalls or areas would I need to watch for?

(Loaded question I know, just wondering...)

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 02-Jan-2013 20:16:33   

1) Could I use an adapter and ss generated DAL at the same time - maybe generating one in a different namespace - so I could convert code over an area at a time?

Yes you can

2) What pitfalls or areas would I need to watch for?

Just generate into different namespaces, as you have said, can't think of anything else.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39590
Joined: 17-Aug-2003
# Posted on: 03-Jan-2013 10:54:36   

adapter doesn't have lazy loading. If you have code which relies on that, you need to work around that with prefetch paths.

Frans Bouma | Lead developer LLBLGen Pro