2

i have the following ViewModel and I can't find a way to access the variables to perform a select operation

 public class ViewOptionValues
{
    public Option Option { get; set; }
    public IEnumerable<OptionValue_SetVal> Values { get; set; }
}

public class OptionValue_SetVal
{
    public OptionValue OptionValue { get; set; }
    public IEnumerable<SetValue> SetValues { get; set; }
}

public class Option
{
    public int OptionID { get; set;}
    public string OptionName { get; set; }

    public int LsystemID { get; set; }

    public virtual ICollection<OptionValue> OptionValues { get; set; }
}

public class OptionValue
{
    public int OptionValueID { get; set; }
    public string OptionVal { get; set; }

    public int OptionID { get; set; }

    public virtual Option Option { get; set; }
    public virtual ICollection< SetValue> SetValue { get; set; }
}

public class SetValue
{
    public int SetValueID { get; set; }
    public string Value { get; set; }
    public bool Status { get; set; }

    public int OptionValueID { get; set; }

    public virtual OptionValue OptionValue { get; set; }
}

I have added the model class for Option to make it clear that it has a Collection of Option Values and my Option class has a collection of SetValues.

I have two questions :

  1. Do I really require a ViewModel like OptionValue_SetVal ?
  2. How can I set the value for an object of SetVal from my controller?

What I am trying to achieve

Select all OptionValues of a Parent class Option which i am able to achieve through the var op. Now through var setVal I am trying to populate the IEnumerable<SetVal> for eachOptionValue`.

Things that I am failing

  1. Accessing the ID of the OptionValue for which the SetVal needs to be populated.
  2. Populate SetVal

This is my controller(It has build errors in the line adding values for SetVal)

    public ActionResult ViewOptionvalues(int id)
    {
        var viewModel = new ViewOptionValues();
        if (id != 0)
        {
            var op = db.Option.Include(x => x.OptionValues).FirstOrDefault(x => x.OptionID == id);
            if(op!=null)
            {
                op.OptionValues= 
                var setval = db.OptionValue.Include(x => x.SetValue).FirstOrDefault(x => x.OptionValueID == op.OptionID);
                viewModel.Values = setval.SetVal;
                viewModel.OptionValues = op.OptionValues;
            }
        }
    }

EDIT

Based on the comments I have removed the ViewModel ÒptionValue_SetValueand placed a collection of ÒptionValues instead.

Controller

    public ActionResult ViewOptionValues(int id)
    {
        var viewmodel = new Option_OptionValues();
        var op = db.Option.Include(x => x.OptionValues).FirstOrDefault(x => x.OptionID == id);
        var set = db.OptionValue.Include(x => x.SetValue).FirstOrDefault(x => x.OptionValueID == id); //set is being populated, but I am not sure what need to be placed instead of id  in this line
        if(op!=null)
        {
            viewmodel.OptionValues = op.OptionValues;

        }
        return View(viewmodel);
    }

View

@foreach (var item in Model.OptionValues)
{
    <tr>
        <td rowspan="@item.SetValue.Count">@item.OptionVal</td>
        <td rowspan="@item.SetValue.Count">@item.OptionValueID</td>
        @{var set = item.SetValue.FirstOrDefault(x => x.OptionValueID == item.OptionValueID);}
            @if (set != null)
        {

            for (int i = 0; i < item.SetValue.Count; i++)
            {
                <tr>
                    <td>@set.TcSet.SetName</td>
                    <td> @set.Value</td>       
                    <td>@set.Status</td>
                    </tr>
            }

        }
        </tr>
}

In the view I am doing the controller logic(which is not right), but can't get different values for the SetValue.. The count is right but the values I get are the same.

EDIT

Added join

        var set = (from o in db.Option
                   join ov in db.OptionValue on o.OptionID equals ov.OptionID
                   join s in db.SetValue on ov.OptionValueID equals s.OptionValueID
                   where o.TechnicalCharacteristicID == s.TcSet.TechnicalCharacteristicID
                   select ov.SetValue).SingleOrDefault();
Vini
  • 1,978
  • 8
  • 40
  • 82
  • 2
    "the following viewmodel", "the following": did you forget to post the code? – Thomas Levesque Oct 07 '15 at 11:43
  • yes.. posting it in a minute – Vini Oct 07 '15 at 11:43
  • @ViniVasundharan Can you elaborate, what build errors are you getting? It seems you provided incomplete code "op.OptionValues= " after the line if(op!=null){ ... Also please refine your questions with exact variable names you posted in code. – Siva Gopal Oct 07 '15 at 12:07
  • I did not write it because not even the Intellisense is suggesting me what I have in my code. – Vini Oct 07 '15 at 12:08
  • @SivaGopal: i have edited the code with other model classes and added more detailed explanation for my aim – Vini Oct 07 '15 at 12:23
  • Did you check if all the required objects are loading with: db.Option.Include(x => x.OptionValues).Include(x => x.SetValue).... ? – Siva Gopal Oct 07 '15 at 12:57
  • i am unable to set values for `viewModel.Values` So i cant debug to check the values. – Vini Oct 07 '15 at 13:04
  • @ViniVasundharan Then comment those lines giving compile error and then try it step-by-step before you proceed any further. – Siva Gopal Oct 07 '15 at 13:09
  • The problem I see is your collections need to be instantiated as empty collections so you don't get null reference exceptions. Instead of creating a new ViewOptionValues() object, I would create a service (ViewOptionValuesService()) that has a constructor which will instantiate the collections for you. – Jason Williams Oct 07 '15 at 13:12
  • @siva gopal: i have tried it without setval and it worked. – Vini Oct 07 '15 at 13:28
  • @ Jason i will try that. Thanks – Vini Oct 07 '15 at 13:29
  • @JasonWilliams : Am i missing something in your point? CAn I create a constructor for ViewOptionValue to instantiate the class? I did not understand what you meant by `ViewOptionValueService` – Vini Oct 08 '15 at 05:32
  • Yes. Create a new class called ViewOptionValueService(). Create a public constructor in the class called ViewOptionValueService(). Create a public property of type ViewOptionValue(). Call the new property ViewModel. Inside the Constructor, initialize this.ViewModel by setting all your collections as new objects. From your code, you will be able to safely set properties on ViewOptionValueService.ViewModel. I would also move all your business logic out of your Controller and into this new service Class. – Jason Williams Oct 08 '15 at 17:47

1 Answers1

1

If I understand your problem correctly, you are trying to assign a single object to a collection which is not allowed.

var setval = db.OptionValue.Include(x => x.SetValue).FirstOrDefault(x => x.OptionValueID == op.OptionID); //Notice FirstOrDefault(...)

As a quick(& of course dirty!) workaround, you may try with following:

viewModel.Values = new List<OptionValue_SetVal> {new OptionValue_SetVal{} };
viewModel.Values.First().SetValues = new List<SetValue> { setval };
//Assuming you have only one OptionValue_SetVal that hold setVal. Otherwise as a simple step you can go with foreach loop to make things work before you refactor.

NOTE: As a better approach, you can move these default collection initialization logic to a constructor within the class or a separate service as mentioned by @Jason.

Hope this help you...

Siva Gopal
  • 3,474
  • 1
  • 25
  • 22
  • I am not sure if i understood it right. you are trying to instantiate the list of OptionValue_SetValue and the the list of SetValue within the OptionValue_SetValue. – Vini Oct 08 '15 at 05:28
  • I ahve updted the question with the new controller and the error following. – Vini Oct 08 '15 at 05:41
  • @ViniVasundharan Based on your updated code & error, I see you are trying to assign a collection/list to a single object which is not allowed. So if you think you are going to get a collection of 'OptionValues' data then you need to hold a collection inside your viewmodel also or filter & assign only the required single 'OptionValue' object data you get from db. – Siva Gopal Oct 08 '15 at 06:52
  • Correct me if i am wrong : In my ViewModel `ViewOptionValues` , I have one `Option` and a collection of `OptionValue_SetVal` which in turn has a collection of `SetValues`. So should I be really using the second Viewmodel, because I already have the collection of `SetVal` in my `OptionValue` class. – Vini Oct 08 '15 at 07:01
  • So what I think I would get from the object of the ViewOptionValue ViewModel is : `Option`, A collection of `OptionValues` and a collection of `SetValues`. But I already have the collection of `SetValues` in my `OptionValues`. Am i making it redundant? – Vini Oct 08 '15 at 07:03
  • Yes you are correct. If your EF queries are populating as expected then you can try removing the list of 'OptionValue_SetVal' from your view model because the object graph you posted shows all the associations from 'Option' class itself. – Siva Gopal Oct 08 '15 at 07:08
  • Yes. Now i have removed that and I am only using Option and Collection of OptionValues. – Vini Oct 08 '15 at 07:09
  • But still I am unable to make the SetValue populate. – Vini Oct 08 '15 at 07:10
  • I check in the debugger and find that the values are being populated in the right way. But i cant't get it working in the code. – Vini Oct 08 '15 at 07:10
  • Updated my code with new Controller and View. I have some controller logic in my view to get things right. – Vini Oct 08 '15 at 07:15
  • So you need to change your assignment also? Now try changing the assignment to: viewModel.Option.OptionValues = op.Option.OptionValues and check – Siva Gopal Oct 08 '15 at 07:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/91705/discussion-between-siva-gopal-and-vini-vasundharan). – Siva Gopal Oct 08 '15 at 07:16
  • I think you need to research on entity framework joins to get correct values based on your database relations. Take a look at [here](http://stackoverflow.com/questions/21051612/entity-framwork-join-3-tables) and [here](http://stackoverflow.com/questions/11204367/how-to-join-multiple-tables) – Siva Gopal Oct 08 '15 at 07:44
  • ok. so should i be using join in my case to achieve the task ? or is it a suggestion for me to learn? – Vini Oct 08 '15 at 07:47
  • Everything is your question specific. Please read my comment once again :) – Siva Gopal Oct 08 '15 at 07:48
  • Sure :).. And I should add the join in my ViewModel to get it right. Though I have not understood thereal purpose why i should be using join here to do this. – Vini Oct 08 '15 at 07:54
  • You should add the join in controller logic where you query db to get data. To my understanding you need to join the OptionValue and SetValue tables from linq to load SetValue data associated with each OptionValue you are querying based on Primary/Foreign key relation. Hope you get it. – Siva Gopal Oct 08 '15 at 07:59
  • I could not get the join right. I will update the question with the join i tried. I am missing something relevant about joins. – Vini Oct 08 '15 at 08:28
  • What do you mean by "I could not get the join right"? What is the exact problem? – Siva Gopal Oct 08 '15 at 09:30
  • I have added the join. But i am still unable to assign the value of the join to SetValue in ViewModel – Vini Oct 08 '15 at 09:35
  • You put a .SingleOrDefault() at end of join which gives you single object. Instead if you put .ToList() it will get you a collection and then you should be assign it as discussed earlier. – Siva Gopal Oct 08 '15 at 09:45
  • Ok . Thank you. I will try. – Vini Oct 08 '15 at 09:47
  • I am unable to assign my the result of the join list to the viewmodel list.. I have tried using joins. `var set = db.OptionValue.Include(x => x.SetValue).Where(x => x.OptionValueID == op.OptionValues.First().OptionValueID).ToList(); ` – Vini Oct 09 '15 at 06:13