How to simplify this so that search takes less time? - linq-to-sql

string name = null;
foreach (var dealer in contact)
{
if (name != null)
break;
if (name == null)
{
foreach (var emp in dealer.employees)
{
if (emp.id == primarySalespersonId)
{
if (emp.personFirstName != null)
name = emp.personFirstName;
else
name = "No Name";
break;
}
}
}
There are same multiple tables named contact. And each contact table has multiple dealer tables. I need a method to simplify this search using LINQ or any other better way. Please Help

The first optimisation you can do is to replace the inner loop to look for the employee by id, eg
string name = null;
foreach (var dealer in contact)
{
var emp= dealer.employees.Where(e=>e.Id == primarySalespersonId).FirstOrDefault();
if (emp!= null)
{
if (emp.personFirstName != null)
name = emp.personFirstName;
else
name = "No Name";
}
if (name != null)
break;
}
Going further, requires making some assumptions.
When a table has a column named 'id, then I would assume it means the column is an unique identity column.
If contact represents every dealer (as opposed to a selection of dealers) and if every employee belongs to a dealer, then you should be able to look up the id directly.
var emp = employees.Where(e=>e.Id == primarySalespersonId).SingleOrDefault();
if (emp != null)
{
if (emp.personFirstName != null)
name = emp.personFirstName;
else
name = "No Name";
}

Related

Query where clause based on user input

I have some html that allows the user to search with 2 criteria: name and cost. I am trying to make it so that the query displays results based on what the user enters for name and cost. There are 3 cases: name entered no cost, cost entered no name, both entered
SELECT name, cost FROM table WHERE...
I know to get the values entered by doing $_POST['name'] and $_POST['cost'] but I am struggling on how to set up the query to display the information based on the possible user input combinations
Is this what you basically want?
select . . .
from t
where (name = #name or #name is null) and
(cost = #cost or #cost is null);
Here #name and #cost are parameters used to pass the user input values into the query.
For my case, I always arrange the SQL like below:-
$nane = $_POST['name']:
$cost = $_POST['cost'];
if((isset($nane) && ($nane != "")) && (isset($cost) && ($cost != "")))
{
$sql = "select name,cost from table where columnNm ='".$nane."' and columnNm1 = ".$cost;
}
else if((isset($nane) && ($nane != "")) && (!isset($cost) && ($cost == "")))
{
$sql = "select name,cost from table where columnNm ='".$nane."'";
}
else if((!isset($nane) && ($nane == "")) && (isset($cost) && ($cost != "")))
{
$sql = "select name,cost from table where columnNm1 = ".$cost;
}
I solve my issues like this. If you think it's suitable for you then you may use it.

Convert complex nested selects in Entity Framework query

I need to create a table in View by this View Model:
public class ApplicationContentViewModel
{
public BPMSPARS.Models.MySql.application application {get; set;}
public BPMSPARS.Models.MySql.content content { get; set; }
public BPMSPARS.Models.MySql.app_delegation app_delegation { get; set; }
}
But the query for creating new Table is very complex.
I use this query in MySQL, and I can get correct results by using it.
SELECT APP_UID, (SELECT CON_VALUE FROM content WHERE CON_CATEGORY = 'PRO_TITLE' AND CON_ID =
(SELECT PRO_UID from app_delegation WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219')) AS TASK_NAME,
(SELECT CON_VALUE FROM content WHERE CON_CATEGORY = 'TAS_TITLE' AND CON_ID =
(SELECT TAS_UID from app_delegation WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219')) AS PROCESS_NAME FROM app_delegation
WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219'
But, I have to convert this query in linq or EF in MVC.
How Can I write This Query in Entity Framework query?
And How Can I display results in View?
Your SQL query seems (very) peculiar to me, as it is quite redundant. I am going to assume the sub-queries return a single value and enforce it with LINQ.
First I pulled out the common sub-query over app_delegation:
var USR_APP_Delegation = from a in app_delegation
where a.del_thread_status == "open" &&
a.USR_UID == "00000000000000000000000000000001" &&
a.APP_UID == "9134216305aaaea1b67c4e2096663219"
select a;
In LINQ it is easy to combine the two UID queries into one query:
var UIDs = (from a in USR_APP_Delegation
select new { a.PRO_UID, a.TAS_UID })
.Single();
Now you can do the name subqueries:
var TASK_NAME = (from c in content
where c.CON_CATEGORY == "PRO_TITLE" &&
c.CON_ID == UIDs.PRO_UID
select c.CON_VALUE)
.Single();
var PROCESS_NAME = (from c in content
where c.CON_CATEGORY == "TAS_TITLE" &&
c.CON_ID == UIDs.TAS_UID
select c.CON_VALUE)
.Single();
Then you can put all the queries together for the final result:
var ans = (from a in USR_APP_Delegation
select new {
a.APP_UID,
TASK_NAME,
PROCESS_NAME
})
.Single();
Again, this makes it obvious that your e.g. returning APP_UID when you know exactly what it is, and you are combining TASK_NAME and PROCESS_NAME into a query for no real advantage.
I would suggest using join against content makes a much more understandable query (even in SQL) and makes it clearer what is being returned:
var names = from a in app_delegation
join cpro in content on new { CON_ID = a.PRO_UID, CON_CATEGORY = "PRO_TITLE" } equals new { cpro.CON_ID, cpro.CON_CATEGORY }
join ctas in content on new { CON_ID = a.PRO_UID, CON_CATEGORY = "TAS_TITLE" } equals new { ctas.CON_ID, ctas.CON_CATEGORY }
where a.del_thread_status == "open" &&
a.USR_UID == "00000000000000000000000000000001" &&
a.APP_UID == "9134216305aaaea1b67c4e2096663219"
select new {
a.APP_UID,
Task_Name = ctas.CON_VALUE,
Process_Name = cpro.CON_VALUE
};

Select one record from join table

I have this query and i wanted to only select distinct value from Charges table(Port Name must only display once).
public List<Port> GetPortsByCountryOrigin(int countryId, TransportDirection transdirection, TransportType transtype)
{
using (var ctx = CreateDbContext())
{
return (from item in ctx.Ports
join s in ctx.Charges
on item.PortId equals s.PortId
where (s.TransportDirection == transdirection &&
s.TransportType == transtype
&& item.CountryId == countryId)
select item).ToList();
}
}
Currently, the Ports.Name are repeating values.
Try .Distinct() before your ToList()

LINQ to SQL: rows to columns

I would like to have a single LINQ to SQL query to count 2 entities from the same table. E.g. Count number of employees and managers from table Personnel.
Example:
var q = from p in db.Personnel
where p.PersonType == 'Manager' || p.PersonType == 'Employee'
select new
{ NoOfPersonnel = p.Count(p => p.PersonType == 'Employee'), //Wrong way
NoOfManagers = p.Count(p => p.PersonType == 'Manager') //Wrong way
}
How can I do it?
Try this:
var list = from employee in db.Personnel
where employee.PersonType == "Manager" || employee.PersonType == "Employee"
group employee by employee.PersonType
into temp
select new { PersonType = temp.Key, Count = temp.Count() };

Insert a duplicate record based on value of another column

I have a db table named Student, with columns as id, name, age.
id is the Primary Key, name is not null, and age can be null
I want to implement the following in php, Zend:
Only add a duplicate student name in db if the age value is different.
Inside the function/action addStudentAction, I am calling the Student model's function -findStudent to implement the requirement:
public function findStudent($name)
{
$result = null;
$select = $this->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
->setIntegrityCheck(false)
->where('student.name = ?', $name);
//error_log($select->assemble());
$result = $this->getAdapter()->fetchRow($select);
return $result;
}
public function addStudentAction() {
$data = $_POST;
$studentModel = new Application_Model_Student;
$result = $studentModel->findStudent($data['name']);
if(!empty($result)) {
error_log("found student name in db, going to get age");
//Check for age
if( (!empty($result['age'] )) {
if( $result['age'] != $data['age']) {
error_log("going to add student as new record");
return $this->insert($data);
}
else {
error_log("not adding new student record ");
}
}
}
}
Now, there could be multiple records of Students with same name but different age values. Therefore, when adding a new student, I need to compare the ages of all records(if name matches) with the incoming value of age.
What could be best way to implement this requirement? Any help is greatly appreciated.
Thanks
The easiest way would be to create a compound UNIQUE index on the name, then age field. UNIQUE allows multiple NULL values, so that won't be an issue. Depending on your database size and usage, this might not be the most preferred option, in which case a simple SELECT of the student information before an INSERT to check if he/ she is already in there would be the best solution.
Let me know if I need to elaborate on this. I'd be happy to give you some examples.
How about you do a new SELECT with name and age:
public function findStudentWithAge($name, $age =null)
{
$result = null;
$select = $this->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
->setIntegrityCheck(false)
->where('student.name = ?', $name);
if($age) $select->where('student.age = ?', $age);
//error_log($select->assemble());
$result = $this->getAdapter()->fetchRow($select);
return $result;
}
Now in the addStudentAction:
public function addStudentAction() {
$data = $_POST;
$studentModel = new Application_Model_Student;
$result = $studentModel->findStudent($data['name'], $data['age']);
if(!empty($result)) {
error_log("found student with this age, cannot add the record");
} else {
$this->insert($data);
}
}