StructureMap DBServiceRegistry и MVC-мини-профилировщик? - PullRequest
10 голосов
/ 24 июня 2011

Если я использую этот код в каждом классе репозитория, я получаю профилирование SQL, но я хочу переместить этот код из каждого класса в класс, где StructureMap обрабатывает БД.

Пример класса репозитория:

public DB CreateNewContext()
    {
        var sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["connection"].ConnectionString);
        var profiledConnection = ProfiledDbConnection.Get(sqlConnection);
        return DataContextUtils.CreateDataContext<DB>(profiledConnection);
    }

    public SqlRecipeRepository(DB dataContext)
    {         
        _db = CreateNewContext();
    }

Теперь я хочу, чтобы переменная dataContext была профилированной версией и была получена из моего класса DBServiceRegistry.

Вот класс DBServiceRegistry:

public class DBServiceRegistry : Registry
{
    public DBServiceRegistry()
    {
        var sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["GetMeCooking.Data.Properties.Settings.server"].ConnectionString);
        var profiledConnection = ProfiledDbConnection.Get(sqlConnection);
        For<DB>().HybridHttpOrThreadLocalScoped().Use(() => DataContextUtils.CreateDataContext<DB>(profiledConnection));

        //Original method just had this:
        //For<DB>().HybridHttpOrThreadLocalScoped().Use(() => new DB());

    }
}

Этот код не вызывает никаких ошибок, но я не получаю профилирование SQL, что я делаю неправильно?

1 Ответ

1 голос
/ 02 июля 2012

Комментарий правильный, создавая соединение sql со строкой For, вы переопределяете команду scope.

Гораздо лучше заключить весь участок в анонимный делегат

using System.Configuration;
using System.Data.SqlClient;
using System.Threading.Tasks;

using StructureMap;
using StructureMap.Configuration.DSL;

using Xunit;

public class DBServiceRegistry : Registry
{
    private string connString = ConfigurationManager.ConnectionStrings["GetMeCooking.Data.Properties.Settings.server"].ConnectionString;

    public DBServiceRegistry()
    {
        For<DB>().HybridHttpOrThreadLocalScoped().Use(
            () =>
                {
                    var sqlConnection = new SqlConnection(connString);
                    var profiledConnection = new StackExchange.Profiling.Data.ProfiledDbConnection(sqlConnection,  MiniProfiler.Current);
                    return DataContextUtils.CreateDataContext<DB>(profiledConnection);
                });
    }
}

Вы можете использовать модульные тесты, чтобы проверить, что область действия правильна (синтаксис теста - xunit.net)

public class DBRegistryTests : IDisposable
{
    private Container container;

    public DBRegistryTests()
    {
        // Arrange (or test setup)
        container = new Container(new DBServiceRegistry());
    }

    [Fact]
    public void ConnectionsAreSameInThread()
    {
        // Create two connections on same thread
        var conn1 = container.GetInstance<DB>();
        var conn2 = container.GetInstance<DB>();

        // Assert should be equal because hybrid thread is scope 
        // and test executes on same thread
        Assert.Equal(conn1, conn2);

        // Other assertions that connection is profiled
    }

    [Fact]
    public void ConnectionAreNotSameInDifferentThreads()
    {
        var conn1 = container.GetInstance<DB>();

        // Request second connection from a different thread 
        // (for < c# 4.0 use Thread instead of task)
        var conn2 = new Task<DB>(() => this.container.GetInstance<DB>());
        conn2.Start();
        conn2.Wait();

        // Assert that request from two different threads 
        // are not the same
        Assert.NotEqual(conn1, conn2.Result);
    }

    public void Dispose()
    {
        // Test teardown
        container.Dispose();
    }
}
...