【问题标题】:entity framework 4.1 invalid column name实体框架 4.1 无效的列名
【发布时间】:2015-01-17 02:08:35
【问题描述】:

我有两张表 News 和 NewsComments。我遵循命名规则

结构新闻评论

public class NewsComment : BaseComment
{
    public int NewsId { get; set; }

    public virtual News News { get; set; }      
}

但是查询返回异常无效的列名“News_Id”。我知道在表中不相关的列中创建了这个异常。

CREATE TABLE [dbo].[NewsComments](
[Id] [int] IDENTITY(1,1) NOT NULL,
[NewsId] [int] NOT NULL,
[Text] [varchar](max) NOT NULL,
[UserId] [int] NOT NULL,
[CommentDate] [datetime] NOT NULL,
[Ip] [varchar](40) NOT NULL, CONSTRAINT [PK_NewsComments] PRIMARY KEY CLUSTERED([Id] ASC )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY]

基本评论

public abstract class BaseComment : BasePersistentEntity, IComment
{

    public int UserId { get; set; }

    public virtual BaseUser User { get; set; }

    [Display(ResourceType = typeof(FrameworkResurce), Name = "CommentText")]
    public string Text { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "CommentDate")]
    public DateTime CommentDate { get; set; }


    public string Ip { get; set; }
}

新闻

public class News : BaseContent
{
    [Display(ResourceType = typeof(NewsResurce), Name = "NewsImage")]
    public string NewsImage { get; set; }

    public virtual ICollection<NewsCommentView> CommentViews { get; set; }
}

基本内容

public abstract class BaseContent : BasePersistentEntity
{
    [Display(ResourceType = typeof(FrameworkResurce), Name = "Keywords")]
    public string Keywords { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "TitleTranslit")]
    public string TitleTranslit { get; set; }

    [Required(ErrorMessageResourceType = typeof(FrameworkResurce), ErrorMessageResourceName = "IsTextEmpty")]
    [Display(ResourceType = typeof(FrameworkResurce), Name = "Title")]
    public string Title { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "Description")]
    public string Description { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "Contents")]
    public string Contents { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "DatePublish")]
    public DateTime DatePublish { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "AuthorPublish")]
    public string AuthorPublish { get; set; }

    [Display(ResourceType = typeof(FrameworkResurce), Name = "Author")]
    public string Author { get; set; }

    [Display(ResourceType = typeof(FrameworkResurce), Name = "AuthorUrl")]
    public string AuthorUrl { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "Views")]      
    public int Views { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "Comments")]
    public int Comments { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "IsComment")]
    public bool IsComment { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "SumVote")]
    public int SumVote { get; set; }


    [Display(ResourceType = typeof(FrameworkResurce), Name = "VoteCount")]
    public int VoteCount { get; set; }

    [NotMapped]
    [Display(ResourceType = typeof(FrameworkResurce), Name = "Rating")]
    public double Rating
    {
        get
        {
            if (VoteCount > 0)
            {
                return Math.Round((float)SumVote/VoteCount, 2);
            }

            return 0;
        }
    }
}

查询

private IEnumerable<NewsComment> GetComments()
    {
        var news = NewsCommentRepository.AllIncluding(c=>c.User,c=>c.News);
        return news;
    }

private DataRepository<NewsComment> NewsCommentRepository
        {
            get { return DataRepository<NewsComment>.Repository; }
        }

数据存储库

public class DataRepository<T> where T : BasePersistentEntity
{
    public static DataRepository<T>  Repository
    {
        get
        {
            return new DataRepository<T>();
        }
    }

    private readonly SGNContext<T> context = new SGNContext<T>();

    public IQueryable<T> All
    {
        get { return this.context.Table; }
    }

    public IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
    {
        IQueryable<T> query = this.context.Table;
        return includeProperties.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
    }

    public T Find(int id)
    {
        return this.context.Table.Find(id);
    }

    public void InsertOrUpdate(T country)
    {
        if (country.Id == default(int))
        {
            // New entity
            this.context.Table.Add(country);
            Save();
        }
        else
        {
            // Existing entity
            this.context.Entry(country).State = EntityState.Modified;
            Save();
        }
    }

    public void Delete(int id)
    {
        var country = this.context.Table.Find(id);
        this.context.Table.Remove(country);
        this.Save();
    }

    private void Save()
    {
        this.context.SaveChanges();
    }
}

GetComments 在哪里使用

    [GridAction]
    public ActionResult AjaxCommentsBinding()
    {
        return View(new GridModel<NewsComment>
        {
            Data = GetComments()
        });
    }

NewsCommentViews

CREATE VIEW [dbo].[NewsCommentViews]
AS
SELECT     dbo.NewsComments.NewsId, dbo.NewsComments.Text, dbo.NewsComments.UserId, dbo.NewsComments.CommentDate, dbo.NewsComments.Ip, 
                      dbo.Roles.RoleName, dbo.Users.UserName, dbo.Users.DateRegistered, dbo.NewsComments.Id, dbo.Users.Avatar
FROM         dbo.NewsComments INNER JOIN
                      dbo.Users ON dbo.NewsComments.UserId = dbo.Users.Id INNER JOIN
                      dbo.Roles ON dbo.Users.RoleId = dbo.Roles.Id

NewsCommentViews

[Table("NewsCommentViews")]
    public class NewsCommentView : NewsComment
    {
        public string RoleName { get; set; }

        public string UserName { get; set; }

        public DateTime DateRegistered { get; set; }

        public string Avatar { get; set; }
    }

【问题讨论】:

  • 你能显示导致异常的查询吗?也许还有NewsBaseComment 类。 Fluent API 中有映射代码吗?
  • 能否也显示引发异常的查询?
  • 接下来的两个问题:1)NewsCommentView 看起来如何? 2) 您能否准确显示您使用查询GetComments() 的代码?它只是一个IQueryable/IEnumerable,所以查询不在GetComments 中执行,而是在其他地方执行。还请准确指向引发异常的行。
  • 您的模型中的NewsCommentView 是如何定义的?

标签: entity-framework entity-framework-4 entity-framework-4.1


【解决方案1】:

问题在于NewsNewsCommentView 之间的关系:关系的一端是News.CommentViews 集合。但另一端不是 NewsCommentView.News,正如您所料。为什么?因为属性News 不是在NewsCommentView 类上声明,而是在基类NewsComment 上。现在 EF 不允许实体参与与导航属性的关系,该导航属性未在该实体类本身上声明,而仅在基类中。

所以,因为您没有 Fluent 映射 EF 仅按约定定义所有关系。会发生什么?

  • News 有一个导航属性 CommentViews 声明并指向 NewsCommentView 类。
  • EF 没有找到News 类型的逆属性,它在NewsCommentView 类中声明。 (有一个,但它在基类中,不算在内。)
  • 因此,EF 假定关系的另一端在NewsCommentView 类中未公开
  • 未公开意味着:EF 既没有导航属性也没有外键属性,它将假定数据库表/视图NewsCommentViews 中必要的外键列将具有标准的常规名称。
  • 这个常规名称是NameOfEntityClass_PKPropertyName -> News_Id

不过,您在视图中的真实姓名是 NewsId。因此,EF 查询不存在的列 News_Id,因此出现异常。

当你的 MVC-View 访问 NewsComment.News.CommentViews 时,可能是由于延迟加载而触发的异常。

您可以通过在 Fluent API 中明确指定 FK 列名称来解决此问题(据我所知,没有 Fluent 映射没有其他方法):

public class MyContext : DbContext
{
    // ...

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<News>()
            .HasMany(n => n.CommentViews)
            .WithRequired() // <- no param because not exposed end of relation,
                            // nc => nc.News would throw an exception
                            // because nc.News is in the base class
            .Map(a => a.MapKey("NewsId"));
    }
}

警告:请注意,NewsCommentView.News不是属于News.CommentViews 的关系的另一端。这意味着如果您的News.CommentViews 集合中有NewsCommentView,那么NewsCommentView.News 确实 指向该News 对象。另一端是不可见的,不会暴露在模型中。上面的映射只是修复了 FK 列名称问题,但不会改变约定会创建的关系(除了可能将关系更改为必需而不是可选)。

【讨论】:

    【解决方案2】:

    您的 SQL 在用户和 id 之间没有下划线。

    从数据库更新 EDMX(通过右键菜单)并检查映射。

    【讨论】:

    • 我明白了,现在你编辑了你的问题。您在哪里将属性 NewsId 映射到(不存在的)列 News_Id? - 搜索您的代码。如果您已经在代码中更正了输出文件,请尝试删除它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 2012-08-24
    相关资源
    最近更新 更多