0

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?

Geoff James
  • 3,122
  • 1
  • 17
  • 36
Beengie
  • 1,588
  • 4
  • 18
  • 36
  • 1
    Does [this](http://stackoverflow.com/questions/18929483/unable-to-create-a-constant-value-of-type-only-primitive-types-or-enumeration-ty) help? – Grizzly Aug 18 '16 at 18:43
  • 1
    You are trying to use an `Exclude` between two different data types. You have the `Part` class and then the `List`. Do it by parts. First, get the parts. Then, cast it to the list of part structures and then do the exclude – Luis Lavieri Aug 18 '16 at 18:46
  • 1
    You might want to look at [DropDownList in ASP.Net MVC](http://stackoverflow.com/questions/37818949/best-programming-practice-of-using-dropdownlist-in-asp-net-mvc/37819577#37819577) – Win Aug 18 '16 at 19:13

2 Answers2

1

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();
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Thanks for the help. I understand better what I was doing wrong. However, the result is the parts in the exclusion list and not the rest of the list. I tried using Except but I got an error. Obviously I have a bit to learn. How would you implement the Except clause in place of the contains? – Beengie Aug 18 '16 at 19:08
  • As i explained in the answer, If you want to use Except, you need to implement `Equals` and `GetHashCode` methods. What is wrong with the solution i posted ? It should give you all the parts which does not have PartStructures_comp with Ids same as ids in the exlucdeIdList variable. – Shyju Aug 18 '16 at 19:11
  • I implemented your fix before you added the ""== false" and it returned the records included. After putting in the "==false", it returns no records. – Beengie Aug 18 '16 at 19:16
  • Sorry ! The linq code was wrong. I fixed it now (the second line). Let me know if that does not work – Shyju Aug 18 '16 at 19:28
0

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());
Community
  • 1
  • 1
Luis Lavieri
  • 4,064
  • 6
  • 39
  • 69