C# 如何从ASP.NET Core中的另一个类访问DataContext?

C# 如何从ASP.NET Core中的另一个类访问DataContext?,c#,asp.net-core,C#,Asp.net Core,我创建了一个类以便查询数据。如果我在控制器类数据上下文中这样做,但如果我在创建的类中这样做,它会抛出null错误。它抛出以下错误: Microsoft.Extensions.DependencyInjection.Abstractions.dll,但未在用户代码中处理 我的启动配置: public void ConfigureServices(IServiceCollection services) { // Add framework services. services.Ad

我创建了一个类以便查询数据。如果我在控制器类数据上下文中这样做,但如果我在创建的类中这样做,它会抛出null错误。它抛出以下错误:

Microsoft.Extensions.DependencyInjection.Abstractions.dll,但未在用户代码中处理

我的启动配置:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);

    services.AddDbContext<Abstractor_DataContext>(options =>
       options.UseSqlServer(Configuration.GetConnectionString("ApplicationDatabase")));

    //services.AddTransient(typeof(Abstractor_DataContext));


    //Register your filter as a service (Note this filter need not be an attribute as such)
    services.AddTransient<AppExceptionFilterAttribute>();

    services.AddMvc();
}
public void配置服务(IServiceCollection服务)
{
//添加框架服务。
services.AddApplicationInsightsTelemetry(配置);
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetConnectionString(“ApplicationDatabase”));
//AddTransient(typeof(Abstractor_DataContext));
//将筛选器注册为服务(注意,此筛选器本身不必是属性)
services.AddTransient();
services.AddMvc();
}
My class函数来访问DataContext

using Microsoft.Extensions.DependencyInjection;
public static IList<ApplicationInfo> TestDb()
{
    //var options = _serviceProvider.GetService<Abstractor_DataContext>();
    using (var context = _serviceProvider.GetService<Abstractor_DataContext>())
    {
        return context.ApplicationInfo.ToList();
    }
}
使用Microsoft.Extensions.DependencyInjection;
公共静态IList TestDb()
{
//var options=_serviceProvider.GetService();
使用(var context=\u serviceProvider.GetService())
{
返回context.ApplicationInfo.ToList();
}
}
var上下文
为空。我错过了什么?我正在慢慢地学习DI

根据新的基于DB的ASP.net核心项目,首先需要创建模型和DbContext:

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

namespace EFGetStarted.AspNetCore.NewDb.Models
{
    public class BloggingContext : DbContext
    {
        public BloggingContext(DbContextOptions<BloggingContext> options)
            : base(options)
        { }

        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }

        public List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
}
在任何类中使用DbContext与在控制器中使用它是相同的。您需要将类注册到依赖项注入器。这是在
ConfigureServices
方法中完成的。包含详细信息。以下是注册服务类实现的一些示例:

services.AddScoped<ICharacterRepository, CharacterRepository>();
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
services.addScope();
services.AddTransient();
services.addScope();
services.AddSingleton();
AddSingleton(新操作(Guid.Empty));
services.AddTransient();
正如许多人所说(在a中也是如此),访问模型中的数据上下文在SOLID中是一种反模式,但在某些项目中可能是有意义的

可以先注入依赖项,然后再注入模型,这样就不必为每个模型注册服务

下面的示例演示如何从模型访问数据库以获取视图的下拉值

查看

@model MyProject.Models.MyClass
@inject MyDataContext db
@{
    ViewData["Title"] = "Create";
    MyClass tmp = new MyClass(db);
}

<!-- Markup... -->

<select asp-for="MyField" class="form-control" asp-items="tmp.MyModelFunc()"></select>
private readonly MyDataContext db;
public MyClass(MyDataContext context)
{
    db = context;
}

// class properties...    

public IEnumerable<SelectListItem> MyModelFunc()
{
    List<SelectListItem> ddlb = db.MyClass.Select(x => new SelectListItem { Value = x.ID, Text = x.name}).ToList();
    return new SelectList(ddlb , "Value", "Text");
}
@model MyProject.Models.MyClass
@注入MyDataContext数据库
@{
ViewData[“标题”]=“创建”;
MyClass tmp=新的MyClass(db);
}
型号

@model MyProject.Models.MyClass
@inject MyDataContext db
@{
    ViewData["Title"] = "Create";
    MyClass tmp = new MyClass(db);
}

<!-- Markup... -->

<select asp-for="MyField" class="form-control" asp-items="tmp.MyModelFunc()"></select>
private readonly MyDataContext db;
public MyClass(MyDataContext context)
{
    db = context;
}

// class properties...    

public IEnumerable<SelectListItem> MyModelFunc()
{
    List<SelectListItem> ddlb = db.MyClass.Select(x => new SelectListItem { Value = x.ID, Text = x.name}).ToList();
    return new SelectList(ddlb , "Value", "Text");
}
private只读MyDataContext数据库;
公共MyClass(MyDataContext上下文)
{
db=上下文;
}
//类属性。。。
公共IEnumerable MyModelFunc()
{
List ddlb=db.MyClass.Select(x=>newselectListItem{Value=x.ID,Text=x.name}).ToList();
返回新的选择列表(ddlb,“值”、“文本”);
}

您没有将DbContext作为输入,因此它无法向您提供DbContext对象。您何时使用此
TestDb
方法?如果在调用此方法时数据上下文已经注册,那么它应该可以工作。但在这个例子中,若你们在数据库
Seed
期间调用这个函数,它将不起作用。[HttpGet][Route(“GetTestDb”)]public IList GetTestDb(int id){return DataAccessServices.TestDb();/_context.ApplicationInfo.ToList()}OP希望访问控制器外部的上下文。不是这样的。三菊谢谢你的意见。我确实使用EF创建了模型。如果像您提供的示例一样访问控制器类中的数据上下文,那么一切都可以正常工作,但是如果我尝试在另一个不是控制器的类中使用数据上下文,则会抛出错误。阅读文档时说使用iSeries调用dbcontext服务并添加microsoft扩展DI包,但这仍然会引发错误,并说上下文为空。更新了答案,在服务类(控制器类之外)中使用DI使用dbcontext。谢谢,它现在可以工作了。我创建了接口类,然后将其注册到startup.cs文件中。一个问题是,你必须有接口类,还是可以注册没有接口的类?你可以注册没有接口的类。使用
services.AddScoped()我认为使用接口是一种很好的设计模式,因为
接口
抽象了实际的实现,您将能够使用接口轻松地更改实现,而无需对调用类中的依赖项需求进行任何更改,因为它们取决于接口。