我正在尝试创建一个负责阅读所有用户访问设置的对象。
我已经创建了类:
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值取决于用户访问级别。
我的问题是:
这个线程安全吗?有没有机会DB多次查询?如何防止这种情况?
我应该使用await和async吗?我只查询一次db。我怎样才能改善这个? (await和async对我来说真的很新,因为我刚刚从.NET3.5迁移到4.5)
答案 0 :(得分:2)
1)这个线程安全吗?
是
DB有多少次查询?
没有
2)我应该使用await和async吗?
这取决于您是否需要异步访问数据库。如果需要,可以使用异步ADO.NET API。
答案 1 :(得分:1)
1)是的,线程安全
线程安全的Singleton: 此实现使用内部类使.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)如果您想要对数据库进行异步访问,则依赖它。
答案 2 :(得分:1)
- 这个线程安全吗?
醇>
是。您正确使用Lazy<T>
类型以确保线程安全。
- 我应该使用await和async吗?
醇>
我会推荐它。现在,第一次应用程序代码调用SettingsManager.Instance.CanDo("canWrite")
时,它将一直阻塞,直到数据库响应。您的消费者可以async
(或(await SettingsManager.Instance).CanDo("canWrite")
)进行await SettingsManager.CanDoAsync("canWrite")
实施。这意味着您的消费者在等待数据库时不会阻止。
您可以使用名为async
,originally developed by Stephen Toub和included in my AsyncEx library的Lazy<T>
就绪版AsyncLazy<T>
。