解决EF Code First列名 'Discriminator' 无效的问题

解决EF Code First列名 'Discriminator' 无效的问题

10857发表于2016-01-08

今天在项目中加了一个类继承了EF的Model,但是莫名的出现了列名 'Discriminator' 无效的问题。

“/”应用程序中的服务器错误。
列名 'Discriminator' 无效。
列名 'Discriminator' 无效。
列名 'Discriminator' 无效。
列名 'Avatar' 无效。
列名 'LoginName' 无效。
列名 'Name' 无效。
列名 'ChildrenCount' 无效。
列名 'Article_ID' 无效。
说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

异常详细信息: System.Data.SqlClient.SqlException: 列名 'Discriminator' 无效。
列名 'Discriminator' 无效。
列名 'Discriminator' 无效。


我的类定义如下:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.linq;
using System.Text;
using System.Threading.Tasks;

namespace lanhuCMS.Models.View
{
    public class Comment : MComment
    {
        public string Avatar { get; set; }
        public string LoginName { get; set; }
        public string Name { get; set; }

        public int ChildrenCount { get; set; }
    }
}

后来才知道code first的POCO实体对象的继承问题,EF会把项目中在DbContext中引用的所有的Model类及这些Model类对应的子类都生成对应映射视图。如果数据库没有对应表或字段就会报错。EF的映射视图其实是一个xml的文件,默认是在第一个EF查询时动态生成这个映射,然后把它缓存起来以提高EF的查询性能。

上面竟然报列名 'Discriminator' 无效。那么我们就去映射视图看看这个报错的Discriminator列出现在什么地方?

从上图可以看到上面的sql语句,终于找到Discriminator的出处了。

我们可以看到上面都是一些sql语句,当我们要访问对应的实体时,EF会先去到这个映射视图里面找到对应的sql语句。我定义了Model实体类,EF会默认把它当成数据库中的一个表,然后生成映射中的一个结点。我建的类Comment在数据库中不存在,当然要报错了。

解决办法:只需要在类前面加上[NotMapped],表示应从数据库映射中排除属性或类。修改后的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace lanhuCMS.Models.View
{
    [NotMapped]
    public class Comment : MComment
    {
        public string Avatar { get; set; }
        public string LoginName { get; set; }
        public string Name { get; set; }

        public int ChildrenCount { get; set; }
    }
}
补充:为了提高的的程序性能,对一些不是数据库中的实体类最好都加上NotMapped。这样避免EF在生成映射时把这个类包含进去。刚才有提到[NotMapped],表示从数据库映射中排除类。当我们要排除一个字段是也可以在其前面加一上[NotMapped]。


小编蓝狐