1

我是 SQL Server 存储过程的新手,如果我是个白痴,我深表歉意。我想使用一个存储过程来返回一个对象列表,每个对象都有一个包含相关对象列表的属性。例如

public class Question
{
    public int QuestionID { get; set; }
    public string Question { get; set; }
    public List<Answer> Answers { get; set; }
}

public class Answer
{
    public int AnswerID { get; set;}
    public int QuestionID { get; set; }
    public string Answer { get; set;}
}

我想编写一个存储过程,它返回一个问题列表,每个问题的 Answers 属性都填充了相关的 Answer 对象。

非常感谢任何帮助!

谢谢,

戴夫

4

2 回答 2

1

实际上,存储过程提供的是关系结果而不是对象。作为替代方案,您可以使用返回 XMLFOR XML并将其反序列化为对象。将此映射到对象通常使用 O/R 映射器完成。

您可以使用数据集和表适配器将关系数据导入您的应用程序。一旦加载到数据集中,您就可以填充您的QuestionAnswer对象。

这是一个示例玩具代码,用于将存储过程的结果填充到数据集中:

var ds = new DataSet();

using (var cn = new SqlConnection())
using (var cmd = new SqlCommand("myStoredProcedure", cn))
{
    cmd.CommandType = CommandType.StoredProcedure;

    using (var adapter = new SqlDataAdapter(cmd))
    {
        adapter.TableMappings.Add("Table0", "Answers");
        adapter.TableMappings.Add("Table1", "Questions");

        adapter.Fill(ds);
    }
}

对于实际开发,我建议您使用Typed Dataset和适当的SqlConnection. 但是,正如评论所指出的,如果可以,请使用 EF 或其他 O/R 映射器。

于 2013-05-13T13:42:41.077 回答
0

这是您最基本的 ORM 映射器类型。

嗯,最基本的,考虑到一些可维护性和可读性。

我会访问数据库一次,但在您的存储过程中有多个结果集。并查看 IDataReader.NextResult

(如此处所示链接

下面是一些基本的 ORM。

[Serializable]
public partial class Answer
{
    public int AnswerKey { get; set; }                   
    public int ParentQuestionID { get; set; }
    public string AnswerText { get; set; }                   

    public Question ParentQuestion  { get; set; }    

}

internal static class AnswerDefaultLayout
{
    public static readonly int AnswerKey = 0;
    public static readonly int ParentQuestionID = 1;
    public static readonly int AnswerText = 2;

}

public class AnswerSerializer
{
    public ICollection<Answer> SerializeAnswers(IDataReader dataReader)
    {
        Answer item = new Answer();
        ICollection<Answer> returnCollection = new List<Answer>();

            int fc = dataReader.FieldCount;//just an FYI value

            int counter = 0;//just an fyi of the number of rows

            while (dataReader.Read())
            {

                if (!(dataReader.IsDBNull(AnswerDefaultLayout.AnswerKey)))
                {
                    item = new Answer() { AnswerKey = dataReader.GetInt32(AnswerDefaultLayout.AnswerKey) };

                    if (!(dataReader.IsDBNull(AnswerDefaultLayout.ParentQuestionID)))
                    {
                        item.ParentQuestionID = dataReader.GetInt32(AnswerDefaultLayout.ParentQuestionID);
                    }

                    if (!(dataReader.IsDBNull(AnswerDefaultLayout.AnswerText)))
                    {
                        item.AnswerText = dataReader.GetString(AnswerDefaultLayout.AnswerText);
                    }


                    returnCollection.Add(item);
                }

                counter++;
            }

            return returnCollection;

    }
    }


[Serializable]
public class Question
{
    public int QuestionID { get; set; }
    public string Question { get; set; }
    public ICollection<Answer> Answers { get; set; }
}

internal static class QuestionDefaultLayout
{
    public static readonly int QuestionID = 0;
    public static readonly int QuestionText = 1;
}


public class QuestionSerializer
{
    public ICollection<Question> SerializeQuestions(IDataReader dataReader)
    {
        Question item = new Question();
        ICollection<Question> returnCollection = new List<Answer>();


            int fc = dataReader.FieldCount;//just an FYI value

            int counter = 0;//just an fyi of the number of rows

            while (dataReader.Read())
            {

                if (!(dataReader.IsDBNull(QuestionDefaultLayout.QuestionID)))
                {
                    item = new Question() { QuestionID = dataReader.GetInt32(QuestionDefaultLayout.QuestionID) };

                    if (!(dataReader.IsDBNull(QuestionDefaultLayout.LAST_NAME)))
                    {
                        item.LastName = dataReader.GetString(QuestionDefaultLayout.LAST_NAME);
                    }



                    returnCollection.Add(item);
                }

                counter++;
            }

            return returnCollection;


    }
}






public class QuestionManager
{

    public ICollection<Question> GetAllQuestionsWithChildAnswers()
    {

    String myConnString  = "User ID=<username>;password=<strong password>;Initial Catalog=pubs;Data Source=myServer";
    SqlConnection myConnection = new SqlConnection(myConnString);
    SqlCommand myCommand = new SqlCommand();
    SqlDataReader myReader ;

    myCommand.CommandType = CommandType.StoredProcedure;
    myCommand.Connection = myConnection;
    myCommand.CommandText = "dbo.uspQuestionAndAnswersGetAll";
    int RecordCount=0; 

    try
    {
        myConnection.Open();
        myReader = myCommand.ExecuteReader();

        ICollection<Question> questions = new QuestionSerializer().SerializeQuestions(myReader);

        myReader.NextResult();

        ICollection<Answer> answers = new AnswerSerializer().SerializeAnswers(myReader);

        questions = this.MergeQuestionObjectGraphs(questions, answers);

    catch(Exception ex) 
    {
       MessageBox.Show(ex.ToString());
    }
    finally
    {
    if (null != myReader)
    {
        myReader.Close();
    }
    if (null != myConnection)
    {
        myConnection.Close();
    }
    }
    }

        private ICollection<Question> MergeQuestionObjectGraphs(ICollection<Question> qtions, ICollection<Answer> aners)
        {
            if (null != qtions && null != aners)
            {
                foreach (Question qtn in qtions)
                {
                    IEnumerable<Answer> foundLinks = aners.Where(lnk => lnk.ParentQuestionId == qtn.QuestionId);
                    if (null != foundLinks)
                    {
                        foreach (Answer link in foundLinks)
                        {
                            link.ParentQuestion = qtn;
                        }

                        qtn.Answers = foundLinks.ToList();
                    }
                }
            }

            return qtions;
        }

}

TSQL

CREATE PROC dbo.uspQuestionAndAnswersGetAll
AS
    SELECT QuestionId, QuestionText FROM dbo.Question
    SELECT AnswerId, QuestionId, AnswerText FROM dbo.Answer
GO 
于 2013-05-13T14:01:43.980 回答