.NET Core 2.1 Web和Console的DbContexts

6

很抱歉我的问题表述可能不够清晰,我没有任何正式的培训,但现在遇到了难题。

我正在将.NET 4.7.1升级到.NET Core 2.1。我的解决方案包括两个部分:一个用于MVC的IIS Web应用程序,以及一个控制台应用程序。IIS应用程序显示数据,而控制台应用程序处理所有实际操作。

在开始对我的控制台应用程序进行端口移植之前,当我需要从数据库中获取信息时,我只会简单地

using (var db = new ApplicationDbContext())
{
    SomethingModel model = db.X.First(x => x.Whatever == whatever);
}

就这样,我从数据库中获得了想要的数据,但是你认为我能在Core 2.1中做到吗?不可能。

我已经将所有代码移植并解决了所有引用问题,就我所知,它已经准备好运行。但是我无法从数据库中调用数据,我被卡住了,谷歌只显示Code First和EF相关内容,或者我不知道我真正需要什么。

所以如果有人能帮忙,非常感谢。

--更新1--

错误是“需要对象引用才能访问非静态字段、方法或属性Program._db”。

DbModel在Data/ApplicationDbContext.cs中为IIS应用程序定义,并且如下所示:

public ApplicationDbContext(DbContextOptions<ApplicationDbContext>
options)
            : base(options)
         {
         }

-- 控制台应用程序的 Program.cs
 class Program
    {
        private ApplicationDbContext _db { get; }
        public Program(ApplicationDbContext context)
        {
            _db = context;
        }
        static void Main(string[] args)
        {
            new ExecutionEngine(_db).Run();
        }
    }

发生了什么?你是否遇到了异常? - Johnathan Barclay
所以Core有一个不同的配置模型。你至少应该发布你在哪里配置上下文和构造函数。使用DI会更好,但对于现有的应用程序来说可能太过繁琐了。 - bommelding
我已经更新了原始问题,希望能更加清晰明了。 - Mark
这不是一个升级。ASP.NET Core MVC不是ASP.NET MVC的新版本,而是全新编写的框架。你只能迁移到ASP.NET Core,而不能升级到它。这并不像更改一些软件包那么简单,就能让它正常工作。 - Tseng
1个回答

17

你之前的代码写法(using)从来都不是一个好主意。你的上下文应该是请求范围的;使用 using 可以导致实体跟踪方面的各种问题,并完全破坏 EF 进行的所有有用缓存。获取上下文实例的最佳方法始终是通过 DI 容器进行依赖注入。

ASP.NET Core 为所有内容使用依赖注入,因此 EF Core 的 DbContext 被设计为可以进行依赖注入。在这方面,它不再使用默认构造函数,这就是为什么你的旧代码会失败(它依赖于有默认构造函数的情况)。

长话短说,正确地处理事情并注入你的上下文。根据你的更新,看起来你正试图这样做。但是,你无法将其注入到像 Program 这样的东西中。这是你的应用程序的入口点,这意味着什么都不存在。如果你查看一下你的 Web 应用程序,你会注意到那里的 Program 设置了 Web 主机生成器(使用 Startup),然后构建并运行它。在幕后,这做了一堆事情,包括设置服务集合。这就是你在控制台应用程序中需要做的(设置服务集合)。这相对简单:

class Program
{
    static void Main(string[] args)
    {
        var serviceProvider = new ServiceCollection()
            .AddDbContext<ApplicationDbContext>(o =>
                o.UseSqlServer("connection string"))
            .BuildServiceProvider();

        var context = serviceProvider.GetRequiredService<ApplicationDbContext>();

        new ExecutionEngine(context).Run();
    }
}

现在,基于你在这里的代码,这有点过度使用。你可以通过DbContextOptionsBuilder简单地创建一个上下文实例:

var options = new DbContextOptionsBuilder<ApplicationDbContext>()
    .UseSqlServer("connection string")
    .Options;
var context = new ApplicationDbContext(options);

然而,使用服务集合可以让您处理更高级的情况并更好地重用像上下文这样的实例。另外值得一提的是,您应该考虑集成配置提供程序,这样您就不需要硬编码连接字符串。这也相对简单:

var config = new ConfigurationBuilder()
    .SetBasePath(Path.Combine(AppContext.BaseDirectory))
    .AddJsonFile("appsettings.json", optional: true)
    .Build();

您可能还想添加特定于环境的配置:

var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

然后:

.AddJsonFile($"appsettings.{environment}.json", optional: true);

这与在Web应用程序中执行所有操作完全相同,因此您可以添加任何类型的配置。


嗨,Chris。谢谢你详细的帖子,我会试一试学习。我的以前(使用)的问题代码是继承来的,我只是继续使用他们以前做过的东西,我没有任何关于编写代码的培训,但我正在慢慢地学习。我会回报我的发现。 - Mark
不是挑剔你的帮助,而是为了其他人,请将o.UseSqlServer("connection string"));更改为o.UseSqlServer("connection string")),多余的分号。 - Mark
接受的答案有三个原因:第一,它做到了我需要的;第二,我学到了东西;第三,很多其他的部分也顺理成章地联系在了一起。谢谢Chris和其他人 :-) - Mark
@Mark:发现得好。已修复。 - Chris Pratt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接