Database context dependency injection is not working for a page’s model.

huangapple go评论76阅读模式
英文:

Database context dependency injection is not working for a page's model

问题

I read somewhere in the ASP.NET Core documentation that I don't need to worry about how an instance of my database context will be passed to other controller and model classes as dependency injection will automatically do that for me. I declared a Database Context property in the Page's model class and then required an instance of the Database Context in the constructor of the model.

However, when I try to access the Database Context object from the Razor page associated with the model then I get an error that my Database Context is not set to an instance of an object.

The controllers do not throw this error however despite implementing the same declared database context object as property and requiring it in the constructor.

Why is my database context null when I try to access it from the Model property of the Razor page and why is it not null when I access it from the controller?

// This property is accessed from the route
var id = Model.Id;

// Use the id to get all the information about this question
var title = Model.dbctx.Posts.FirstOrDefault(x => x.Id == id).Title;

// The dbctx reference above is returning null

The code above is at the top of the Razor page.

Here is how the model for that Razor page looks like:

public class QuestionViewModel:PageModel
{
    // Get the id from the route
    [FromRoute]
    public int Id { get; set; }

    // The database context property
    public Dbctx dbctx { get; set; }

    // Require an object in the constructor
    public QuestionViewModel(Dbctx ctx)
    {
        dbctx = ctx;
    }
}

I use the same logic as the above in my controllers. The only difference is that I use private fields on my controllers and then pass the Dbctx reference to them via the constructors of the respective controllers.

How can I resolve this?

Update:

I do not know if it's the query that is returning null, but I redirect to this page after a new post object has been posted to the database. I then call databaseContext.SaveChanges() to make sure that the insert query was a success. I then grab the id of the last question that was inserted into the database and then redirect to the QuestionView page as per the logic in this controller.

public IActionResult HandleNewPost(string Title, string Body, string Tags) {
    // Split the tags based on the space
    var tags = Tags.Split(' ');
    var tagList = new List<Tag>();
    tags.ToList().ForEach(tag => tagList.Add(new Tag(tag)));
    // Get the time the post was authored
    var creationTime = DateTime.Now;
    var postedBy = HttpContext.Session.GetString("email");
    var post = new Post {
        Title = Title,
        Body = Body,
        PostedBy = postedBy,
        Tags = tagList,
        Upvotes = 0,
        Downvotes = 0
    };
    // Post the object to the database
    _dbctx.Posts.Add(post);
    _dbctx.SaveChanges();

    // Get the id of the last post and redirect to the QuestionView page
    if(_dbctx.Posts.OrderBy(x=>x.Id).LastOrDefault() != null) {
        var id = _dbctx.Posts.OrderBy(x => x.Id).LastOrDefault().Id;
        return RedirectToPage("/QuestionView", new []{id});
    }
    else {
        // Some custom code
    }
}

It is really weird that the error message starts with a different solution name. The name of my current solution is InputHandling, and there is another solution though in the repositories called ASPLearner. The QuestionView page is in the Page folder of my current solution, but the error stack begins with this line.

ASPLearner.Pages.Pages_QuestionView.ExecuteAsync() in QuestionView.cshtml
7.var title = Model.dbctx.Posts.FirstOrDefault(x => x.Id == id).Title

Is Visual Studio confused and could this be the source of the error?

英文:

I read somewhere in the ASP.NET Core documentation that I don't need to worry about how an instance of my database context will be passed to other controller and model classes as dependency injection will automatically do that for me. I declared a Database Context property in the Page's model class and then required an instance of the Database Context in the constructor of the model.

However, when I try to access the Database Context object from the Razor page associated with the model then I get an error that my Database Context is not set to an instance of an object.

The controllers do not throw this error however despite implementing the same declare database context object as property and require it in the constructor.

Why is my database context null when I try to access it from the Model property of the Razor page and why is it not null when I access it from the controller?

// This property is accessed from the route
var id = Model.Id;

// Use the id to get all the information about this question
 var title = Model.dbctx.Posts.FirstOrDefault(x =&gt; x.Id == id).Title;

// The dbctx reference above is returning null

The code above is at the top of the Razor page.

Here is how the model for that Razor page looks like:

public class QuestionViewModel:PageModel
{
    // Get the id from the route
    [FromRoute]
    public int Id { get; set; }

    // The database context property
    public Dbctx dbctx { get; set; }

    // Require an object in the constructor
    public QuestionViewModel(Dbctx ctx)
    {
        dbctx = ctx;
    }
}

I use the same logic as the above in my controllers. The only difference is that I use private fields on my controllers and then pass the Dbctx reference to them via the constructors of the respective controllers.

How can I resolve this?

Update:

I do not know if it's the query that is returning null, but I redirect to this page after a new post object has been posted to the database. I then call databaseContext.SaveChanges() to make sure that the insert query was a success. I then grab the id of the last question that was inserted into database and then redirect to the QuestionView page as per the logic in this controller.

public IActionResult HandleNewPost(string Title, string Body, string Tags) {
    // Split the tags based on the space
    var tags = Tags.Split(&#39; &#39;);
    var tagList = new List&lt;Tag&gt;();
    tags.ToList().ForEach(tag =&gt; tagList.Add(new Tag(tag)));
    // Get the time the post was authored
    var creationTime = DateTime.Now;
    var postedBy = HttpContext.Session.GetString(&quot;email&quot;);
    var post = new Post {
        Title = Title,
        Body = Body,
        PostedBy = postedBy,
        Tags = tagList,
        Upvotes = 0,
        Downvotes = 0
    };
    // Post the object to database
    _dbctx.Posts.Add(post);
    _dbctx.SaveChanges();

    // Get the id of the last post and redirect to QuestionView page
    if(_dbctx.Posts.OrderBy(x=&gt;x.Id).LastOrDefualt() != null) {
        var id = _dbctx.Posts.OrderBy(x =&gt; x.Id).LastOrDefault().Id;
        return RedirectToPage(&quot;/QuestionView&quot;, new []{id});
    }
    else {
        // Some custom code
    }
}

It is really weird that the error message starts with a different solution name. The name of my current solution is InputHandling, and there is another solution though in the repositories called ASPLearner. The QuestionView page is in the Page folder of my current solution, but the error stack begins with this line.

>ASPLearner.Pages.Pages_QuestionView.ExecuteAsync() in QuestionView.cshtml
7.var title = Model.dbctx.Posts.FirstOrDefault(x => x.Id == id).Title

Is Visual Studio confused and could this be the source of the error?

答案1

得分: 1

This method may help you:

https://github.com/dotnet/EntityFramework.Docs/blob/main/entity-framework/core/dbcontext-configuration/index.md

通过 AddDbContext 配置 DBContext

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext&lt;BloggingContext&gt;(options =&gt; options.UseSqlite(&quot;Data Source=blog.db&quot;));
}

向您的 DBContext 类中添加新的构造函数

public class BloggingContext : DbContext
{
    public BloggingContext(DbContextOptions&lt;BloggingContext&gt; options)
      :base(options)
    { }

    public DbSet&lt;Blog&gt; Blogs { get; set; }
}

将上下文注入到您的控制器中

public class MyController
{
    private readonly BloggingContext _context;

    public MyController(BloggingContext context)
    {
        _context = context;
    }

    // ...
}
英文:

This method may help you:

https://github.com/dotnet/EntityFramework.Docs/blob/main/entity-framework/core/dbcontext-configuration/index.md

Configure DBContext via AddDbContext

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext&lt;BloggingContext&gt;(options =&gt; options.UseSqlite(&quot;Data Source=blog.db&quot;));
}

Add new constructor to your DBContext class

public class BloggingContext : DbContext
{
    public BloggingContext(DbContextOptions&lt;BloggingContext&gt; options)
      :base(options)
    { }

    public DbSet&lt;Blog&gt; Blogs { get; set; }
}

Inject context to your controllers

public class MyController
{
    private readonly BloggingContext _context;

    public MyController(BloggingContext context)
    {
      _context = context;
    }

    ...
}

答案2

得分: -1

I fell victim to a bad answer by ChatGPT again. The whole capturing the value returned by the route using an integer Model Property decorated with the [FromForm] attribute was ChatGPT's idea. That attribute was always zero as all integer properties and variables that are declared, but unassigned. Since I declared the id as a primary key on my Posts table then no record will ever be found with an id of 0 and that explains why the LINQ queries were returning null.

I just used the same logic I used in the controller to fetch the details of the question at the top of the file and it worked.

英文:

I fell victim to a bad answer by ChatGPT again. The whole capturing the value returned by the route using an integer Model Property decorated with the [FromForm] attribute was ChatGPT's idea. That attribute was always zero as all integer properties and variables that are declared, but unassigned. Since I declared the id as a primary key on my Posts table then no record will ever be found with an id of 0 and that explains why the LINQ queries were returning null.

I just used the same logic I used in the controller to fetch the details of the question at the top of the file and it worked.

huangapple
  • 本文由 发表于 2023年7月13日 13:37:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76676231.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定