2

データベースに 3 つのテーブルがあります。すべてのテーブルは異なるエンティティ クラスで動作します。コードは次のとおりです。

public class Quizs
{
    [Key]
    public int QuizId { get; set; }            
    public string Title { get; set; }    
    public string Instructions { get; set; }    
    public string IsTimerEnabled { get; set; }    
    public virtual ICollection<Question> Questions { get; set; }
}

public class Question
{
    [Key]
    public int QuestionId { get; set; }    
    public virtual ICollection<Answers> Answers { get; set; }    
    public int RightAnswer { get; set; } // Key of Answers[]    
    public int QuestionType { get; set; } // 1 = One choise, 2 = Multiple Choise    
    public string Explantion { get; set; } // To appear after answering the question    
    public int MaxTime { get; set; } // In seconds
}

public class Answers
{
    [Key]
    public int asId { get; set; }    
    public int Id { get; set; }    
    public string Text { get; set; }
}

したがって、この 3 つのテーブルのすべてのデータを WebApi ページに出力する必要があります。

コントローラーでデータを引き出すコードは次のとおりです。

// GET api/QuizsData/
    public IEnumerable<Quizs> Get()
    {

        return dba.Quiz.Include("Questions").Include("Questions.Answers").ToList();
    }

これは、API のルートに移動したときに得られるものです。

{"メッセージ":"エラーが発生しました。","ExceptionMessage":"列名 'Question_QuestionId' が無効です。\r\n列名 'Question_QuestionId' が無効です。","ExceptionType":"System.Data.SqlClient.SqlException" 、"StackTrace":" System.Data.SqlClient.SqlConnection.OnError(SqlException 例外、Boolean breakConnection、アクション1 wrapCloseInAction)\r\n at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) で\r\n
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj、Boolean callerHasConnectionLock、Boolean asyncClose で)\r\n
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior、SqlCommand cmdHandler、SqlDataReader dataStream、BulkCopySimpleResultSet bulkCopyHandler、TdsParserStateObject stateObj、Boolean& dataReady)\r\n で System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()\r\n でSystem.Data.SqlClient.SqlDataReader.get_MetaData()\r\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)\r\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds( CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、Boolean async、Int32 timeout、Task& task、Boolean asyncWrite)\r\n at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String メソッド、TaskCompletionSource`1 完了、Int32 タイムアウト、Task& task、Boolean asyncWrite)\r\n System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String メソッド)\r\n System.Data. SqlClient.SqlCommand.ExecuteReader(CommandBehavior 動作、文字列メソッド)\r\n で System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior 動作)\r\n で System.Data.Common.DbCommand.ExecuteReader(CommandBehavior 動作)\r \n System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) で"}RunBehavior runBehavior、Boolean returnStream、String メソッド)\r\n System.Data.SqlClient.SqlCommand.ExecuteReader (CommandBehavior 動作、String メソッド)\r\n System.Data.SqlClient.SqlCommand.ExecuteDbDataReader (CommandBehavior 動作)\r \n System.Data.Common.DbCommand.ExecuteReader (CommandBehavior 動作) で\r\n System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand、CommandBehavior 動作) で"}RunBehavior runBehavior、Boolean returnStream、String メソッド)\r\n System.Data.SqlClient.SqlCommand.ExecuteReader (CommandBehavior 動作、String メソッド)\r\n System.Data.SqlClient.SqlCommand.ExecuteDbDataReader (CommandBehavior 動作)\r \n System.Data.Common.DbCommand.ExecuteReader (CommandBehavior 動作) で\r\n System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand、CommandBehavior 動作) で"}ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior 動作)"}ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior 動作)"}

私はこの例外メッセージを受け取りました..助けはありますか?

ありがとう!

4

3 に答える 3

3

あなたが思っているように人間関係を築いてきたわけではないと思います。

これらの変更を試してください:

public class Quizs
{
    // no attribute
    public virtual ICollection<Question> Questions { get; set; }
}

public class Question
{
    // no attribute
    public virtual ICollection<Answers> Answers { get; set; }

    // add
    [ForeignKey("Quiz")]
    public int QuizId { get; set; }
    public virtual Quizs Quiz { get; set; }
}

public class Answers
{
    // add
    [ForeignKey("Question")]
    public int QuestionId { get; set; }
    public virtual Question Question { get; set; }
}

(また、クラス名を単数形にすることを検討してください。これにより、セマンティックの混乱が少なくなります。)


何が何であるかについてもう少し説明します。

ここで達成しようとしていることは、一対多の関係と呼ばれます。たとえば、1 つのクイズに対して多数の質問があるとします。または、1 つの質問に対して多くの回答がある場合。クイズと質問の関係では、クイズが「一」側であり、問​​題が「多」側です。質問と回答の関係は、質問が「一」側、回答が「多」側です。

Entity Framework でこのような関係を実現するには、関係の「多」側に移動して、次のようなものを追加するだけです。

public virtual Quiz Quiz { get; set; }

そして、関係の「一方」側に移動し、次のようなものを追加します。

public virtual ICollection<Question> Questions { get; set; }

Entity Framework は、最初の宣言が「テーブルへの外部キーを作成する」ことをQuiz意味し、もう 1 つの宣言が「テーブルの複数のレコードがQuestionここを指す」ことを意味することを理解しています。

これは、通常のクラス間のリレーションシップと同じように機能しますが、プロパティを仮想化して、Entity Framework がこのリレーションシップを実際に実装するプロパティで実行時にオーバーライドできるようにする点が異なります。

現状では、(「多」側の) モデルからは、データベースで作成された外部キーにアクセスできません。それが参照するレコードにはアクセスできますが、外部キー自体にはアクセスできません (少なくとも他のレコードをフェッチしない限り)。これを修正するには、次のように、明示的に宣言されたプロパティを外部キーとして使用するように Entity Framework に指示できます。

[ForeignKey("Quiz")]
public int QuizId { get; set; }

このForeignKey属性は、次のintプロパティ ( QuizId) がプロパティによって使用される実際の外部キーQuizになることを示しています。これは、アクセスできないテーブルに独自の外部キーを暗黙的に作成させるのではありません。

別の言い方をすれば、別のモデルを参照したため、とにかく外部キーが作成されることになります。属性は、その外部キーに自分でアクセスしたいことを示すためにあります。ほとんどの場合、これが必要になります。

于 2013-06-17T08:23:56.233 に答える
1

エンティティ フレームワークを使用すると、子エンティティを熱心に読み込むことができます。

 return dba.Quiz.Include("Questions").Include("Questions.Answers").ToList();

または、ラムダ構文を使用します (プロパティの名前を再度変更しても壊れません):

 return dba.Quiz.Include(q => q.Questions.Select(x => x.Answers)).ToList();

その構文を理解するには、 Includeメソッドに関する注釈を参照してください。


Answerまた、エンティティのキ​​ーを修正する必要があります。asId質問の外部キーとして使用しているためですId(奇妙な命名です):

public class Answers
{
    [Key]
    public int asId { get; set; }  // use this property as PK
    public int Id { get; set; }  // because this is FK
    public string Text { get; set; }
}
于 2013-06-17T08:21:08.610 に答える
0

ここで説明されているように、Include メソッドを使用して関連エンティティを熱心に読み込みます: http://msdn.microsoft.com/en-US/data/jj574232

于 2013-06-17T08:22:19.343 に答える