Sunday, May 1, 2011

C# Linq Code Refactoring

The code below is what I currently have and works fine. I feel that I could do more of the work I am doing in Linq instead of C# code.

Is there is anyone out there who can accomplish the same result with more Linq code and less C# code.

    public List<Model.Question> GetSurveyQuestions(string type, int typeID)
    {
        using (eMTADataContext db = DataContextFactory.CreateContext())
        {
            List<Model.Question> questions = new List<Model.Question>();
            List<Linq.Survey_Question> survey_questions;
            List<Linq.Survey> surveys = db.Surveys
                                          .Where(s => s.Type.Equals(type) && s.Type_ID.Equals(typeID))
                                          .ToList();

            if (surveys.Count > 0)
            {                   
                survey_questions = db.Survey_Questions
                                     .Where(sq => sq.Survey_ID == surveys[0].ID).ToList();

                foreach (Linq.Survey_Question sq in survey_questions)
                {
                    Model.Question q = Mapper.ToBusinessObject(sq.Question);
                    q.Status = sq.Status;
                    questions.Add(q);                        
                }
            }
            else
            {
                questions = null;
            }
            return questions;
        }
    }

Here is my Mapper function from my Entity to Biz Object

  internal static Model.Question ToBusinessObject(Linq.Question q)
        {
            return new Model.Question
            {
                ID = q.ID,
                Name = q.Name,
                Text = q.Text,
                Choices = ToBusinessObject(q.Question_Choices.ToList())                
            };            
  }

I want my mapper funciton to map the Question Status like so.

 internal static Model.Question ToBusinessObject(Linq.Question q)
    {
        return new Model.Question
        {
            ID = q.ID,
            Name = q.Name,
            Text = q.Text,
            Choices = ToBusinessObject(q.Question_Choices.ToList()),
            Status = q.Survey_Questions[?].Status
        };
    }

? the issue is this function does not know which survey to pull the status from.

Instead of creating the biz object then setting the Status property in a foreach loop like so

 foreach (Linq.Survey_Question sq in survey_questions)
{
    Model.Question q = Mapper.ToBusinessObject(sq.Question);
    q.Status = sq.Status;
    questions.Add(q);                        
}

I would like to somehow filter the EntitySet<Survey_Question> in the q object above in the calling method, such that there would only be one item in the q.Survey_Questions[?] collection.

below is my database schema and business object schema alt text alt text

From stackoverflow
  • from question in db.Survey_Questions
        let surveys = (from s in db.Surveys 
         where string.Equals(s.Type, type, StringComparison.InvariantCultureIgnoreCase) &&
         s.Type_ID == typeID)
    where surveys.Any() && 
    surveys.Contains(s => s.ID == question.ID)
    select new Mapper.Question
    {
        ID = question.Id,
        Name = question.Name,
        Text = question.Text,
        Choices = ToBusinessObject(question.Question_Choices.ToList()),
        Status = question.Status
    }
    

    Does that get you on the right track?

  • Why are you duplicating all your classes? You could just extend the LINQ to SQL classes with your business logic - they are partial classes. This is somewhat against the purpose of an OR mapper - persisting business entities.

  • What I needed to do was setup a join.

      public List<Model.Question> GetSurveyQuestions(string type, int typeID)
        {
            using (eMTADataContext db = DataContextFactory.CreateContext())
            {
                return db.Survey_Questions
                         .Where(s => s.Survey.Type.Equals(type) && s.Survey.Type_ID.Equals(typeID))
                         .Join(db.Questions,
                                  sq => sq.Question_ID,
                                  q => q.ID,
                                  (sq, q) => Mapper.ToBusinessObject(q, sq.Status)).ToList();
            }
        }
    

    And then overload my Mapper Function

      internal static Model.Question ToBusinessObject(Linq.Question q, string status)
        {
            return new Model.Question
            {
                ID = q.ID,
                Name = q.Name,
                Text = q.Text,
                Status = status,
                Choices = ToBusinessObject(q.Question_Choices.ToList()),
            };
        }
    

0 comments:

Post a Comment