2013-08-06 23 views
0

我在改写这个问题:模型计数= null

我有2个模型。入口和主题。

public class Entry 
{ 
    public int EntryId { get; set; } 
    public int UserId { get; set; } 
    public int TopicId { get; set; } 

    public String EntryQuestion { get; set; } 
    public String EntryAnswer { get; set; } 
    public int EntryReview { get; set; } 
    public String QuestionValidationURL { get; set; } 

    public virtual ICollection<Topic> TopicList { get; set; } 
} 

public class Topic 
{ 
    public int TopicId { get; set; } 
    public String TopicName { get; set; } 
} 

我跟着一个关于ASP.Net/MVC的例子来设置我的模型。 我想要做的是为每个项目我有一个TopicId,但是我想通过访问我的TopicList将其转换为TopicName。

我的问题是,我如何加载TopicList?

在下面的例子中,我看到了一些关于LazyLoading和EagerLoading的内容,但它似乎没有工作。

我试着做从我的输入控制器如下:

db.Entries.Include(x => x.TopicList).Load(); 

但是,这仍然给我的0题目列表(比空好)

我怎样才能做到这一点?

在我看来,我绑定到的条目是这样的:

@model IEnumerable<projectInterview.Models.Entry> 

我想访问这里的题目列表:

@foreach (var item in Model) { 
    <tr> 
     <td> 
      @Html.DisplayFor(modelItem => item.TopicId) 
     </td> 
     ... 
    </tr> 

我想用TopicId在这循环并显示属于集合中对象一部分的TopicName。

+0

请显示您如何绑定模型并在视图中使用它。 – Dima

+0

已更新问题 – webdad3

+0

请显示'getTopicsCount()'方法 – bazz

回答

3

我假设你正在关注一个实体框架的例子。据我所知,您正试图创建一对多的关系,但我不确定哪一端是哪一端。

在一般情况下,建立一个一对多的关系,你必须做这样的事情:

public class One 
{ 
    [Key] 
    public int Id { get; set; } 

    public virtual ICollection<Many> Many { get; set; } 
} 

public class Many 
{ 
    [Key] 
    public int Id { get; set; } 

    [ForeignKey("One")] 
    public int OneId { get; set; } 
    public virtual One One { get; set; } 
} 

如果你想要做的是有一个Entry与许多Topic对象有关,那么你几乎就在那里,但你缺乏一些东西。

对于ICollection<Topic>实际上包含任何的(多)Topic对象需要有一个外键(一个)Entry。 (它也不会伤害到明确标记两侧的主键,而不是依赖于EF约定。)

public class Topic 
{ 
    [Key] 
    public int TopicId { get; set; } 
    public String TopicName { get; set; } 

    [ForeignKey("Entry")] 
    public int EntryId { get; set; } 
    public virtual Entry Entry { get; set; } 
} 

public class Entry 
{ 
    [Key] 
    public int EntryId { get; set; } 

    public int UserId { get; set; } 
    public int TopicId { get; set; } 

    public String EntryQuestion { get; set; } 
    public String EntryAnswer { get; set; } 
    public int EntryReview { get; set; } 
    public String QuestionValidationURL { get; set; } 

    public virtual ICollection<Topic> TopicList { get; set; } 
} 

现在TopicList应该是一个实际和填充集合,而不需要做一个Include


如果,另一方面,你要一个Topic涉及许多Entry对象,那么你拥有它有点倒退。正确的方法是:

public class Topic 
{ 
    [Key] 
    public int TopicId { get; set; } 

    public String TopicName { get; set; } 

    public virtual ICollection <Entry> Entries { get; set; } 
} 

public class Entry 
{ 
    [Key] 
    public int EntryId { get; set; } 

    public int UserId { get; set; } 

    public String EntryQuestion { get; set; } 
    public String EntryAnswer { get; set; } 
    public int EntryReview { get; set; } 
    public String QuestionValidationURL { get; set; } 

    [ForeignKey("Topic")] 
    public int TopicId { get; set; } 
    public virtual Topic Topic { get; set; } 
} 

在这种情况下,你可能会或可能不是你是否希望他们加载一次全部或一个接一个按需使用db.Entries.Include(x => x.Topic)根据。不管你选择什么样的,下面的表达式应该返回正确的值:

​​
+0

@ webdad3你打算成为哪一方,哪一方是多方?我已经包括了两个例子,但如果答案太长,我可以删除错误的。 –

+0

一个入口只会有1个主题。 Topic对象是我的查找表(ID,Name)。我将TopicId传递给一个Entry对象。但是,我在想的是Entry.TopicList将是我的查找列表,所以我可以将TopicId转换为TopicName。也许这需要是一本字典(Key,ValuePair)...我是否让这个更复杂? – webdad3

+0

@ webdad3我想我得到了您的想法,但您不必这样做,因为EF的动态代理类将为您处理此问题。简而言之,如果你有一个'ForeignKey'属性设置正确的属性,那么(虚拟)导航属性将自动获取正确的实体(通过在幕后为你进行查找)。 –

0

在我看来问题是铸造。鉴于你有IEnumerable<projectInterview.Models.Entry>TopicsICollection<Topic>,这是不同类型的

+0

如何从我的Entry模型加载Topic的集合? – webdad3

+0

重写列表。你可以使用Automapper或类似的东西,如果你不想自己制作 –

0

主题= NULL的集合意味着有列表中的遍历没有话题。你如何填补他们?您的观点期望IEnumerable您如何将主题投入到条目中?

基于原来的问题,我添加了一个小的工作示例,也许它可以帮助你找到你的bug。

控制器:

public class TestController : Controller 
{ 
    public ActionResult Index() 
    { 
     var viewModel = new ViewModel() 
     { 
      Topics = new List<Topic>() 
     }; 

     viewModel.Topics.Add(new Topic() { header = "test" }); 
     viewModel.Topics.Add(new Topic() { header = "test2" }); 

     return View(viewModel); 
    } 

} 

型号:

public class ViewModel 
{ 
    public virtual ICollection<Topic> Topics { get; set; } 

    public int getCount() 
    { 
     return Topics.Count; 
    } 
} 

public class Topic 
{ 
    public string header { get; set; } 
} 

检视:

@model testProject.Models.ViewModel 
@{ 
    ViewBag.Title = "Index"; 
} 

<h2>Index</h2> 
@Model.getCount() 

@foreach(var item in Model.Topics) 
{ 
    <div>@item.header</div> 
} 

输出:

指数测试 test2

+0

谢谢你......也许我没有问正确的问题。我有2个模型。入口和主题。最初我希望Entry模型包含主题列表,以便我可以将TopicId转换为TopicName。如何从Entry模型加载Topic模型,然后如何在Entry模型中加载列表?这有任何意义吗? – webdad3

+0

我想我知道你的意思,虽然我不确定你为什么要这样做。您可以为视图模型创建复杂的模型(例如列表列表)。特别是当你创建窗体和httpposts时,模型绑定器会自动将每个列表绑定到正确的模型。这让你的生活变得更加简单:-) 但是现在你的问题是:只要我不知道Entry和Topic的外观如何,我不能直接帮你。但看看LINQ:例如:http://stackoverflow.com/questions/2445410/use-linq-and-c-sharp-to-make-a-new-list-from-an-old-list – Vulcano

+0

是有一个很好的教程,你可以推荐你建议的方式(对于视图模型)?我正在学习一些教程,也许我已经走上了轨道。再次感谢你的帮助。 – webdad3

0

看起来您并未在代码中的任何位置初始化您的Topics。如果集合为空,则表示它未初始化。如果您有

ICollection<Topic> Topics = new List<Topic>(); 

它实例初始化完成后,你应该打电话Topics.Count时收到零。如果你不打电话给数据库,它将保持为零。

你的情况检查你是否正在实例化Topics

+0

好吧,这很容易,但我会如何加载该列表?那是我可以从我的Entry模型做的事情吗? – webdad3

1

如果我理解正确的话,你已经加入主题,条目的列表只是为了显示条目时,得到的主题的名称。做到这一点的最好方法是在您的入门模型中实际拥有一个Topic属性。所以,你的模型应该是这样的:

public class Entry 
{ 
    public int EntryId { get; set; } 
    public int UserId { get; set; } 
    public int TopicId { get; set; } 
    public String EntryQuestion { get; set; } 
    public String EntryAnswer { get; set; } 
    public int EntryReview { get; set; } 
    public String QuestionValidationURL { get; set; } 
    //Change this..... 
    public virtual Topic Topic { get; set; } 
} 

然后在您的视图你可以使用(假设模型是一个IEnumerable):

@foreach (var item in Model) { 
<tr> 
    <td> 
     @Html.DisplayFor(modelItem => modelItem.Topic.TopicName) 
    </td> 
    ... 
</tr> 

此链接对如何做一个很好的例子: http://weblogs.asp.net/manavi/archive/2011/03/28/associations-in-ef-4-1-code-first-part-2-complex-types.aspx

+0

谢谢,我今晚会尝试这个。 – webdad3

+0

这就像你说的那样工作。你能告诉我我做错了什么,为什么这个工作? – webdad3

+0

当您将对象作为另一个对象中的属性时,EF会自动为您执行映射。而如果它是一个集合,即使您将它链接并正确映射,EF也会为您填充它,但不会“猜测”您将topicId与列表中的某个主题关联起来的意图。所以你必须在你的模型的某个地方建立这个逻辑。当该属性是一个对象时,EF将自动填充其所有属性,因此您将自动填入Name属性。我希望这澄清的事情,而不是让他们更加混乱:) – JTMon