2011-08-14 274 views
11

我有两个表新闻和新闻评论。我跟着命名实体框架4.1无效列名

结构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] 

BaseComment

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

BaseContent

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

DataRepository

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

NewsCommentVi EWS

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; } 
    } 
+0

你能显示导致异常的查询吗?也许还有'News'和'BaseComment'类。你有没有在Fluent API中的映射代码? – Slauma

+0

我不使用Fluent API – Greg

+0

你还可以显示引发异常的查询吗? – Slauma

回答

18

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

如此,因为你没有良好的映射EF只能由公约规定的所有关系。怎么了?

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

你在视图中的真名是NewsId虽然。因此,EF查询不存在的列News_Id,因此是例外。

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

您可以用流利的API显式地指定FK列名解决这个问题(据我知道有没有流利的映射没有其他的方法):

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列名问题,但并未改变约定会创建的关系(除了可能将关系更改为必需而非可选)。

1

你的SQL不具有用户和ID之间的下划线。

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

+0

我使用EF 4.1 CF – Greg

+0

我现在看到你编辑了你的问题。你在哪里将NewsId属性映射到(不存在的)列News_Id? - 搜索你的代码。尝试删除输出文件,如果您已经在您的代码中更正了这些文件。 –

+0

这对我来说非常适合!谢谢 – mikemike396