Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 确保单例调用数据库查询仅一次_C#_Singleton - Fatal编程技术网

C# 确保单例调用数据库查询仅一次

C# 确保单例调用数据库查询仅一次,c#,singleton,C#,Singleton,我正在尝试创建一个对象,该对象将负责读取所有用户的访问设置 我创建了这样的类: public class SettingsManager { private static string _connString = @"Data Source=MyDB;Initial Catalog=IT;Integrated Security=True;Asynchronous Processing=true;"; private const string _spName = "

我正在尝试创建一个对象,该对象将负责读取所有用户的访问设置

我创建了这样的类:

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;
    }
}
这将根据用户访问级别返回真/假值

我的问题是:

  • 这个线安全吗?数据库是否有可能被多次查询?如何预防

  • 我应该使用wait和async吗?我只查询数据库一次。我该如何改进这一点?(wait和async对我来说真的很新,因为我刚从.NET3.5迁移到4.5)

  • 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)这取决于您是否希望异步访问数据库。

    1) 这个线安全吗

    数据库是否有可能被多次查询

    没有

    2) 我应该使用wait和async吗

    这将取决于您是否需要对数据库进行异步访问。如果需要,可以使用异步ADO.NET API

  • 这个线安全吗
  • 对。您正在正确使用
    Lazy
    类型以确保线程安全

  • 我应该使用wait和async吗
  • 我推荐它。现在,当应用程序代码第一次调用
    setingsManager.Instance.CanDo(“canWrite”)
    时,它将阻塞,直到数据库响应为止。它还可以有一个
    异步
    实现,用户可以在其中执行
    (wait SettingsManager.Instance).CanDo(“canWrite”)
    (或
    wait SettingsManager.CanDoAsync(“canWrite”)
    )。这意味着您的使用者在等待DB时不会阻塞


    您可以使用名为
    AsyncLazy
    AsyncLazy
    AsyncLazy
    就绪版本,并且。

    @Ravi-我正在使用其中一种模式-Lazy@Ravi-lazysingleton3您不能在静态成员中使用
    this
    关键字。1。反模式使用此锁定,2。懒惰其实就是线程-safe@CuongLe-是的,Lazy是线程安全的-我只需要确保只调用一次查询。我的代码应该很好,但可能有改进的方法:)简单、快速、漂亮的答案:)只是想确保我的代码是正确的:)是的,你的代码是安全的<代码>惰性是一个线程安全的类,因此您的单例模式得到了正确的实现。另外,通过使用语句将所有IDisposable资源包装在一起,您可以正确地处理它们,这非常好。感谢您的回答,我想我尝试使用async执行第二个版本的CanDo:)
    SettingsManager.Instance.CanDo("canWrite")
    
    public sealed class Singleton
    {
    
       private Singleton() {}
    
       public static Singleton GetInstance()
       {
          return NestedSingleton.singleton;
       }
    
       class NestedSingleton
       {
          internal static readonly Singleton singleton = new Singleton();
    
          static NestedSingleton() {}
       }
    }