Flattening a loop with lookups into a single linq expression

前端 未结 2 1075
别那么骄傲
别那么骄傲 2021-01-15 05:38

In Type member support in LINQ-to-Entities? I was attempting to declare a class property to be queried in LINQ which ran into some issues. Here I will lay out the code insi

相关标签:
2条回答
  • 2021-01-15 06:24

    The issues you're coming across are common when you couple your database objects to your domain objects. It's for this exact reason that it's good to have a separate set of classes that represent your domain and a separate set of classes that represent your database and are used for database CRUD. Overlap in properties is to be expected, but this approach offers more control of your application and decouples your database from your business logic.

    The idea that a quiz is closed belongs to your domain (the business logic). Your DAL (data access layer) should be responsible for joining all the necessary tables so that when you return a Quiz, all the information needed to determine whether or not it's closed is available. Your domain/service/business layer should then create the domain object with the IsClosed property properly populated so that in your UI layer (MVC) you can easily access it.

    I see that you're access the database context directly, I'd warn against that and encourage you to look into using DI/IoC framework (Ninject is great), however, I'm going to access the database context directly also

    Use this class in your views/controllers:

    public class QuizDomainObject 
    {
        public int Id {get; set;}
        public bool IsClosed {get; set;}
        // all other properties
    }
    

    Controller:

    public class QuizController : Controller 
    {
        public ActionResult View(int id)
        {
            // using a DI/IoC container is the 
            // preferred method instead of 
            // manually creating a service
            var quizService = new QuizService(); 
            QuizDomainObject quiz = quizService.GetQuiz(id);
    
            return View(quiz);
        }
    }
    

    Service/business layer:

    public class QuizService
    {
        public QuizDomainObject GetQuiz(int id)
        {
            // using a DI/IoC container is the 
            // preferred method instead of 
            // access the datacontext directly
            using (EFContainer db = new EFContainer())
            {
                Dictionary<string, int> max = db.Registry
                    .Where(x => x.Domain == "Quiz")
                    .ToDictionary(x => x.Key, x => Convert.ToInt32(x.Value));
    
                var quiz = from q in db.Quizes
                           where q.Id equals id
                           select new QuizDomainObject()
                           {
                                Id = q.Id,
                                // all other propeties,
    
                                // I'm still unclear about the structure of your  
                                // database and how it interlates, you'll need 
                                // to figure out the query correctly here
                                IsClosed =  from q in ....
                           };
    
    
                return quiz;
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-15 06:29

    Re: your comment

    The join to QuestionLevels is making it think there are two contexts... but really there shouldn't be because the QuestionLevels should contain in-memory objects

    I believe that if you join on simple types rather than objects you'll avoid this problem. The following might work for you:

    return from ql in QuestionLevels                
           join q in query 
           on ql.LevelId equals q.Questions.Select(x => x.Level).Single().LevelId
           into qs 
    

    (and if this doesn't work then construct some anonymous types and join on the Id)

    The problem is that joining on the Level objects causes EF to do some under-the-covers magic - find the objects in the database and perform a join there. If you tell it to join on a simple type then it should send the values to the database for a SELECT, retrieve the objects and stitch them together back in your application layer.

    0 讨论(0)
提交回复
热议问题