使用 EF 的单例设计模式和异步方法
Singleton design pattern and asynchrounous method with EF
我有一个 wpf 应用程序,我在其中使用 EF 作为 ORM。
我有很多异步调用的方法:
public Task<double> GetSelectedOGCAvance2(int reference)
{
return Task.Factory.StartNew(() =>
{
DataEntities _db = new DataEntities();
_db.Configuration.LazyLoadingEnabled = false;
using (_db)
{
var dpcs = _db.ass_dpc_ogc.Where(x => x.ass_dpc_id_fk == reference).ToList();
return (Double)dpcs[0].ass_dpc_ogc_avance2.Value;
}
});
}
上面的方法是一个例子,所有使用的方法都是类似的。
我想将 Singleton Pattern
实现到 DbContext (_db),而不是在每个方法中创建和处理它。
我想知道这是否是个好主意?如果存在另一种可以改进代码的方法,我愿意接受建议
单例模式用于拒绝创建多个实例。 作为此模式的一个可以容忍的缺点,它创建了一个全局变量。这就是您为使用它所付出的代价。
你似乎是那些想要全局变量的人之一,读过全局变量是 "bad" (tm) 现在他们发现了单例模式,虽然他们不需要它的优势,但他们会很乐意为此付出代价,因为现在你有借口拥有一个全局变量:但这是一种模式!
别这样了。模式本身并不好。它们是解决问题的工具。你没有问题,所以不要通过应用随机工具来修复它!
找到您的问题,然后然后寻找规律。提示:在 99% 的情况下,Singleton 不会很好地解决你的问题。即使看起来是这样,我向您保证使用 "singleton" 生命周期变量的依赖注入会好很多。
在您的情况下,传递给所有函数的单个变量可能就足够了。
正如@nvoigt 所提到的,Singleton 很少是一个好主意,您最好使用 IoC 来控制对象的生命周期。
但是,如果您想写一个,Jon Skeet 的 blog on singleton 是一个很好的指南。他的第六个版本的通用版本可能如下所示:
public class Foo {}
public sealed class Singleton<T> where T : class, new()
{
private static readonly Lazy<T> lazy = new Lazy<T>(() => new T());
public static T Instance { get { return lazy.Value; } }
private Singleton()
{
}
}
void Main()
{
Foo foo1 = Singleton<Foo>.Instance;
Foo foo2 = Singleton<Foo>.Instance;
if(foo1 == foo2)
{
Console.WriteLine("Foos are equal");
}
}
我之前没有使用过 SimpleIoc
但根据 documentation 你应该可以像这样注册一个单例实例:
var container = new GalaSoft.MvvmLight.Ioc.SimpleIoc();
var foo = new Foo();
container.Register<Foo>(() => foo);
var foo1 = container.GetInstance<Foo>();
var foo2 = container.GetInstance<Foo>();
if(foo1 == foo2 && foo1 == foo)
{
Console.WriteLine("Foos are equal");
}
我有一个 wpf 应用程序,我在其中使用 EF 作为 ORM。
我有很多异步调用的方法:
public Task<double> GetSelectedOGCAvance2(int reference)
{
return Task.Factory.StartNew(() =>
{
DataEntities _db = new DataEntities();
_db.Configuration.LazyLoadingEnabled = false;
using (_db)
{
var dpcs = _db.ass_dpc_ogc.Where(x => x.ass_dpc_id_fk == reference).ToList();
return (Double)dpcs[0].ass_dpc_ogc_avance2.Value;
}
});
}
上面的方法是一个例子,所有使用的方法都是类似的。
我想将 Singleton Pattern
实现到 DbContext (_db),而不是在每个方法中创建和处理它。
我想知道这是否是个好主意?如果存在另一种可以改进代码的方法,我愿意接受建议
单例模式用于拒绝创建多个实例。 作为此模式的一个可以容忍的缺点,它创建了一个全局变量。这就是您为使用它所付出的代价。
你似乎是那些想要全局变量的人之一,读过全局变量是 "bad" (tm) 现在他们发现了单例模式,虽然他们不需要它的优势,但他们会很乐意为此付出代价,因为现在你有借口拥有一个全局变量:但这是一种模式!
别这样了。模式本身并不好。它们是解决问题的工具。你没有问题,所以不要通过应用随机工具来修复它!
找到您的问题,然后然后寻找规律。提示:在 99% 的情况下,Singleton 不会很好地解决你的问题。即使看起来是这样,我向您保证使用 "singleton" 生命周期变量的依赖注入会好很多。
在您的情况下,传递给所有函数的单个变量可能就足够了。
正如@nvoigt 所提到的,Singleton 很少是一个好主意,您最好使用 IoC 来控制对象的生命周期。
但是,如果您想写一个,Jon Skeet 的 blog on singleton 是一个很好的指南。他的第六个版本的通用版本可能如下所示:
public class Foo {}
public sealed class Singleton<T> where T : class, new()
{
private static readonly Lazy<T> lazy = new Lazy<T>(() => new T());
public static T Instance { get { return lazy.Value; } }
private Singleton()
{
}
}
void Main()
{
Foo foo1 = Singleton<Foo>.Instance;
Foo foo2 = Singleton<Foo>.Instance;
if(foo1 == foo2)
{
Console.WriteLine("Foos are equal");
}
}
我之前没有使用过 SimpleIoc
但根据 documentation 你应该可以像这样注册一个单例实例:
var container = new GalaSoft.MvvmLight.Ioc.SimpleIoc();
var foo = new Foo();
container.Register<Foo>(() => foo);
var foo1 = container.GetInstance<Foo>();
var foo2 = container.GetInstance<Foo>();
if(foo1 == foo2 && foo1 == foo)
{
Console.WriteLine("Foos are equal");
}