I want to change a row field in my ResultSet before returning it to my Controller.
$resultSet->buffer();
foreach ($resultSet as $row) {
$row->foo = $newvalue;
}
return $resultSet;
Problem is, when I use the buffer() function I can indeed loop over my ResultSet and make some changes on my rows, but once the loop ends all changes are gone.
I tried to set up a reference on $row :
foreach ($resultSet as &$row)
But then caught the following exception :
Fatal error: An iterator cannot be used with foreach by reference
I also tried to change resultSet to array but the same problem occurs.
Have I missed something ?
I don't think it is possible via the usual ResultSet usage. The array solution might work only if you are going to use the array in loops (foreach() in this case).
From any Table class -
$arr_resultSet = array();
foreach ($resultSet as $row) {
$row->foo = $newvalue;
//Object is assigned instead of converting it to an array.
$arr_resultSet[] = $row;
}
return $arr_resultSet;
Usage of this array in controller or view file -
//Here you can access that $row object as if the $resultSet was never converted to array.
foreach($arr_resultSet as $row) {
echo $row->foo;
}
No need of buffer(). I hope it works for now. Will definitely search for a proper solution.
Related
Below is the code in question. I receive Object reference not set to an instance of an object. on the where clause inside the Linq query. However, this only happens after it goes through and builds my viewpage.
Meaning: If I step through using debugger, I can watch it pull the correct order I am filtering for, go to the correct ViewPage, fill in the model/table with the correct filtered item, and THEN it comes back to my Controller and shows me the error.
public ActionResult OrderIndex(string searchBy, string search)
{
var orders = repositoryOrder.GetOpenOrderList();
if (Request.QueryString["FilterOrderNumber"] != null)
{
var ordersFiltered = from n in orders
where n.OrderNumber.ToUpper().Contains(Request.QueryString["FilterOrderNumber"].ToUpper().ToString())
select n;
return View(ordersFiltered);
}
return View(orders);
}
its always better to manipulate your strings and other things outside the linq query ,
please refer : http://msdn.microsoft.com/en-us/library/bb738550.aspx
from the readability point of view also its not good ,
public ActionResult OrderIndex(string searchBy, string search)
{
var orders = repositoryOrder.GetOpenOrderList();
var orderNumber = Request.QueryString["FilterOrderNumber"];
if (!string.IsNullOrEmpty(orderNumber))
{
orderNumber = orderNumber.ToUpper();
var ordersFiltered = from n in orders
where n.OrderNumber.ToUpper().Contains(orderNumber)
select n;
return View(ordersFiltered);
}
return View(orders);
}
Your query is not being executed in your Action method because you don't have a ToList (or equivalent) added to your query. When your code returns, your query will be enumerated somewhere in your view and that's the point where the error occurs.
Try adding ToList to your query like this to force query execution in your action method:
var ordersFiltered = (from n in orders
where n.OrderNumber.ToUpper().Contains(Request.QueryString["FilterOrderNumber"].ToUpper().ToString())
select n).ToList();
What's going wrong is that a part of your where clause is null. This could be your query string parameter. Try moving the Request.QueryString part out of your query and into a temporary variable. If that's not the case make sure that your orders have an OrderNumber.
You both were right. Just separately.
This fixed my problem
var ordersFiltered = (from n in orders
where !string.IsNullOrEmpty(n.OrderNumber) && n.OrderNumber.ToUpper().Contains(Request.QueryString["FilterOrderNumber"].ToUpper().ToString())
select n);
Using ASP MVC5 and EF6.
I had a curious case the other day when I was looking to have different behaviour when a foreach-loop got to the last element.
The loop wouldn't enter if-condition comparing the object with the result from .Last()-method on the collection.
The collection I was iterating over was something like:
public class CollectionClass{
IEnumerable<TestClass1> CollectionA
IEnumerable<TestClass2> CollectionB
}
My code was something like:
DbContext db = new DbContext(); //just for illustration, not actual code
CollectionClass cc = new CollectionClass {
CollectionA = db.TestClasses1,
CollectionB = db.TestClasses2
};
//(TestClasses1 and TestClasses2 are DbSet<T> properties of my DbContext.
foreach(TestClass1 tc1 in cc.CollectionA)
{
if (tc1 == cc.CollectionA.Last()){ //<---NEVER enters in here!!
//doStuff
}
else{
//doOtherStuff
}
}
With the code above, the loop never entered into the if-condition, even for the last element, which one would expect.
But when changed my CollectionClass to:
public class CollectionClass{
List<TestClass1> CollectionA
List<TestClass2> CollectionB
}
and instantiated the CollectionClass-object like this:
CollectionClass cc = new CollectionClass {
CollectionA = db.TestClasses1.ToList(),
CollectionB = db.TestClasses2.ToList()
}; //Added .ToList()
the loop entered into the first if-condition at the last iteration as I expected.
Why this difference? Why did the equals-operator (==) evaluate to TRUE when the object had been stored in a List and FALSE when the object was stored in an IEnumerable?
I know that IEnumerable is an interface -- is that what makes the difference?
I even did an explicit test in the sorts of:
var obj1 = cc.CollectionA.Last();
var obj2 cc.CollectionA.Last();
bool result = obj1 == obj2; //result = FALSE
and the result was FALSE.
I think it's because in first example you get two objects from database. First from iteration and second from call to Last().
In second example all objects are created at the time you assign collections to CollectionA and CollectionB (you call ToList()).
It is because you are not allowed to use Last and LastOrDefault on DbSet objects. Instead you should use OrderByDescending(t=>t.ID).First()
I have the following statements but they return an empty result set:
$sql = 'SELECT * FROM `industry` WHERE `code` LIKE ?';
$statement = $this->getAdapter()->createStatement($sql, array('A_'));
$statement->execute();
What am I doing wrong? I really don't want to use the Zend\Db\Sql\Sql, as it is very verbose.
On a related point, where can I go to find out more about the theory of operation for Zend\Db? It's absolutely maddening. Why does it sometimes return a driver result? Sometimes a ResultSet? How can you view the complete SQL (after quoting, but before execution?) Etc...
OK, I had missed the fact that a Result is iterable (as well as a ResultSet). Therefore, assigning the result of $statement->execute() to a variable, then iterating that variable, sorted out the problem.
Futhermore, you can call getResource() on the result object, and from there access the underlying object (in this case, a PDO Statement). This means you can do things like result->getResource()->fetchAll();
Try with this query.
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Sql\Sql;
class tableNameTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
Publice function getIndustry(){
$adapter = $this->tableGateway->getAdapter();
$statement = $adapter->query("Your Query");
$results = $statement->execute();
return $results;
}
}
I am having an issue with ZF2 trying to use the table gateways and getting result sets:
I am trying to query two result sets (from two different tables/two different gateways) and send them to the view to be iterated through and placed on the screen.
(Simplified example):
function viewAction() {
$table1 = $this->getServiceLocator()->get('Model\Table\Table1');
$table2 = $this->getServiceLocator()->get('Model\Table\Table2');
return new ViewModel([
'table1' => $table1->fetchAll(),
'table2' => $table2->fetchAll()
]);
}
With the Model\Table\Table1 and Model\Table\Table2 having a fetch all:
public function fetchAll() {
return $this->tableGateway->select();
}
Then in my view:
...
<?php
foreach($table1 as $row) {
echo "<tr><td>{$row['col1']}</td><td>{$row['col2']}</td></tr>";
}
?>
...
<?php
foreach($table2 as $row) {
echo "<tr><td>{$row['col1']}</td><td>{$row['col2']}</td></tr>";
}
?>
...
The problem is, $table1 will have no data when looping. However, if I instead do something like this (in the controller, instead of passing the result set to the view, passing $results1 and $results2 to the view):
$fetchAll = $table1->fetchAll();
$results1 = [];
foreach($fetchAll as $row) {
$results1[] = $row;
}
$fetchAll = $table2->fetchAll();
$results2 = [];
foreach($fetchAll as $row) {
$results2[] = $row;
}
Then all works fine. I don't want to have to loop through the same set of data twice. So why does ZF2 prevent me from using two different ResultSets before all the data in a ResultSet has been accessed?
Since I was querying to different record sets one after the other, the database was still waiting for action to take place on the first query. I could only have one action record set at a time.
There first solution was what I presented in the question, get a record set and loop through all the rows that are available before trying to query again. This frees the record set as we have all the data.
The second solution (the one I have adapted), is to enable Multiple Active Record Sets (MARS) for the database connection.
I was able to do this by adding MARS_Connection=yes to the dsn connection string for MSSQL.
I am trying to retrieve the latest entered if from the 'order' table within my database.
I'm currently trying to use the following method:
public function getLatestOrderId()
{
$adapter = $this->adapter;
$sql = new Sql($adapter);
$select = $sql->select();
$select->columns(array('id' => 'orderId'));
$select->from('order');
$select->order('orderId DESC');
$select->limit(1);
$statement = $sql->prepareStatementForSqlObject($select);
$statement->execute();
}
I have a feeling that this should be working. I am then accessing this method in the controller like so:
$orderId = $this->getOrderTable()->getLatestOrderId();
I have realised that at present the getLatestOrderId method does not actually return anything e.g. return $statement->execute();. This is because I receive an error saying that the sql result could not be converted to a string.
I'm insure what is going wrong, so any help would be much appreciated.
Thank you.