【问题标题】:How to display foreign key name in list table in Blazor Client Side如何在 Blazor 客户端的列表中显示外键名称
【发布时间】:2020-03-14 18:17:46
【问题描述】:

我正在尝试显示我从客户端 Blazor 应用程序的数据库驱动下拉列表中保存主题的课程的主题名称。该值作为 Guid 而不是主题名称返回。有没有人用 Blazor 做到这一点?我在 Blazor 文档或任何可以解决我遇到的问题的教程中找不到任何内容。这是在 Blazor 客户端,我正在使用 Entity Framework Core

这是我的课程模型在共享项目中的样子:

public class Course
    {
        public Guid CourseID { get; set; }

        [Required]
        public string CourseCode { get; set; }

        [Required]
        public string CourseName { get; set; }

        public string CourseSubject { get; set; }

        public string CourseCredits { get; set; }
    } 

这是我的主题模型在共享项目中的样子:

public class Subject
    {
        public Guid SubjectID { get; set; }

        public string SubjectName { get; set; }
    } 

这是我在服务器项目中的 CourseData 数据访问模型:

ApplicationDbContext db = new ApplicationDbContext ();

public IEnumerable<Course> GetAllCourses()
        {
            try
            {
                return db.Courses.ToList();
            }
            catch
            {
                throw;
            }
        } 
        public void AddCourse(Course course)
        {
            try
            {
                db.Courses.Add(course);
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        } 

这是我在服务器项目中的 SubjectData 数据访问模型:

ApplicationDbContext db = new ApplicationDbContext ();

        public IEnumerable<Subject> GetAllSubjects()
        {
            try
            {
                return db.Subjects.ToList();
            }
            catch
            {
                throw;
            }
        }    
        public void AddSubject(Subject subject)
        {
            try
            {
                db.Subjects.Add(subject);
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        } 

这是我在服务器项目中的课程控制器:

CourseData objcourse = new CourseData();

        [HttpGet]
        [Route("api/Courses/Courses")]
        public IEnumerable<Course> Index()
        {
            return objcourse.GetAllCourses();
        }
        [HttpPost]
        [Route("api/Courses/Create")]
        public void Create([FromBody] Course course)
        {
            if (ModelState.IsValid)
                objcourse.AddCourse(course);
        } 

这是我在客户项目的课程创建页面中保存值的方式:

@page "/Courses/Create"
@inject HttpClient Http
@inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager

<h1>Add Course</h1>
<hr />
<div class="row">
    <div class="col-md-4">
        <div>
            <div class="form-group">
                <label for="CourseCode" class="control-label">Course Code</label>
                <input for="CourseCode" class="form-control" @bind="@course.CourseCode" />
            </div>
            <div class="form-group">
                <label for="CourseName" class="control-label">Course Name</label>
                <input for="CourseName" class="form-control" @bind="@course.CourseName" />
            </div>
            <div class="form-group">
                <label for="CourseSubject" class="control-label">Subject</label>
                <select class="form-control" @bind="@course.CourseSubject">
                    <option></option>
                    @foreach (var subject in subjectList)
                    {
                        <option value="@subject.SubjectID">@subject.SubjectName</option>
                    }
                </select>
            </div>
            <div class="form-group">
                <label for="CourseCredits" class="control-label">Course Credits</label>
                <input for="CourseCredits" class="form-control" @bind="@course.CourseCredits" />
            </div>
            <div class="form-group">
                <button type="submit" class="btn btn-default" @onclick="@CreateCourse">Save</button>
                <button class="btn" @onclick="@cancel">Cancel</button>
            </div>
        </div>
    </div>
</div>
@functions {
    List<Subject> subjectList = new List<Subject>();

    Course course = new Course();

    protected override async Task OnInitializedAsync()
    {
        subjectList = await Http.GetJsonAsync<List<Subject>>("api/Subjects/Subjects");
    }

    protected async Task CreateCourse()
    {
        await Http.SendJsonAsync(HttpMethod.Post, "/api/Courses/Create", course);
        NavigationManager.NavigateTo("/Courses/Courses");
    }

    void cancel()
    {
        NavigationManager.NavigateTo("/Courses/Courses");
    }
} 

最后,这是我的客户项目中的课程列表页面,它返回主题名称的 Guid,我想显示主题名称而不是 Guid:

@page "/Courses/Courses"
@inject HttpClient Http
<h1>Courses</h1>
<p>
    <a href="/Courses/Create">Create New</a>
</p>
@if (courseList == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class='table'>
        <thead>
            <tr>
                <th>Course Code</th>
                <th>Course Name</th>
                <th>Subject</th>
                <th>Credits</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var course in courseList)
            {
                <tr>
                    <td>@course.CourseCode</td>
                    <td>@course.CourseName</td>
                    <td>@course.CourseSubject</td>
                    <td>@course.CourseCredits</td>
                    <td>
                        <a href='/Courses/Edit/@course.CourseID'>Edit</a>  |
                        <a href='/Courses/Delete/@course.CourseID'>Delete</a>
                    </td>
                </tr>

            }
        </tbody>
    </table>
}
@functions {
    Course[] courseList;

    protected override async Task OnInitializedAsync()
    {
        courseList = await Http.GetJsonAsync<Course[]>
        ("/api/Courses/Courses");
    }
} 

请求的数据库上下文:

public class ApplicationDbContext : DbContext
    {
        public virtual DbSet<Course> Courses { get; set; }
        public virtual DbSet<Subject> Subjects { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(@"REMOVED-FOR-SECURITY");
            }
        }
    } 

我们将不胜感激。

【问题讨论】:

    标签: foreign-keys entity-framework-core blazor blazor-client-side


    【解决方案1】:

    其他答案很好,但让我给你一些其他的想法......

    在编写 Blazor 应用程序时,尝试更多地考虑组件而不是代码

    例如,假设Subjects 是不会发生太大变化的静态数据。因此,如果每次显示列表或想要为它们构建下拉列表时,您可能必须进行数据库调用或 SQL JOIN?所以我的第一个想法是为 GUID-to-Subject-name 创建一个查找缓存。由于这是 Blazor,如果它缓存在客户端上,您不再需要进行数据库或 API 调用 - 它只加载一次。

    然后,由于我们在 Blazor 中,我将创建一个 &lt;SubjectName&gt; 组件,例如

       Subject: <SubjectName Id="@Model.SubjectId" />
    

    组件使用缓存来获取值,它可以处理一个空值,它可以处理一个无效的主题 ID。您已经在一个地方封装了很多的行为和错误处理,并且可以在每次需要将 ID 映射到主题名称时重复使用。

    同样,我会创建一个&lt;SubjectDropdown&gt; 组件来显示主题列表,再次使用缓存。

    【讨论】:

    • 感谢改进答案和分享知识。
    【解决方案2】:

    您将CourseSubjectSubjectID 设置为Guid,因此您得到了一个Guid。 如果您想显示主题名称,请通过其 Guid 请求主题,或在您的课程中返回主题:

    public class Course
    {
        public Guid CourseID { get; set; }
    
        [Required]
        public string CourseCode { get; set; }
    
        [Required]
        public string CourseName { get; set; }
    
        public string CourseSubject { get; set; }
    
        public string CourseCredits { get; set; }
    
        public virtual Subject Subject { get; set; }
    }
    
    public IEnumerable<Course> GetAllCourses()
    {
        try
        {
             return db.Courses
                .Include(c => c.Subject)
                .ToList();
        }
        catch
        {
            throw;
        }
    ...
    }
    
    
     @foreach (var course in courseList)
      {
          <tr>
              <td>@course.CourseCode</td>
              <td>@course.CourseName</td>
              <td>@course.Subject.SubjectName</td>
              <td>@course.CourseCredits</td>
              <td>
                  <a href='/Courses/Edit/@course.CourseID'>Edit</a>  |
                   <a href='/Courses/Delete/@course.CourseID'>Delete</a>
              </td>
          </tr>
    }
    
    

    【讨论】:

    • 这个解决方案对我不起作用。我得到一个对象引用未设置为对象错误的实例。它还在我的 Courses 表中添加了一个 SubjectID 字段。保存课程时此字段为空,并且 ID 仍保存到 CourseSubject 字段。如果我走我在 MVC 中所做的路线,我将添加一个公共虚拟 ICollection Courses { get;放; } 到 Subject 模型并在我的 Course 模型中将 CourseSubject 更改为 SubjectID,创建课程页面中断,没有明确的错误错误。
    • 更新你的数据库,并检查迁移是否创建了外键
    • 当我添加公共虚拟 ICollection Courses { get; 时,它确实创建了外键关系放; } 到主题模型。然后我在数据库中手动创建了一条课程记录,并将现有主题的 Guid 放在外键字段中,但是表中断并且没有返回任何内容
    • 你能发布你的 DbContext 吗?
    • 将数据库上下文添加到原始帖子:)
    猜你喜欢
    • 2012-06-25
    • 2021-05-23
    • 2019-12-22
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多