新接触ASP.NET MVC5(这个说法准确?),采用vs2015,发现困难好多,以前只接触过HTML、ASP。
现在准备用MVC5做个小系统,发现了多个问题,本文说明数据库的问题之一:
EntityType“TbFun”未定义键。请为该 EntityType 定义键
我有一张表:
TbFun,只有两个字段,定义如下:
CREATE TABLE [dbo].[TbFuns] (
[FunId] INT IDENTITY (0, 1) NOT NULL,
[FunName] NVARCHAR (50) NOT NULL,
CONSTRAINT [PK_dbo.TbFuns] PRIMARY KEY CLUSTERED ([FunId] ASC)
);
其中的FunId为整数主键,自动增长
定义它的模型:
public class TbFun
{
public int FunId { get; set; }
public string FunName { get; set; }
}
定义数据库操作模型:
public class fwDatabase : DbContext
{
public fwDatabase() : base("fwDB")
{
}
public DbSet<TbFun> TbFuns { get; set; }
... // 这是其它的表
}
连接字符串为 fwDB。
在一个Controller中,我要加载数据:
public class FileController : Controller
{
private fwDatabase m_db = new fwDatabase();
int m_funIndex;
string m_strFunName = "";
public ActionResult Index()
{
var defFunInfo = m_db.TbFuns.Single(tb => tb.FunId == 1);
m_funIndex = defFunInfo.FunId;
m_strFunName = defFunInfo.FunName;
return View();
}
... // 其它动作
}
在这个 Index() 中,第一行从这个表中搜索一条记录出来(这条记录是我自己通过表加进去的,它一定存在),结果总是提示标题中的错误:
EntityType“TbFun”未定义键。请为该 EntityType 定义键
这就奇怪了,我看了很多遍,度娘了好多次,大家的一致说法就是在前面加上 [Key] ,如下:
public class TbFun
{
[Key]
public int FunId { get; set; }
public string FunName { get; set; }
}
但是所有人都没有说明是为啥。
我重新建立一个工程,选项和当前的项目一样,建立完之后,参考:
https://www.cnblogs.com/sanshi/p/6210695.html
中的“数据库操作”一节,在完成后,检查Students的模型定义,它前面它的 ID 前是没有 [Key] 关键字的,表的定义,除了字段数量和字段名称不一样,主键的属性也都完全一样,但它是可以正常运行的,我也通过页面添加了一条记录进去,而且也可以通过页面显示出来,这就更奇怪了。
通过反复对比,终于发现一个了一个区别,就是Students表的主键字段名称为 ID,而我的表的主键字段名称为 FunId,难道是这个不一样导致的?
我把Students的模型以及相关代码中的 ID,改成了 StuId(这和我表中的主键字段名称形式上也一样了),然后再调试。这次到了
return View(m_db.Students.ToList());
这一行时,果然出现了标题中的错误提示!
“System.Data.Entity.ModelConfiguration.ModelValidationException”类型的异常在 EntityFramework.dll 中发生,但未在用户代码中进行处理
其他信息: 模型生成过程中检测到一个或多个验证错误:
TestData.Models.Student: : EntityType“Student”未定义键。请为该 EntityType 定义键。
Students: EntityType: EntitySet“Students”基于未定义任何键的类型“Student”。
再看看ie页面上的显示:
“/”应用程序中的服务器错误。
模型生成过程中检测到一个或多个验证错误:
TestData.Models.Student: : EntityType“Student”未定义键。请为该 EntityType 定义键。
Students: EntityType: EntitySet“Students”基于未定义任何键的类型“Student”。
说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.Entity.ModelConfiguration.ModelValidationException: 模型生成过程中检测到一个或多个验证错误:
TestData.Models.Student: : EntityType“Student”未定义键。请为该 EntityType 定义键。
Students: EntityType: EntitySet“Students”基于未定义任何键的类型“Student”。
源错误:
行 18: public ActionResult Index()
行 19: {
行 20: return View(m_db.Students.ToList());
行 21: }
行 22:
源文件: Q:\exp\asp.net\TestData\TestData\Controllers\StudentsController.cs 行: 20
这个错误不多贴一次心里不爽,困了我好久,现在终于复现了它!
这样,大概明白了是怎么回事。
对于MVC,它并不知道表模型中的哪个字段是主键,但是它又要求必需有一个主键,所以,要么这个主键字段名称必需为 ID,要么就指定哪个字段是主键。现在既然我的表中没有名称为 ID 的这个字段,所以就必需把另外一个整形字段 FunId 指定为主键
public class TbFun
{
[Key]
public int FunId { get; set; }
public string FunName { get; set; }
}
好了,像上面这样,添加 [Key] 之后,这个问题解决!
不过还是有一点疑问:学习的站点 mvcmusicstore 的表模型定义中,其主键字段的名称不是 ID,但是在模型定义中,也没有 [Key] 关键字,它为啥就能正常工作(下载的代码我没有尝试运行,所以我不确定在我这里是否可以正常运行,它也许是vs2013的工程---因为我用vs2015打开时,提示工程版本将升级,可能是vs2013的工程中不需要这个 [Key] 关键字吧)?