在 C# 中有必要为 DbSet 设置 virtual 关键字

It is necessary to have virtual keyword for DbSet in c#

我正在做一个实践问题,这是我的公司在培训中给我的。实践基于 Entity Framework 建模的代码优先方法。所以我创建了课程 class 如下:

 //Course.cs file
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks; 
 namespace Exercise1 
{
  public  class Course  
    {
        
        public int CourseId { get; set; }
        public String CourseName { get; set; }
        public double CourseFee { get; set; }
        public int Duration { get; set; }
        public String InstructorName { get; set; }

 }
}

然后我定义了 CourseContext class 如下:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Data.Entity;
 namespace Exercise1
 {
 public  class CourseContext:DbContext        
     {

        public CourseContext() : base("name=CourseConnectionString"){}
        public  DbSet<Course> Courses {get; set;}
        //public virtual DbSet<Course> Courses {get; set;}
        
    }
}

然后CourseRepository class如下:

 using System;
 using System.Collections.Generic;
 using System.Data.Entity;
 using System.Linq;
 
 namespace Exercise1             //DO NOT Change the namespace name
 {
     public class CourseRepository      //DO NOT Change the class name
     {
        //Thi perform operation like insert,update, retrieve and delete method.
        
        private CourseContext context;
        
        public CourseRepository(CourseContext context)
        {
            this.context=context;
            //last line
        }
        
        public IList<Course> GetCourseList()
        {
            IList<Course> result = this.context.Courses.ToList();
            return result;
             
            //last line
        }

        public Course GetCourseByID(int courseId)
        {
           Course c = new Course();
           c = null;
           c = this.context.Courses.Find(courseId);
           return c;
           //Implement code here
        }

        public void InsertCourse(Course course)
        {
            
            this.context.Courses.Add(course);
            this.context.SaveChanges();
            Console.WriteLine("Details Added Successfully");
            // last line
        }

        public Course UpdateCourseFee(int id, double fee)
        {
           Course c =  new Course();
           c = null;
           foreach(Course cc in this.context.Courses)
           {
               if(cc.CourseId == id)
               {
                   cc.CourseFee = fee;
                   c = cc;
               }
           }
           this.context.SaveChanges();
           return c;
           
        }
    }
}

最后在主文件 program.cs 中,我编写了如下代码:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
 namespace Exercise1      
 {
      public class Program
    {
        static void Main(string[] args)
        {
            CourseContext courseContext = new CourseContext();
            
            CourseRepository cr = new CourseRepository(courseContext);
            
            
            Course NewCourse = new Course();
            
            // taking the details of the first course
            Console.WriteLine("Enter Course Id");
            NewCourse.CourseId = int.Parse(Console.ReadLine());
            Console.WriteLine("Enter Course Name");
            NewCourse.CourseName = Console.ReadLine();
            Console.WriteLine("Enter Duration");
            NewCourse.Duration = int.Parse(Console.ReadLine());
            Console.WriteLine("Enter Course Fee");
            NewCourse.CourseFee = double.Parse(Console.ReadLine());
            Console.WriteLine("Enter Instructor Name");
            NewCourse.InstructorName = Console.ReadLine();
            cr.InsertCourse(NewCourse);
            
            // get course list
            var resultList = cr.GetCourseList();
            
            
                foreach(var item in resultList)
                {
                    Console.WriteLine("{0}",item);
                }
            
            
            // get course details by id
            Console.WriteLine("get Course Details By id");
            int id = int.Parse(Console.ReadLine());
            var result = cr.GetCourseByID(id);
            if(result != null)
            {
                Console.WriteLine(result);
            }
            
            //update the course Fee
            Console.WriteLine("Update Course Fee");
            int updateId = int.Parse(Console.ReadLine());
            double fee = double.Parse(Console.ReadLine());
            Course tush = cr.UpdateCourseFee(updateId,fee);
            if(tush!=null)
            {
                Console.WriteLine("Updated Successfully");
            }
            
        }
    }
}

**现在我每次 运行 tekstac 控制台的代码。我总是得到如下错误:**

失败的测试用例名称:Test1InsertProduct 失败消息:System.NotSupportedException:不支持的表达式:m => m.CoursesNon-可覆盖成员(此处:CourseContext.get_Courses)不能用于设置/验证表达式。

失败的测试用例名称:Test2GetCourseByID 失败消息:System.NotSupportedException:不支持的表达式:c => c.CoursesNon-可覆盖成员(此处:CourseContext.get_Courses)不能用于设置/验证表达式。

失败的测试用例名称:Test3UpdateCourseFee 失败消息:System.NotSupportedException:不支持的表达式:c => c.CoursesNon-可覆盖成员(此处:CourseContext.get_Courses)不能用于设置/验证表达式。

我真的不知道为什么会这样。

但是当我像这样使用 DbSet 课程的虚拟关键字 'public virtual DbSet Courses {get; set;}' 时,我没有收到任何错误。我的导师也没有告诉我任何关于这件事的事情。

谁能告诉我使用 virtual 关键字时发生了什么变化? 我真的需要你的帮助。

没必要使用virtual关键字。当您为 table 创建数据库上下文和模型 class 时,您必须 运行 迁移以在您的数据库中创建 table。

您提供的错误是指测试用例执行。只有在这种情况下才需要 DbSet 的虚拟关键字。

查看 this post 以获得更好的理解。