3

I'm trying to make the same thing like in this thread, but I'm getting error:

'System.Collections.Generic.IEnumerable' does not contain a definition for 'Add' and no extension method 'Add' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?)

Here is my code:

[HttpPost]
public ActionResult Create(ANIME anime)
{
    var db = new MainDatabaseEntities();
    var newanime = new ANIME
    {
        ID_AN = anime.ID_AN,
        TITLE_OR = anime.TITLE_OR,
        TITLE_EN = anime.TITLE_EN,
        GENRES = new List<GENRES>()
    };

    foreach (var selectedAnime in anime.GENRES.Where(c => c.isSelected))
    {
        var genre = new GENRES { ID_GE = selectedAnime.ID_GE };
        db.GENRES.Attach(genre);
        newanime.GENRES.Add(genre); <--- this is the error line
    }

    db.ANIME.Add(newanime);
    db.SaveChanges();
    return RedirectToAction("Index");
}

ANIME:

public partial class ANIME
{
    public int ID_AN { get; set; }
    public string TITLE_OR { get; set; }
    public string TITLE_EN { get; set; }

    public virtual IEnumerable<GENRES> GENRES { get; set; }
}

GENRES:

public partial class GENRES
{
    public int ID_GE { get; set; }
    public string GENRE { get; set; }
    public bool isSelected { get; set; }
    public virtual ICollection<ANIME> ANIME { get; set; }
}

The error is in the line newanime.GENRES.Add(genre) in HttpPost. I added using System.Linq to all models and controllers but it doesn't help. Any ideas how to resolve this?

EDIT:

After repairing this a new error arrived. I think it's not related to above one but I don't want to spam unnecessary threads.

Error message:

The entity or complex type 'MainDatabaseModel.GENRES' cannot be constructed in a LINQ to Entities query.

Related code:

public ActionResult Create()
{
    var db = new MainDatabaseEntities();
    var viewModel = new ANIME
    {
        GENRES = db.GENRES.Select(c => new GENRES
        {
            ID_GE = c.ID_GE,
            GENRE = c.GENRE,
            isSelected = false
        }).ToList()
    };
    return View(viewModel);       
}
Community
  • 1
  • 1
Placek
  • 699
  • 2
  • 7
  • 10
  • this post explain more your issue http://stackoverflow.com/questions/1210295/how-can-i-add-an-item-to-a-ienumerablet-collection – BRAHIM Kamel Dec 02 '13 at 11:25
  • @Satpal: there is no `.Add` method in `Linq` either; `IEnumerable`s cannot be modified. – Dan Puzey Dec 02 '13 at 11:25
  • The question you link to uses the `IEnumerable` for a _view model_. You are using your _Entity Framework entities_ as view models (about which I warned you on an earlier question), you cannot apply that logic as models [require `ICollection` for navigation properties that are one-to-many relations](http://stackoverflow.com/questions/2866881/why-does-the-entity-framework-need-an-icollection-for-lazy-loading). Just change `IEnumerable` to `ICollection`. – CodeCaster Dec 02 '13 at 11:31
  • If I can ask, why the odd naming conventions on your properties/classes? In C#, we use Pascal Case for properties, methods and types, and we use camelCase for fields (which are generally not exposed) – Dan Dec 02 '13 at 11:44

4 Answers4

13

You have an IEnumerable property that you're initialising with a List. The List class implements the IEnumerable interface.

When you are invoking something like this:

IEnumerable myList = new List<MyType>();

you're saying that you want for your object the features of the IEnumerable interface that are also inherited from the List class. In this case, the method Add isn't part of the IEnumerable interface, because it's a method of the List class only, and you have that exception.

You have then to change the type of your property, from IEnumerable<YourType> to IList<YourType> (more info about IList here). If you do so, the exception about Add method won't be thrown.

Alberto Solano
  • 7,972
  • 3
  • 38
  • 61
6

Try this:

public partial class ANIME
{

    public int ID_AN { get; set; }
    public string TITLE_OR { get; set; }
    public string TITLE_EN { get; set; }

    public virtual ICollection<GENRES> GENRES { get; set; } // Use ICollection here
}
Aleksei Poliakov
  • 1,322
  • 1
  • 14
  • 27
  • Ok, it helped... I had it at the beginning but I changed to IEnumerable because I had some problem with toList() but now it all works. Hmm weird, thanks for help. – Placek Dec 02 '13 at 11:28
  • What was your issue with `ToList()`? – Dan Dec 02 '13 at 11:30
  • @Placek ICollection is more 'rich' interface than IEnumerable. Check out this question for details: http://stackoverflow.com/questions/10113244/why-use-icollection-and-not-ienumerable-or-listt-on-many-many-one-many-relatio – Aleksei Poliakov Dec 02 '13 at 11:35
  • New error arrived after repairing this one ;_;. See EDIT in first post. – Placek Dec 02 '13 at 11:41
  • @Placek your really need to make a new post - because new answer is quite long. Short answer: you can not construct GENRE in linq to entities, you need to project it to anonymous type and only then construct GENRE objects (by this type you are already in linq to objects). The code: GENRES = db.GENRES.Select(c => new{ ID_GE = c.ID_GE,GENRE = c.GENRE,isSelected = false }).ToList().Select(g => new GENRE {......}).ToList() – Aleksei Poliakov Dec 02 '13 at 11:44
  • I think this is occurring mainly because he has no ID (by convention!) in GENRES, rather than because you need a proxy type. I do what he has done several times in my code just fine. `field = db.Type.Select(dbType => new fieldType() { ... }).ToList()` will work just fine. EDIT: woops! no this will not work in linq-to-sql, only in linq-to-objects. – Dan Dec 02 '13 at 11:47
  • @DarkWalker The short version of your answer was enough. Thank you very much. I'm setting answer and closing this topic cause I was scolded by CMate ;). – Placek Dec 02 '13 at 11:55
1

IEnumerable<> is just a sequence of items. You can't add items to it and you can't remove items from it. You can query it.

If you need to add items, you will need a collection implementing at least the ICollection<> interface or IList<> interface.

Good news is that you can use IEnumerable<> there like as follows

var list = new List<GENRES>();
var newanime = new ANIME
{
    ID_AN = anime.ID_AN,
    TITLE_OR = anime.TITLE_OR,
    TITLE_EN = anime.TITLE_EN,
    GENRES = list
};

list.Add(genre);

But this has limited possibilities. You won't be able to add new items once you leave the scope and loose a reference to the local list variable.

Ondrej Janacek
  • 12,486
  • 14
  • 59
  • 93
1

The answer for your second question is that you cannot (and should not be able to) project onto a mapped entity. You can, however, project onto an annonymous type or on data transfer object.

See this thread: The entity cannot be constructed in a LINQ to Entities query

Also, please do not extend your initial question with a totally new, unrealted one in the future. It makes it hard to follow...

Community
  • 1
  • 1
mcserep
  • 3,231
  • 21
  • 36