控制台/库应用程序中的实体框架初始化器
本文关键字:实体 框架 初始化 应用程序 控制台 | 更新日期: 2023-09-27 18:02:02
我目前正在一个项目上工作,有一个控制台应用程序和几个库项目。一个库项目是EF代码优先项目,它包含了我的模型和上下文:
public class MyDbContext: DbContext
{
public MyDbContext() : base("MyConnectionString")
{
}
public DbSet<File> Files { get; set; }
}
我也有一个单例类,我想通过它访问数据库。这个单例是这样的:
public sealed class DbLogger : IDbLogger
{
private static readonly DbLogger instance = new DbLogger();
private static MyDbContext ctx = new MyDbContext();
static DbLogger() {
Database.SetInitializer<MyDbContext>(new DbInitializer());
}
private DbLogger() { }
public static DbLogger Instance
{
get {
return instance;
}
}
public void AddFile(string fileName)
{
ctx.Files.Add(new File() { FullPath = fileName });
}
}
db初始化器非常简单,只实现了CreateDatabaseIfNotExists。
在控制台所有引用库项目,我只是想使用它作为:
private DbLogger logger = DbLogger.Instance;
并从任务中调用日志记录器,使用:
logger.AddFile("myFileName");
当应用程序到达logger时。我得到以下异常:
类型为'System '的异常。InvalidOperationException'发生在EntityFramework.dll,但未在用户代码中处理
附加信息:当模型处于状态时,不能使用上下文被创建。如果使用了上下文,则可能引发此异常在OnModelCreating方法中,或者在相同的上下文实例中由多个线程并发访问。请注意,实例成员的DbContext和相关类不能保证是线程安全的。
我如何延迟上下文的使用,直到模型被创建?我现在有点困在这个问题上,任何关于如何解决这个问题的想法都会很感激。
谢谢!
我推荐这种方法
public void AddFile(string fileName){
using(var ctx = new MyDbContext() ){
ctx.Files.Add(new File() { FullPath = fileName });
ctx.SaveChanges();
}
}
您应该只在需要时使用DbContext。打开DB连接,与DB交互,然后关闭连接。using语句负责打开和关闭DB连接。
编辑——更新SaveChanges ()
ad to @Kunukn answer:
我认为你应该责怪
private static MyDbContext ctx = new MyDbContext();
试图在数据库初始化程序运行之前访问上下文。
如果你不想在每次调用AddFile()时都创建新的上下文,可以尝试在静态构造函数中创建上下文。
我看到一行有问题
数据库。SetInitializer(新DbInitializer ());
如果使用public void AddFile(string fileName){
using(var ctx = new MyDbContext() ){
ctx.Files.Add(new File() { FullPath = fileName });
ctx.SaveChanges();
}
}
那么你的单例目的没有得到解决,因为它会创建一个新的MyDbContext每次AddFile被调用(这是推荐的)
,但即使你坚持只有一个dbcontext对象,你也应该创建一些初始化函数,可以在对象创建后调用。
可能像
private DbLogger logger = DbLogger.Instance;
logger.Initialize()