MVC 3:使用EF生成的类作为强类型模型

本文关键字:强类型 模型 使用 EF MVC | 更新日期: 2023-09-27 18:00:00

根据这个问题,我将使用一个简单的ViewModel类来测试将强类型模型传递到视图。虽然Darin对我最初问题的回答解决了我的问题,但现在让我挠头,为什么我不能对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());
    }
}

这是类别ViewModel:

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

在我看来,我只是对模型做了一些预测。这将产生所需的结果。然而,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());
    }
}

这给了我以下错误:

"无法在LINQ to Entities查询中构造实体或复杂类型"MyProjectModel.Category"。"

所以我的问题是,CategoryViewModel和为我生成的Category之外的Category之间有什么区别?是什么阻止我在这种情况下使用Category作为我的模型类型?我今天一直在看SO上的其他问题(和答案),但我找不到讨论这个问题的内容。我也在这些帖子中看到了其他一些新术语(伙伴类、自动映射器、POCO),但在不了解我问题的基础的情况下研究它们似乎为时过早。

我真的很感激你的真知灼见。

MVC 3:使用EF生成的类作为强类型模型

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

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

当您将上下文类的属性映射到另一个类(IE而不是EF生成的类)时,您只需要选择新对象。

我对这个问题做了更多的研究,包括自己复制它,根据堆栈跟踪,这就是抛出异常的地方:System.Data.Objects.ELinq.ExpressionConverter.CheckInitializerType(Type type)以下是CheckInitializerType的源代码(可在此处找到):

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

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