2011-06-20 72 views
0

this question开始,我使用一个简单的ViewModel类来测试将强类型模型传递给视图。虽然Darin对我原来的问题的回答已经解决了我所遇到的问题,但现在让我挠头,为什么我不能用EF生成的课程做同样的事情。下面是我有:MVC 3:使用EF生成的类作为强类型模型

public ActionResult Test() 
{ 
    using (MyEntities db = new MyEntities()) 
    { 
     var model = from c in db.Categories 
        select new CategoryViewModel { CategoryID = c.CategoryID, Name = c.Name }; 

     return View(model.ToList()); 
    } 
} 

这是CategoryViewModel:

public class CategoryViewModel 
{ 
    public int CategoryID { get; set; } 
    public string Name { get; set; } 
} 

在我看来,我只是foreaching在模型。这产生了期望的结果。然而,EF为我生成的一个类是Category。我最初是想用它来构建强类型的模型,并传递给视图,而不是像这样:

public ActionResult Test() 
{ 
    using (MyEntities db = new MyEntities()) 
    { 
     var model = from c in db.Categories 
        select new Category { CategoryID = c.CategoryID, Name = c.Name }; 

     return View(model.ToList()); 
    } 
} 

这是给我下面的错误:

“的实体或复杂类型'MyProjectModel.Category'不能在LINQ to Entities查询中构建。“

所以我的问题是,CategoryViewModel和Category之外的区别是为我生成的区别是什么?什么阻止我在这种情况下使用Category作为我的模型类型?我一直在关注今天的其他问题(和答案),但我一直无法找到讨论这个问题的东西。我还看到了那些帖子中提到的其他一些新术语(buddy classes,automappers,POCO),但在不了解我的问题基础的情况下查看它们的内容似乎为时过早。

我真的很感谢一些见解。

回答

1

虽然我不知道为什么我敢打赌,实体框架不喜欢在您正在编写查询的属性中选择相同类型的new对象。如果我的假设是正确下面的代码应该是等同于你正在尝试做的事:

public ActionResult Test() 
{ 
    using (MyEntities db = new MyEntities()) 
    { 
     var model = from c in db.Categories; 

     return View(model.ToList()); 
    } 
} 

你只需要在你映射的上下文的类的属性,另一个类选择新的对象(即不一个由EF生成)。

我做多一点研究的问题,其中包括复制它自己,根据堆栈跟踪这就是异常被抛出:System.Data.Objects.ELinq.ExpressionConverter.CheckInitializerType(Type type) 下面是CheckInitializerType的源代码(found here):

// Determines whether the given type is supported for materialization 
    private void CheckInitializerType(Type type) 
    { 
     // nominal types are not supported 
     TypeUsage typeUsage; 
     if (_funcletizer.RootContext.Perspective.TryGetType(type, out typeUsage)) 
     { 
       BuiltInTypeKind typeKind = typeUsage.EdmType.BuiltInTypeKind; 
       if (BuiltInTypeKind.EntityType == typeKind || 
        BuiltInTypeKind.ComplexType == typeKind) 
       { 
        throw EntityUtil.NotSupported(System.Data.Entity.Strings.ELinq_UnsupportedNominalType(
          typeUsage.EdmType.FullName)); 
       } 
     } 

     // types implementing IEnumerable are not supported 
     if (TypeSystem.IsSequenceType(type)) 
     { 
      throw EntityUtil.NotSupported(System.Data.Entity.Strings.ELinq_UnsupportedEnumerableType(
         DescribeClrType(type))); 
     } 
    } 

由于我尚未确定的原因,如果您尝试投影属性的对象具有BuiltInTypeKindEntityTypeComplexType,则不支持投影。通过我的测试,我发现我可以将属性投影到由另一个edmx文件生成的实体上,因此与给定ObjectContext的关系似乎归结为装饰生成的实体类的System.Data.Objects.DataClasses.EdmEntityTypeAttribute

+0

嗨Nathan,这确实有效,但它从表中检索所有数据。我想要的是,虽然我的示例没有显示这一点,但只需选择几列并返回它们的数据。我有一个很大的Articles表,里面有很多字段,有时我只需要几个字段。我不想从数据库中提取不必要的数据。我使用分类表作为一个简单的测试。:) –

+0

我想我明白你想要做什么,但看起来问题的症结在于仍然选择由EF生成的新对象。如果你只需要几列,你可能最好使用另一个类,而只使用你关心的那些属性(或者至少只是将它限制在你感兴趣的对象中,比如var model = from db in db。类别where c.IsActive select c;' - 至少那会返回符合条件的行。 –

+0

Thanks Nathan。对于慢速回复感到抱歉,我很感谢你的回答和评论,但我不愿意接受你的回答,因为它仍然没有告诉我为什么会出现这种情况 –