不包含“Add”的定义。

3
我正在尝试做和这个主题中相同的事情,但是我遇到了错误:

'System.Collections.Generic.IEnumerable'不包含定义为“Add”的方法,也没有接受类型为“System.Collections.Generic.IEnumerable”的第一个参数的扩展方法“Add”(是否缺少使用指令或程序集引用?)

这是我的代码:

[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");
}

动漫:

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; }
}

类型:

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; }
}

错误出现在HttpPost中的newanime.GENRES.Add(genre)这一行。我已经在所有的模型和控制器中添加了using System.Linq,但是没有起到作用。有什么想法可以解决这个问题吗?
编辑:
修复这个错误后,又出现了一个新的错误。我认为这与上面的错误无关,但我不想发送无关的贴子。
错误信息:

不能在LINQ to Entities查询中构建实体或复杂类型'MainDatabaseModel.GENRES'。

相关代码:
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);       
}

这篇帖子更详细地解释了你的问题 https://dev59.com/ZHM_5IYBdhLWcg3w1G2N - BRAHIM Kamel
@Satpal:在Linq中也没有.Add方法;IEnumerable是不可修改的。 - Dan Puzey
你链接的问题使用 IEnumerable 作为 _视图模型_。你正在使用你的 Entity Framework 实体 作为视图模型(我在之前的一个问题中警告过你),你不能将那个逻辑应用于模型,因为需要 ICollection 来导航属性是一对多关系的模型。只需将 IEnumerable<T> 更改为 ICollection<T> 即可。 - CodeCaster
如果我可以问一下,为什么你的属性/类使用奇怪的命名约定?在C#中,我们使用Pascal Case来表示属性、方法和类型,而对于字段(通常不公开),我们使用camelCase。 - Dan
4个回答

13

您有一个IEnumerable属性,您正在使用List进行初始化。List类实现了IEnumerable接口。

当您调用以下内容时:

IEnumerable myList = new List<MyType>();

你的意思是你想让你的对象具有从List类继承而来的IEnumerable接口的特性。在这种情况下,方法Add不是IEnumerable接口的一部分,因为它只是List类的一个方法,所以你会遇到这个异常。

那么你需要改变你属性的类型,从IEnumerable<YourType>改为IList<YourType>(关于IList的更多信息在这里)。如果你这样做,就不会出现关于Add方法的异常了。


6

试试这个:

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
}

好的,它有帮助......我一开始就有它,但我改成了IEnumerable,因为我在使用toList()时遇到了一些问题,但现在都可以正常工作了。嗯,奇怪,谢谢你的帮助。 - Placek
@Placek ICollection<T> 比 IEnumerable<T> 更为“丰富”的接口。有关详细信息,请查看此问题:https://dev59.com/C2kw5IYBdhLWcg3wJHGF - Aleksei Poliakov
修复了这个错误后,又出现了新的错误;_;。请查看第一篇帖子中的编辑。 - Placek
@Placek,你真的需要发布一篇新文章——因为新答案相当长。简短回答:你无法在Linq to Entities中构造GENRE,你需要将其投影到匿名类型,然后才能构造GENRE对象(通过此类型,您已经在Linq to Objects中)。代码:GENRES = db.GENRES.Select(c => new{ ID_GE = c.ID_GE,GENRE = c.GENRE,isSelected = false }).ToList().Select(g => new GENRE {......}).ToList() - Aleksei Poliakov
我认为这主要是因为在GENRES中他没有ID(按照惯例!),而不是因为你需要代理类型。我在我的代码中已经多次成功地做了他所做的事情。field = db.Type.Select(dbType => new fieldType() { ... }).ToList()将完美地工作。编辑:哎呀!不好意思!这在linq-to-sql中行不通,只能在linq-to-objects中使用。 - Dan
显示剩余2条评论

2

IEnumerable<>只是一个项目序列。您不能向其中添加项目,也不能从中删除项目。您可以查询它。

如果您需要添加项目,则需要实现至少ICollection<>接口或IList<>接口的集合。

好消息是,您可以像下面这样使用IEnumerable<>

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);

但这具有限制性。一旦您离开作用域并且失去对本地list变量的引用,就无法添加新项目。


1
你的第二个问题的答案是,你不能(也不应该能够)将投影映射到已映射的实体上。但是,你可以将其投影到匿名类型或数据传输对象上。请参见此线程:在LINQ to Entities查询中无法构造实体。另外,请不要在未来用一个完全不相关的新问题扩展你的初始问题。这会使跟进变得困难...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接