Выполните хранимую процедуру SQL перед каждым запросом, сгенерированным EntityFramework - PullRequest
3 голосов
/ 14 октября 2010

Мне нужно выполнять хранимую процедуру SQL каждый раз, прежде чем я сделаю запрос к моему ObjectContext. Чего я хочу добиться, так это установить CONTEXT_INFO в значение, которое позже будет использоваться с большинством моих запросов.

Кто-нибудь делал это? Это возможно?

[EDIT]

В настоящее время я достигаю этого, открывая соединение и выполняя хранимую процедуру в моем конструкторе ObjectContext следующим образом:

public partial class MyEntitiesContext
{       
    public MyEntitiesContext(int contextInfo) : this()
    {
        if (Connection.State != ConnectionState.Open)
        {
            Connection.Open(); // open connection if not already open
        }

        var connection = ((EntityConnection)Connection).StoreConnection;

        using (var cmd = connection.CreateCommand())
        {
            // run stored procedure to set ContextInfo to contextInfo
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "[dbo].[SetContextInfo]";
            cmd.Parameters.Add(new SqlParameter("@ci", _contextInfo));
            cmd.ExecuteNonQuery();
        }
        // leave the connection open to reuse later
    }
}

Тогда в моем интеграционном тесте:

[TestMethod]
public void TestMethod1()
{
    using (var ctx = new MyEntitiesContext(1))
    {               
        Assert.AreEqual(2, ctx.Roles.ToList().Count);
        Assert.AreEqual(2, ctx.Users.ToList().Count);
    }
}

Но для этого требуется, чтобы я оставил соединение открытым - это подвержено ошибкам, поскольку мне всегда понадобится CONTEXT_INFO, и другой разработчик может легко это сделать:

[TestMethod]
public void TestMethod2()
{
    using (var ctx = new MyEntitiesContext(1))
    {               
        // do something here
        // ... more here :)
        ctx.Connection.Close(); // then out of the blue comes Close();
        // do something here
        Assert.AreEqual(2, ctx.Roles.ToList().Count);
        Assert.AreEqual(2, ctx.Users.ToList().Count); // this fails since the where
        // clause will be:
        // WHERE ColumnX = CAST(CAST(CONTEXT_INFO() AS BINARY(4)) AS INT)
        // and CONTEXT_INFO is empty - there are no users with ColumnX set to 0
        // while there are 2 users with it set to 1 so this test should pass
    }
}

Вышесказанное означает, что я могу написать код, как в моем тесте, и все будет зеленым (ДАЙ!), Но тогда мой коллега использует код из TestMethod2 где-то в своей бизнес-логике, и все это вышло - и никто не знает, где и почему, поскольку все тесты зеленого цвета: /

[EDIT2]

Этот пост в блоге определенно не отвечает на мой вопрос, но фактически решает мою проблему. Возможно, переход на NHibernate лучше подойдет для моих целей:)

Ответы [ 2 ]

1 голос
/ 14 октября 2010

Мы использовали этот шаблон.

Но мы сделали так, чтобы хранимая процедура была первой операцией внутри каждого контекста БД.

0 голосов
/ 15 декабря 2011

Наконец я нашел ответ.Я могу обернуть соединение с помощью набора инструментов EFProvider из EFProviderWrappers .Для этого мне в основном нужно извлечь из EFProviderWrapperConnection и переопределить метод DbConnection.Open().Я уже пробовал это с провайдером трассировки, и он работает нормально.Как только я протестирую это с моим решением, я добавлю больше информации.

...