Renvoyer des objects avec des propriétés de liste renseignées à partir d’une procédure stockée

Je suis nouveau dans les procédures stockées SQL Server, alors excuses-moi si je suis un idiot. J’aimerais utiliser une procédure stockée pour renvoyer une liste d’objects, chacun d’eux ayant une propriété contenant une liste d’objects associés. Par exemple

public class Question { public int QuestionID { get; set; } public ssortingng Question { get; set; } public List Answers { get; set; } } public class Answer { public int AnswerID { get; set;} public int QuestionID { get; set; } public ssortingng Answer { get; set;} } 

J’aimerais écrire une procédure stockée qui retourne une liste de questions, chacune d’entre elles ayant sa propriété Réponses remplie avec les objects Answer associés.

Toute aide grandement appréciée!

Merci,

Dave

En réalité, une procédure stockée fournit un résultat relationnel plutôt que des objects. Au lieu de cela, vous pouvez renvoyer XML en utilisant FOR XML et le désérialiser en objects. Le mappage sur des objects est généralement effectué à l’aide d’un mappeur O / R.

Vous pouvez utiliser des jeux de données et des adaptateurs de table pour obtenir les données relationnelles dans vos applications. Une fois chargé dans le jeu de données, vous pouvez renseigner vos objects Question et Answer .

Voici un exemple de code de jouet pour intégrer le résultat d’une procédure stockée dans un dataset:

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

Pour le développement actuel, je vous suggérerais d’utiliser un jeu de données typé et un SqlConnection approprié. Toutefois, comme le font remarquer les commentaires, utilisez EF ou un autre mappeur O / R si vous le pouvez.

Voici votre type le plus fondamental de mappeur ORM.

Eh bien, le plus fondamental, avec une certaine facilité de maintenance et de lisibilité à l’esprit.

Je voudrais bash la firebase database une fois, mais plusieurs résultats dans votre procédure stockée. Et regardez dans le IDataReader.NextResult

(comme vu ici LINK )

Ci-dessous quelques bases ORM.

 [Serializable] public partial class Answer { public int AnswerKey { get; set; } public int ParentQuestionID { get; set; } public ssortingng 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 SerializeAnswers(IDataReader dataReader) { Answer item = new Answer(); ICollection returnCollection = new List(); 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.GetSsortingng(AnswerDefaultLayout.AnswerText); } returnCollection.Add(item); } counter++; } return returnCollection; } } [Serializable] public class Question { public int QuestionID { get; set; } public ssortingng Question { get; set; } public ICollection Answers { get; set; } } internal static class QuestionDefaultLayout { public static readonly int QuestionID = 0; public static readonly int QuestionText = 1; } public class QuestionSerializer { public ICollection SerializeQuestions(IDataReader dataReader) { Question item = new Question(); ICollection returnCollection = new List(); 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.GetSsortingng(QuestionDefaultLayout.LAST_NAME); } returnCollection.Add(item); } counter++; } return returnCollection; } } public class QuestionManager { public ICollection GetAllQuestionsWithChildAnswers() { Ssortingng myConnSsortingng = "User ID=;password=;Initial Catalog=pubs;Data Source=myServer"; SqlConnection myConnection = new SqlConnection(myConnSsortingng); 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 questions = new QuestionSerializer().SerializeQuestions(myReader); myReader.NextResult(); ICollection answers = new AnswerSerializer().SerializeAnswers(myReader); questions = this.MergeQuestionObjectGraphs(questions, answers); catch(Exception ex) { MessageBox.Show(ex.ToSsortingng()); } finally { if (null != myReader) { myReader.Close(); } if (null != myConnection) { myConnection.Close(); } } } private ICollection MergeQuestionObjectGraphs(ICollection qtions, ICollection aners) { if (null != qtions && null != aners) { foreach (Question qtn in qtions) { IEnumerable 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