/// <summary>Executes a query and directly fills given collection with objects build from retrieved data.</summary> /// <param name="conn">Connection provider.</param> /// <param name="destination">A collection to fill with objects built from data.</param> /// <param name="objectBuilder">Builds objects directly from retrieved data.</param> /// <remarks><para>The method uses provided converter to directly build specified object type from data contained in /// <see cref="IDataReader"/> objects, thus skipping the need to create intermediate data structures such as <see cref="DataTable"/> /// and <see cref="DataSet"/> objects. This can increase performance and reduce memory consumption when working with very /// large results sets.</para> /// <example><para>The following example demonstrates the fastest way to fetch and initialize entity collection:<code> /// EmployeesMeta employees = new EmployeesMeta(); /// SelectStatement select = new SelectStatement(employees, employees.Columns); /// var allEmployees = new EntityCollection<EmployeesEntity, EmployeesMeta>(); /// select.FillCollection(allEmployees, employees.NewEntityFiller()); /// </code></para> /// <para>Besides entity collections, you can also fill any custom collections or data structures by implementing your own <see cref="IObjectFiller"/> objects. /// The following example demonstrates the fastest way to fetch all values used in a single column of a table using custom developed object filler:<code> /// //Fetch all values from OrderID column of Order Details table. /// public List<int> FillOrderIdCollection() /// { /// OrderDetailsMeta details = new OrderDetailsMeta(); /// SelectStatement select = new SelectStatement(details, details.OrderID); /// // Operation is slightly faster if we can estimate the number of items that the target collection will contain. /// var allItems = new List<int>(2200); /// select.FillCollection(allItems, new SingleFieldFiller()); /// return allItems; /// } /// /// //Fills collection with primitive types. /// public class SingleFieldFiller : IObjectFiller /// { /// public void FillCollection(IDataReader openedDataReader, IList collection) /// { /// while (openedDataReader.Read()) /// { /// object value = openedDataReader.GetValue(0); /// collection.Add(value); /// } /// } /// } /// </code></para></example></remarks> public void FillCollection(IConnectionProvider conn, IList destination, IObjectFiller objectBuilder) { this.ConnectionProvider = conn; FillCollection(destination, objectBuilder); }
/// <summary>Executes a query and converts data to specified objects.</summary> /// <param name="conn">Connection provider.</param> /// <param name="destination">A collection to fill with objects built from data.</param> /// <param name="objectBuilder">Builds objects directly from retrieved data.</param> /// <param name="cmdText">Command text.</param> /// <param name="parameters">Command parameters.</param> /// <param name="cmdType">Command type (stored procedure or text).</param> /// <param name="cmdTimeout">Set timeout for specified command.</param> /// <param name="useSequentalAccess">Uses CommandBehavior.SequentialAccess instead of CommandBehavior.SingleResult.</param> /// <remarks><para>The method uses provided converter to directly build specified object type from data contained in /// <see cref="IDataReader"/> objects, thus skipping the need to create intermediate data structures such as <see cref="DataTable"/> /// and <see cref="DataSet"/> objects. This can increase performance and reduce memory consumption when working with very /// large results sets.</para></remarks> internal static void ExecuteReader(IConnectionProvider conn, IList destination, IObjectFiller objectBuilder, string cmdText, DbParameterCollection parameters, CommandType cmdType, int cmdTimeout, bool useSequentalAccess) { IDbCommand cmd = CreateCommand(conn.DBMS, cmdText, parameters, cmdType, cmdTimeout); cmd.Connection = conn.Connection; bool connIsOpennedLocally = EnsureOpenConnection(conn); try { AssignExistingPendingTransactionToCommand(conn, cmd); CommandBehavior behaviour = CommandBehavior.SingleResult; if (useSequentalAccess) behaviour = CommandBehavior.SequentialAccess; using (IDataReader reader = cmd.ExecuteReader(behaviour)) { objectBuilder.FillCollection(reader, destination); PopulateOutputParameterValues(parameters, cmd); } } finally { CloseConnectionIfLocal(conn, connIsOpennedLocally); cmd.Dispose(); } }
/// <summary>Executes a query and directly fills given collection with objects build from retrieved data.</summary> /// <param name="destination">A collection to fill with objects built from data.</param> /// <param name="objectBuilder">Builds objects directly from retrieved data.</param> /// <param name="cmdTimeout">Sets timeout for collection fetching SQL command. Default is 30 seconds.</param> /// <remarks><para>The method uses provided converter to directly build specified object type from data contained in /// <see cref="IDataReader"/> objects, thus skipping the need to create intermediate data structures such as <see cref="DataTable"/> /// and <see cref="DataSet"/> objects. This can increase performance and reduce memory consumption when working with very /// large results sets.</para> /// <example><para>The following example demonstrates the fastest way to fetch and initialize entity collection:<code> /// EmployeesMeta employees = new EmployeesMeta(); /// SelectStatement select = new SelectStatement(employees, employees.Columns); /// var allEmployees = new EntityCollection<EmployeesEntity, EmployeesMeta>(); /// select.FillCollection(allEmployees, employees.NewEntityFiller()); /// </code></para> /// <para>Besides entity collections, you can also fill any custom collections or data structures by implementing your own <see cref="IObjectFiller"/> objects. /// The following example demonstrates the fastest way to fetch all values used in a single column of a table using custom developed object filler:<code> /// //Fetch all values from OrderID column of Order Details table. /// public List<int> FillOrderIdCollection() /// { /// OrderDetailsMeta details = new OrderDetailsMeta(); /// SelectStatement select = new SelectStatement(details, details.OrderID); /// // Operation is slightly faster if we can estimate the number of items that the target collection will contain. /// var allItems = new List<int>(2200); /// select.FillCollection(allItems, new SingleFieldFiller()); /// return allItems; /// } /// /// //Fills collection with primitive types. /// public class SingleFieldFiller : IObjectFiller /// { /// public void FillCollection(IDataReader openedDataReader, IList collection) /// { /// while (openedDataReader.Read()) /// { /// object value = openedDataReader.GetValue(0); /// collection.Add(value); /// } /// } /// } /// </code></para></example></remarks> public void FillCollection(IList destination, IObjectFiller objectBuilder, int cmdTimeout = 30) { bool blobAware = false; DbParameterCollection parameters = new DbParameterCollection(); StringBuilder cmdText = new StringBuilder(); Render(this.ConnectionProvider.DBMS, cmdText, parameters); string command = cmdText.ToString(); this.LastExecutedCommandInfo = new CommandExecutionStatistics(command); if (objectBuilder is IBlobFiller) blobAware = true; DbUtil.ExecuteReader(this.ConnectionProvider, destination, objectBuilder, command, parameters, CommandType.Text, cmdTimeout, blobAware); this.LastExecutedCommandInfo.StopTime(); }