【问题标题】:Cannot inject Controller, DbContext inside Blazor razor page (Blazor server-side)无法在 Blazor razor 页面(Blazor 服务器端)中注入 Controller、DbContext
【发布时间】:2020-08-02 01:37:46
【问题描述】:

我正在使用最新的 .NET Core 技术栈包括:Microsoft Visual Studio Community 2019 Preview 版本 16.7.0 预览版 6.0 ; .NET Core 5.0.100-preview.7.20366.6; Microsoft.EntityFrameworkCore.SqlServer 版本 5.0.0-preview.7.20365.15 ;用于我的 Blazor 服务器端 Web 应用的 Microsoft SQLServer 2019。

Startup.cs我有

services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddSingleton<SysAutoIdController>();

在文件SystemInformation.razor

@page "/system_information"
@using myproj.Forms
@using myproj.DTO
@using myproj.Models

@inject myproj.Data.ApplicationDbContext dbContext;
@inject myproj.Controllers.SysAutoIdController sysAutoIdController;


<h3>System information</h3>

database size = @foo

@code {
   string fooTemp = sysAutoIdController.getDbSize(dbContext);
   string foo = foo2.ToString();
}

控制器,文件SysAutoIdController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using myproj.Data;
using myproj.Models;
using Microsoft.EntityFrameworkCore;

namespace myproj.Controllers
{
    public class SysAutoIdController : Controller
    {
        ApplicationDbContext db = new ApplicationDbContext();

        public string getDbSize(ApplicationDbContext db2)
        {
            var foo = db2.SysautoId.FromSqlRaw("" +
        " SELECT a.dbdisk " +
        " FROM " +
            "(SELECT sys.databases.name AS dbname, " +
              "      CONVERT(VARCHAR, SUM(SIZE) * 8 / 1024) + \' MB\' AS dbdisk " +
            " FROM sys.databases " +
           " JOIN sys.master_files ON sys.databases.database_id = sys.master_files.database_id " +
           " GROUP BY sys.databases.name) a " +
        " WHERE a.dbname = \'mydatabase\' ");
            return foo.ToString();
        }
    }
}

错误

CS0236:字段初始化程序无法引用非静态字段, 方法或属性“SystemInformation.sysAutoIdController”

CS0236:字段初始值设定项无法引用非静态字段, 方法或属性“SystemInformation.dbContext”

如何在剃刀页面成功时运行sysAutoIdController.getDbSize(dbContext); 之类的内容?

【问题讨论】:

    标签: c# asp.net-core entity-framework-core blazor blazor-server-side


    【解决方案1】:

    “字段初始化程序”在对象的构造函数之前立即运行。对于 Blazor 页面,就在任何注入发生之前。 C# 语法不允许您使用尚未构造的实例中的任何内容。

    @code {
       string fooTemp; // = sysAutoIdController.getDbSize(dbContext);
       string foo => foo2?.ToString();  // string.ToString() is a little pointless
    
        protected override async Task OnInitializedAsync()
        {
           // see if you can make getDbSize async, that would be better
           fooTemp = sysAutoIdController.getDbSize(dbContext);
        }
    }
    

    旁注:DbContext 是您需要管理的宝贵资源。让它注入Controller,你已经注册了所有东西:

    public class SysAutoIdController : Controller
    {
       public SysAutoIdController(ApplicationDbContext db)
       {
          _db = db;
       }
    
       ... 
    }
    
        
    

    【讨论】:

    • 非常有帮助,虽然你的回答不是解决方案,但它帮助我找到了解决方案。
    【解决方案2】:

    感谢Henk Holtermanhttps://stackoverflow.com/a/63213132/3728901的回答

    (1)控制器

    using myproj.Data;
    
    public class SysAutoIdController : Controller
    {
    
       ApplicationDbContext _db;
        
       public SysAutoIdController(ApplicationDbContext db)
       {
          _db = db;
       }
    
       public string getDbSize()
            {
                var foo = _db.SysautoId.FromSqlRaw("" +
            " SELECT a.dbdisk " +
            " FROM " +
                "(SELECT sys.databases.name AS dbname, " +
                  "      CONVERT(VARCHAR, SUM(SIZE) * 8 / 1024) + \' MB\' AS dbdisk " +
                " FROM sys.databases " +
               " JOIN sys.master_files ON sys.databases.database_id = sys.master_files.database_id " +
               " GROUP BY sys.databases.name) a " +
            " WHERE a.dbname = \'mydatabase\' ");
                return foo.ToString();
        }
    
    }
    

    (确实,原始SQL不起作用,我通过一个简单的查询尝试了,我稍后会修复它。)

    (2) 我没有在Startup.cs中注入控制器

    //services.AddSingleton<SysAutoIdController>(); // Important: must comment.
    

    (3) 在剃刀文件中

    @page "/system_information"
    @using myproj.Forms
    @using myproj.DTO
    @using myproj.Models
    
    
    @inject myproj.Data.ApplicationDbContext dbContext;
    @*@inject myproj.Controllers.CommonController commonController;*@  @*must comment*@
    
    
    Database size: @fooTemp
    
    @code {
        string fooTemp;
    
        protected override async Task OnInitializedAsync()
        {
            myproj.Controllers.CommonController Cc = new Controllers.CommonController(dbContext);
            // see if you can make getDbSize async, that would be better
            fooTemp = Cc.getDbSize();
        }
    
    }
    

    然后就可以了!

    真的,我不太了解这个问题,为什么它会起作用,有人可以发表评论或回答我更多信息。

    【讨论】:

    • 如果您想进一步澄清,您首先必须解释 CommonController 和 SysAutoIdController 是什么。您不应该注入或使用 ASP.Net 控制器,它需要一个 HttpContext。将逻辑重构为单独的(Servive 或 Helper)类。
    • 哦,对不起,我的意思是CommonControllerSysAutoIdController 是一样的。我创建新控制器以避免更改现有SysAutoIdController 的逻辑。
    • 好吧,你不应该那样做。 Controller 不是工具包库,它有依赖关系。
    猜你喜欢
    • 2020-04-03
    • 2020-01-07
    • 1970-01-01
    • 2021-02-05
    • 2020-01-01
    • 1970-01-01
    • 2021-11-10
    • 2021-05-10
    • 1970-01-01
    相关资源
    最近更新 更多