4

すべてのユーザー アクセス設定の読み取りを担当する 1 つのオブジェクトを作成しようとしています。

私はクラスを次のように作成しました:

public class SettingsManager
{
    private static string _connString =
        @"Data Source=MyDB;Initial Catalog=IT;Integrated Security=True;Asynchronous Processing=true;";
    private const string _spName = "SettingTest";
    private IEnumerable<string> _mySettings;
    private static readonly Lazy<SettingsManager> _instance = new Lazy<SettingsManager>(() => new SettingsManager());

    private SettingsManager()
    {
        //Console.WriteLine("Hello from constructor");
        if (_mySettings == null)
            _mySettings = ReadSettings();
    }

    public static SettingsManager Instance
    {
        get { return _instance.Value; }
    }

    public bool CanDo(string setting)
    {
        return _mySettings.Contains(setting);
    }

    private IEnumerable<string> ReadSettings()
    {
        try
        {
            using (var conn = new SqlConnection(_connString))
            {
                using (var cmd = new SqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandText = _spName;
                    cmd.CommandType = CommandType.StoredProcedure;
                    conn.Open();
                    using (var reader = cmd.ExecuteReader())
                    {
                        return reader.Select(SettingParser).ToList();
                    }
                }
            }
        }
        catch
        {
        }
        return null;
    }

    private string SettingParser(SqlDataReader r)
    {
        try
        {
            return r[0] is DBNull ? null : r[0].ToString();
        }
        catch
        {
        }
        return null;
    }
}

および SqlDataReader 拡張機能

public static class DBExtensions
{
    public static IEnumerable<T> Select<T>(
        this SqlDataReader reader, Func<SqlDataReader, T> projection)
    {
        while (reader.Read())
        {
            yield return projection(reader);
        }
    }
}

次に、アプリケーション内で次のように呼び出すことができます。

SettingsManager.Instance.CanDo("canWrite")

これは、ユーザーのアクセス レベルに応じて true/false 値を返します。

私の質問は次のとおりです。

  1. このスレッドは安全ですか? DBが複数回クエリされる可能性はありますか? これを防ぐ方法は?

  2. await と async を使用する必要がありますか? db を一度だけクエリします。どうすればこれを改善できますか? (.NET3.5 から 4.5 に移行したばかりなので、await と async は私にとってまったく新しいものです)

4

3 に答える 3

2

1) Is this thread safe?

Yes.

Are there any chances DB will be query multiple times?

No.

2) Should I use await and async?

That will depend on whether you need asynchronous access to your database. If you need that you could use the async ADO.NET API.

于 2013-02-18T08:53:00.867 に答える
1
  1. このスレッドは安全ですか?

はい。Lazy<T>スレッドセーフを確保するために型を正しく使用しています。

  1. await と async を使用する必要がありますか?

私はそれをお勧めします。現時点では、アプリケーション コードが初めて を呼び出すとSettingsManager.Instance.CanDo("canWrite")、DB が応答するまでブロックされます。asyncコンシューマーが実行できる(await SettingsManager.Instance).CanDo("canWrite")(または) 実装を行うこともできますawait SettingsManager.CanDoAsync("canWrite")。これは、DB を待っている間、コンシューマーがブロックしないことを意味します。

元々は Stephen Toub によって開発され、私の AsyncEx ライブラリに含まれている calledの準備完了asyncバージョンを使用できます。Lazy<T>AsyncLazy<T>

于 2013-02-18T13:15:52.500 に答える
1

1)はい、これはスレッドセーフです

スレッド セーフなシングルトン: この実装では、内部クラスを使用して .NET のインスタンス化を完全に遅延させます。GetInstance() のみが型初期化子をトリガーします。そのため、このバージョンは従来のバージョンと同じくらい怠け者です。そして、それは他のバージョンと同じくらい迅速に実行されます。

public sealed class Singleton
{

   private Singleton() {}

   public static Singleton GetInstance()
   {
      return NestedSingleton.singleton;
   }

   class NestedSingleton
   {
      internal static readonly Singleton singleton = new Singleton();

      static NestedSingleton() {}
   }
}

2)DBへの非同期アクセスが必要かどうかによって異なります。

于 2013-02-18T08:49:45.693 に答える