Beengie
Beengie

Reputation: 1608

populate dropdownlistfor mvc

I having a problem understanding some of the datatypes and datasets with MVC and LINQ. I am trying to populate a dropdownlist.

I receive the following error (noted below in the code)

"Unable to create a constant value of type 'vps_intranet.Models.Part'. Only primitive types or enumeration types are supported in this context."

PartsController.cs

private List<Part> partsNotPartOfStructure(int partID)
{
    Part mainPart = db.Parts.Find(partID);
    //var alreadySelected = db.Parts.Select(p => p.PartStructures_comp).Distinct();
    List<Part> parts = new List<Part>();

    List<PartStructures> excludeList = db.PartStructures1
        .Where(p => p.mainPart_id == partID).ToList();

    parts = db.Parts.Where(c => c.PartStructures_comp
        .Except((List<PartStructures>) excludeList)).ToList();
    //The line above gives the error...
    //Unable to create a constant value of type 'vps_intranet.Models.Part'.
    //Only primitive types or enumeration types are supported in this context.**

    return parts;
}

public async Task<ActionResult> Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Part part = await db.Parts.FindAsync(id);
    if (part == null)
    {
        return HttpNotFound();
    }
    ViewData["AvailableParts"] = partsNotPartOfStructure(id.Value);
    return View(part);
}

Details.cshtml

@model vps_intranet.Models.Part

@{ 
    var fullList = (IEnumerable< vps_intranet.Models.Part >) ViewData["AvailableParts"];
    var availableParts = fullList.Select(p => new SelectListItem { Text = p.partNo.ToString(), Value = p.id });
}

...

@Html.DropDownListFor(model => model.PartStructures_comp, availableParts));

What do I need to change?

Upvotes: 0

Views: 77

Answers (2)

Shyju
Shyju

Reputation: 218722

You are passing in a list of PartStructures class objects to the Except method. Except method uses the default equality comparer to compare the values.

If you are passing a custom class (not a simple value type like int) , You should implement IEqualityComparer<T> interface methods such as Equals and GetHashCode.

If you do not prefer to do that, You can get the Ids of your PartStructures collection and use that with the Contains method.

var excludeIdList = db.PartStructures1.Where(p => p.mainPart_id == partID)
                      .Select(g=>g.Id).ToList();

var parts = db.Parts
          .Where(c => !c.PartStructures_comp.Any(g=>excludeIdList.Contains(g.Id)))
          .ToList();

Upvotes: 1

Luis Lavieri
Luis Lavieri

Reputation: 4109

You are trying to use an Exclude between two different data types. You have the Part class and then the List<PartStructure>. Do it by parts. First, get the parts. Then, cast it to the list of part structures and then do the exclude.

You have to implement IEqualityComparer<T>

Taken from: this post.

public class Compare : IEqualityComparer<Part>
{
    public bool Equals(Part x, Part y)
    {
        return x.SomeProperty == y.SomeProperty;
    }
    public int GetHashCode(Part part)
    {
        return part.SomeProperty.GetHashCode();
    }
}

This way you could do

var parts = db.Parts.Exclude(someList, new Compare());

Upvotes: 0

Related Questions