Search code examples
.netvisual-studioentity-frameworkc#-4.0ef-code-first

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


I am working on a hands-on question which my Company has given me as a part of my training. The hands-on is based on the Code-First Approach of Entity Framework Modelling. So I have created the course class as follows:

 //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; }

 }
}

and then i have defined the CourseContext class as follows:

 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;}
        
    }
}

and then the CourseRepository class as follows:

 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;
           
        }
    }
}

and finally in the program.cs which is the main file i wrote the code as follows:

 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");
            }
            
        }
    }
}

**Now everytime i run the code of the tekstac console. I always get the error as follows: **

Failed TestCase Name : Test1InsertProduct Failure Message : System.NotSupportedException : Unsupported expression: m => m.CoursesNon-overridable members (here: CourseContext.get_Courses) may not be used in setup / verification expressions.

Failed TestCase Name : Test2GetCourseByID Failure Message : System.NotSupportedException : Unsupported expression: c => c.CoursesNon-overridable members (here: CourseContext.get_Courses) may not be used in setup / verification expressions.

Failed TestCase Name : Test3UpdateCourseFee Failure Message : System.NotSupportedException : Unsupported expression: c => c.CoursesNon-overridable members (here: CourseContext.get_Courses) may not be used in setup / verification expressions.

I really don't have any idea why is this happening.

But when i use the virtual keyword for the DbSet Courses as this 'public virtual DbSet Courses {get; set;}' , I Don't get any error. My instructor has also not told me anything about this.

Can anyone tell me what changes when i use the virtual keyword ? I really need your help.


Solution

  • The errors that you have provided refer to test case executions. The virtual keyword for the DbSet is needed for that case only.

    Check out this post to get a better understanding.