2

我的数据库中有三个表。每个表都使用不同的实体类,代码:

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

所以现在我需要将这三个表中的所有数据输出到 WebApi 页面。

这是在控制器中提取数据的代码:

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

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

这是我去api的路线时得到的:

{"Message":"发生错误。","ExceptionMessage":"无效的列名 'Question_QuestionId'。\r\n无效的列名 'Question_QuestionId'。","ExceptionType":"System.Data.SqlClient.SqlException" “StackTrace”:“在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常,布尔 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,布尔 callerHasConnectionLock,布尔 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 在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)\r\n 在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds( CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、Boolean async、Int32 超时、Task& 任务、Boolean asyncWrite)\r\n 在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String 方法、TaskCompletionSource`1 完成,Int32 超时,Task& 任务,布尔 asyncWrite)\r\n 在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,布尔 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 行为)"}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; }
}

(另外,考虑把你的类名变成单数。这会减少语义混淆。)


关于什么是什么的更多解释:

您在这里尝试实现的目标称为一对多关系。例如,您有许多问题指向一个测验。或者你有很多答案指向一个问题。在问答关系中,问答是“一”面,问题是“多”面。在问答关系中,问题是“一”方,答案是“多”方。

要在 Entity Framework 中实现这样的关系,您所要做的就是转到关系的“多”端并添加如下内容:

public virtual Quiz Quiz { get; set; }

然后转到关系的“一个”方面并添加如下内容:

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

Entity Framework 理解第一个声明的意思是“为表创建外键Quiz”,另一个意思是“Question表的多条记录将指向这里”。

这就像普通类之间的关系一样,除了您将属性设置为虚拟,以便实体框架可以在运行时使用实际实现这种关系的属性覆盖它们。

就像现在一样,从您的(“多”方面)模型中,您无法访问在数据库中创建的外键。您确实可以访问它所引用的记录,但不能访问外键本身(至少在不获取其他记录的情况下不能)。要解决此问题,您可以告诉实体框架使用显式声明的属性作为外键,如下所示:

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

或者使用 lambda 语法(如果您再次重命名属性,则不会中断):

 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 回答