控制台/库应用程序中的实体框架初始化器

本文关键字:实体 框架 初始化 应用程序 控制台 | 更新日期: 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()