11

私は2つのテーブルニュースとNewsCommentsを持っています。私はエンティティフレームワーク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ではなくNewsCommentViewクラスのと宣言されていますが、ベースクラスNewsCommentと宣言されています。現在EFでは、エンティティがナビゲーションプロパティを持つリレーションシップに参加することは許可されていません。はそのエンティティクラス自体で宣言されていますが、基底クラスでのみ宣言されています。

したがって、Fluentマッピングがないため、EFはすべてのリレーションシップを慣習によってのみ定義します。何が起こるのですか?

  • News宣言とNewsCommentViewクラスを指すCommentViewsナビゲーションプロパティを持っています。
  • クラスにの逆プロパティがあり、と宣言されていません。
  • したがって、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