找不到 EntityType 异常的映射和元数据信息
我正在尝试使用 Microsoft Entity Framework 来使用 ASP.NET MVC Framework 2,当我尝试保存新记录时,出现此错误:
找不到 EntityType 'WebUI.Controllers.PersonViewModel' 的映射和元数据信息
我的实体框架容器存储 Person 类型的记录,并且我的视图使用派生于 Person 的类 PersonViewModel 进行强类型化。记录将正确保存,直到我尝试使用派生视图模型类。谁能解释为什么当我派生视图模型时元数据类不起作用?我希望能够使用强类型模型并使用数据注释(元数据),而无需混合存储逻辑(EF 类)和表示逻辑(视图)。
// Rest of the Person class is autogenerated by the EF
[MetadataType(typeof(Person.Metadata))]
public partial class Person
{
public sealed class Metadata
{
[DisplayName("First Name")]
[Required(ErrorMessage = "Field [First Name] is required")]
public object FirstName { get; set; }
[DisplayName("Middle Name")]
public object MiddleName { get; set; }
[DisplayName("Last Name")]
[Required(ErrorMessage = "Field [Last Name] is required")]
public object LastName { get; set; }
}
}
// From the View (PersonCreate.aspx)
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<WebUI.Controllers.PersonViewModel>" %>
// From PersonController.cs
public class PersonViewModel : Person
{
public List<SelectListItem> TitleList { get; set; }
} // end class PersonViewModel
更新:这是堆栈跟踪:
[InvalidOperationException: Mapping and metadata information could not be found for EntityType 'WebUI.Controllers.PersonViewModel'.] System.Data.Objects.ObjectContext.GetTypeUsage(Type entityCLRType) +11531168 System.Data.Objects.ObjectContext.VerifyRootForAdd(Boolean doAttach, String entitySetName, IEntityWrapper wrappedEntity, EntityEntry existingEntry, EntitySet& entitySet, Boolean& isNoOperation) +195 System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity) +243 DomainModel.Entities.MyEntities.AddToPeople(Person person) in C:\Users\...\Documents\Visual Studio 2010\Projects\PersonWeb\DomainModel\Entities\MyEntities.Designer.cs:71 DomainModel.Concrete.Repository.SavePerson(Person person) in C:\Users\...\Documents\Visual Studio 2010\Projects\PersonWeb\DomainModel\Concrete\Repository.cs:42 WebUI.Controllers.PersonController.Create(FormCollection form, Int32 hidCancel) in C:\Users\...\Documents\Visual Studio 2010\Projects\PersonWeb\WebUI\Controllers\PersonController.cs:163 lambda_method(Closure , ControllerBase , Object[] ) +165 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +258 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +39 System.Web.Mvc.c__DisplayClassd.b__a() +125 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +640 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +312 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +709 System.Web.Mvc.Controller.ExecuteCore() +162 System.Web.Mvc.c__DisplayClass8.b__4() +58 System.Web.Mvc.Async.c__DisplayClass1.b__0() +20 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +453 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +371
I am trying out ASP.NET MVC Framework 2 with the Microsoft Entity Framework and when I try and save new records I get this error:
Mapping and metadata information could not be found for EntityType 'WebUI.Controllers.PersonViewModel'
My Entity Framework container stores records of type Person and my view is strongly typed with class PersonViewModel which derives from Person. Records would save properly until I tried to use the derived view model class. Can anyone explain why the metadata class doesnt work when I derive my view model? I want to be able to use a strongly typed model and also use data annotations (metadata) without resorting to mixing my storage logic (EF classes) and presentation logic (views).
// Rest of the Person class is autogenerated by the EF
[MetadataType(typeof(Person.Metadata))]
public partial class Person
{
public sealed class Metadata
{
[DisplayName("First Name")]
[Required(ErrorMessage = "Field [First Name] is required")]
public object FirstName { get; set; }
[DisplayName("Middle Name")]
public object MiddleName { get; set; }
[DisplayName("Last Name")]
[Required(ErrorMessage = "Field [Last Name] is required")]
public object LastName { get; set; }
}
}
// From the View (PersonCreate.aspx)
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<WebUI.Controllers.PersonViewModel>" %>
// From PersonController.cs
public class PersonViewModel : Person
{
public List<SelectListItem> TitleList { get; set; }
} // end class PersonViewModel
Update: here is the stack trace:
[InvalidOperationException: Mapping and metadata information could not be found for EntityType 'WebUI.Controllers.PersonViewModel'.] System.Data.Objects.ObjectContext.GetTypeUsage(Type entityCLRType) +11531168 System.Data.Objects.ObjectContext.VerifyRootForAdd(Boolean doAttach, String entitySetName, IEntityWrapper wrappedEntity, EntityEntry existingEntry, EntitySet& entitySet, Boolean& isNoOperation) +195 System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity) +243 DomainModel.Entities.MyEntities.AddToPeople(Person person) in C:\Users\...\Documents\Visual Studio 2010\Projects\PersonWeb\DomainModel\Entities\MyEntities.Designer.cs:71 DomainModel.Concrete.Repository.SavePerson(Person person) in C:\Users\...\Documents\Visual Studio 2010\Projects\PersonWeb\DomainModel\Concrete\Repository.cs:42 WebUI.Controllers.PersonController.Create(FormCollection form, Int32 hidCancel) in C:\Users\...\Documents\Visual Studio 2010\Projects\PersonWeb\WebUI\Controllers\PersonController.cs:163 lambda_method(Closure , ControllerBase , Object[] ) +165 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +258 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +39 System.Web.Mvc.c__DisplayClassd.b__a() +125 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +640 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +312 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +709 System.Web.Mvc.Controller.ExecuteCore() +162 System.Web.Mvc.c__DisplayClass8.b__4() +58 System.Web.Mvc.Async.c__DisplayClass1.b__0() +20 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +453 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +371
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我刚刚遇到了类似的问题(搜索异常导致我来到这里),使用 MVC3,对我来说,这是因为我移动了我的 edmx 文件,并且它对 EdmEntityTypeAttribute 的名称空间属性应该在哪里感到困惑指点一下。
我创建了一个与您所描述的结构类似的结构,其中我有一个从实体类型派生的模型类,并且我再次遇到了相同的错误。如果我将 EdmEntityTypeAttribute 从实体类型复制到派生类,那么问题就会消失(至少对于写入而言,在读取时会遇到不同的问题)。这让我相信框架可能正在使用反射来询问传递给 add 方法的类,以确定存在哪些属性,但仅限于实际类型(继承树被忽略)。
我考虑过这一点,如果您考虑从数据库流回的数据,它实际上是有意义的。如果您要取回“Person”对象的列表,框架将需要决定创建哪个类并从表中填充,并且它不知道您的派生模型类,因此需要创建基类。充其量,这意味着您使用原始实体类型进行读取并使用模型类型进行写入与存储进行交互,这似乎会让人感到困惑。
在生成的实体类型中使用分部类允许您在需要时扩展它们,或者如果您想显式分离实体和模型类型,则可能需要某种对象映射。
当然,我仍在了解实体框架,因此很可能还有另一种方法来解决该问题。我认为到目前为止,您已经找到了适合您的解决方案。
I've just had a similar problem (a search for the exception lead me here), with MVC3, which for me turned out to be because I had moved my edmx file and it had got confused about where the namespace attribute of the EdmEntityTypeAttribute should be pointing.
I create a structure similar to the one you've described, whereby I had a model class that derived from an entity type and again, I got the same error. If I copy the EdmEntityTypeAttribute from the entity type to the derived class then the problem goes away (at least for writing, you get a different problem on reading). This leads me to believe that the framework is probably using reflection to interrogate the class passed into the add method, to determine what attributes are present, but only on the actual type (inheritence tree is ignored).
I thought about this and it actually makes a bit of sense if you think about data flowing back from the database. If you were to fetch back a list of 'Person' objects, the framework would need to decide what class to create to and populate from the table and it doesn't know about your derived Model class so it will need to make the base class. At best, this would mean that you're interacting with the storage using raw entity types for reading and model types for writing, which seems like it would get confusing.
The use of partial classes in the generated entity types allows you to extend them if you need to, or if you want to explicitly separate the entity and model types, then some kind of object mapping may be required.
Of course, I'm still getting to know the entity framework, so there may well be another way around the problem. I assume by this point, you've already found a solution that's working for you.
对我来说,这是一个简单的问题,当 *.edmx 文件中的值是 UserAccounts 时,我错误地调用了数据库中的表 UserAccount。 HTH。
For me it was a simple problem where I had called my table UserAccount in my database by mistake when the value in the *.edmx file was UserAccounts. HTH.