Использование блока вокруг ссылки на статический / одноэлементный ресурс - PullRequest
0 голосов
/ 21 мая 2010

Это интересно (для меня в любом случае), и я хотел бы посмотреть, есть ли у кого-нибудь хороший ответ и объяснение этому поведению.

Скажем, у вас есть одноэлементный объект базы данных (или статический объект базы данных), и он хранится в классе Foo.

public class Foo
{
    public static SqlConnection DBConn = new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString);
}

Итак, давайте представим, что вы осведомлены о полезности вызова и избавления от своего соединения (представьте для этого примера, что это одноразовое использование в целях иллюстрации). Поэтому вы решаете использовать блок «using», чтобы позаботиться о вызове Dispose ().

using (SqlConnection conn = Foo.DBConn)
{
    conn.Open();
    using (SqlCommand cmd = new SqlCommand())
    {
        cmd.Connection = conn;
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.CommandText = "SP_YOUR_PROC";

        cmd.ExecuteNonQuery();
    }
    conn.Close();
}

Это завершается ошибкой, вызывая исключение при вызове для открытия соединения, заявляя, что «свойство ConnectionString не инициализировано». Это не проблема с извлечением строки подключения из app.config / web.config. Когда вы исследуете в сеансе отладки, вы видите, что Foo.DBConn не является нулевым, но содержит пустые свойства.

Почему это?

Ответы [ 3 ]

2 голосов
/ 21 мая 2010

Немного не в тему и не совсем отвечаю на ваш вопрос, но зачем использовать синглтон для SqlConnection, когда ADO.NET уже использует пул соединений? Ваш код мог бы очень хорошо выглядеть так:

using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString))
using (var cmd = conn.CreateCommand())
{
    conn.Open();
    cmd.Connection = conn;
    cmd.CommandType = System.Data.CommandType.StoredProcedure;
    cmd.CommandText = "SP_YOUR_PROC";
    cmd.ExecuteNonQuery();
}

И еще одна вещь, о которой нужно беспокоиться в вашей программе: жизненный цикл соединения

0 голосов
/ 21 мая 2010

Статическое поле оценивается иногда до того, как оно будет использовано (не детерминировано). См. beforefieldinit для более подробной информации. Таким образом, система может быть не готова к созданию SQL-соединения при его вызове или, возможно, даже правильно создать статическое поле после того, как вы его используете.

Кроме того, как бы вы обработали вторую SQL-команду после закрытия первой? Я не знаю точно, как работает SqlConnection, но после закрытия (обратите внимание, что это cals Dispose) и удаления соединения, ваш статический Foo.DBConn должен исчезнуть, т.е. он не будет переоценен.

Если вы хотите сохранить базовую инфраструктуру, я бы заменил статическое поле статическим свойством, которое возвращает новое SqlConnection при get:

public static SqlConnection DBConn
{
    get
    {
        return new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString);
    }
}
0 голосов
/ 21 мая 2010

Возможно, у вас нет соответствующего узла connectionStrings в вашем web / app.config?

<connectionStrings>
<add name="BAR"
     connectionString="Data Source=localhost\sqlexpress;Initial Catalog=mydatabase;User Id=myuser;Password=mypassword;" />

...