I have a search page with 4 options city , state , year ,school
You put that information in the textbox once you click submit it queries the database to find matching records. This works but i was wondering if there is a more efficient way of doing things for example you can search by city,state or school and year but each time I have to do this ...
if(string school == null && int year == null)
{
// then search for city,state
}
if(string city == null && string state== null)
{
// then search for school, year
}
else
{
// search for city,state,school,year
}
as you can see this is only 4 fields and it becomes tedious searching for each one especially since im planning to add more fields in the future. Is there a way that I can check everything in 1 if statement and if for example the user left city,state empty to just ignore it.
This is a sample of my city state search
public ActionResult search(string city, string state,string school,int year,int? page)
{
ViewBag.city = city;
ViewBag.state = state;
ViewBag.year = year;
ViewBag.school = school;
int pageSize = 10;
int pageNumber = (page ?? 1);
if (school == null && year ==null)
{
// I would like to put all my variables here and ignore blanks one like
var article = (from x in db.relistings.OrderByDescending(x => x.relistingID)
where x.city == city && x.state == state select x);
return View(article.ToPagedList(pageNumber, pageSize));
}
}
Related
I have csv file like this:
1392249600;EUR;CHF;USD;JPY;GBP
1392163200;GBP;JPY;USD;CHF;EUR
1392076800;GBP;CHF;EUR;JPY;USD
1391990400;JPY;USD;EUR;CHF;GBP
1391904000;GBP;EUR;CHF;USD;JPY
1391731200;GBP;EUR;CHF;JPY;USD
1391644800;EUR;CHF;USD;JPY;GBP
1391558400;JPY;USD;EUR;CHF;GBP
There can be over 15 000 rows in that file. I am trying to write code that could do such thing:
1.Takes first row saves it as parent. Then takes next 3 days as that childs.
2.Counts how often and which combination off childs with that parent are inside this file.
3.It creates something like summary for that so I could read todays combination and script shows the only the most frequent child combinations for next 3 days.
I don't have mathematical thinking so I have big problems to find solution myself.
What I think first I need script that generates all posible combinations of these colums made of EUR,CHF,USD,JPY,GBP so there is posible 5*4*3*2*1 = 120 combinations. Because they cant repeat in single row.
It will be like this.
First parent will be combination from first row like this: EUR;CHF;USD;JPY;GBP
Then 3 childs would be
GBP;JPY;USD;CHF;EUR
GBP;CHF;EUR;JPY;USD
JPY;USD;EUR;CHF;GBP
It saves this combination off parent and child elements.
Then again it starts from begining of the file, but moves one row below(like iteration +1).
then next all childs would be
GBP;CHF;EUR;JPY;USD
JPY;USD;EUR;CHF;GBP
GBP;EUR;CHF;USD;JPY
And again it saves these combinations for counting and make some frequency results.
And this cycle repeats for all rows on csv file.
Is there maybe some tips I should consider how to create this type of programm ?
Any tip would be great !
Thank You Very Much!
BB
Can you please clarify whether first value in a row in your file is date/time? 1392249600;EUR;CHF;USD;JPY;GBP
If yes, are you expecting that there will total 4 rows with the same date/time?
Or else you just need to go sequentially and use Line-1 as parent and then Line-2, Line-3, Line-4 as child and goes on... so that Line-5 becomes parent again?
To check whether country code is equivalent or not, you can use below kind of code. I am not 100% sure about your requirement, please correct me if you think this is not what you are looking for and I will try to answer you in other way:
package com.collections;
public class CountryCodeComparison {
public static void main(String[] args) {
//Read every row and sequentially insert value in CountryCode object.
//For ex. your row is: 1392163200;GBP;JPY;USD;CHF;EUR
String s1 = "1392163200;GBP;JPY;USD;CHF;EUR";
String [] array1 = s1.split(";");
CountryCode cc1 = new CountryCode(array1[1], array1[2], array1[1], array1[4], array1[5]);
//For ex. your row is: 1392076800;GBP;CHF;EUR;JPY;USD
String s2 = "1392076800;GBP;CHF;EUR;JPY;USD";
String [] array2 = s2.split(";");
CountryCode cc2 = new CountryCode(array2[1], array2[2], array2[1], array2[4], array2[5]);
if(cc1.equals(cc2)) {
System.out.println("Both CountryCode objects are equal.");
} else {
System.out.println("Both CountryCode objects are NOT equal.");
}
}
}
class CountryCode {
private String countryCode1;
private String countryCode2;
private String countryCode3;
private String countryCode4;
private String countryCode5;
public CountryCode(String countryCode1, String countryCode2,
String countryCode3, String countryCode4, String countryCode5) {
this.countryCode1 = countryCode1;
this.countryCode2 = countryCode2;
this.countryCode3 = countryCode3;
this.countryCode4 = countryCode4;
this.countryCode5 = countryCode5;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((countryCode1 == null) ? 0 : countryCode1.hashCode());
result = prime * result
+ ((countryCode2 == null) ? 0 : countryCode2.hashCode());
result = prime * result
+ ((countryCode3 == null) ? 0 : countryCode3.hashCode());
result = prime * result
+ ((countryCode4 == null) ? 0 : countryCode4.hashCode());
result = prime * result
+ ((countryCode5 == null) ? 0 : countryCode5.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CountryCode other = (CountryCode) obj;
if (countryCode1 == null) {
if (other.countryCode1 != null)
return false;
} else if (!countryCode1.equals(other.countryCode1))
return false;
if (countryCode2 == null) {
if (other.countryCode2 != null)
return false;
} else if (!countryCode2.equals(other.countryCode2))
return false;
if (countryCode3 == null) {
if (other.countryCode3 != null)
return false;
} else if (!countryCode3.equals(other.countryCode3))
return false;
if (countryCode4 == null) {
if (other.countryCode4 != null)
return false;
} else if (!countryCode4.equals(other.countryCode4))
return false;
if (countryCode5 == null) {
if (other.countryCode5 != null)
return false;
} else if (!countryCode5.equals(other.countryCode5))
return false;
return true;
}
}
I have several jqgrids running and all are functioning fine. However, when I do a search, I am only displaying ten search results per page. Whenever there are more than ten results, clicking on page two has no effect on the grid. Here is one of my controller actions, pay particular attention to the if satatement where search is true....
EDIT
I think I may have found a clue as to what may be causing my issue. You see I have several subgrids under the main grid. In terms of my java code I have object-A which has a list of object-B
, thus A has a subgrid of B. The way i am building up the json string to feed to the grid is by iterating over the list of B contained in A. I did not write a query of some kind to say order by, and limit the results etc.
So i guess the real question should be how to build a finder on a collection so that the contents can be arranged and ordered as i wish?
Here is the action I am calling for one of my entities described as B above. Pay particular attention to where i said person.getContacts()
#RequestMapping(value = "contactjsondata/{pId}", method = RequestMethod.GET)
public #ResponseBody String contactjsondata(#PathVariable("pId") Long personId, Model uiModel, HttpServletRequest httpServletRequest) {
Person person = Person.findPerson(personId);
String column = "id";
if(httpServletRequest.getParameter("sidx") != null){
column = httpServletRequest.getParameter("sidx");
}
String orderType = "DESC";
if(httpServletRequest.getParameter("sord") != null){
orderType = httpServletRequest.getParameter("sord").toUpperCase();
}
int page = 1;
if(Integer.parseInt(httpServletRequest.getParameter("page")) >= 1){
page = Integer.parseInt(httpServletRequest.getParameter("page"));
}
int limitAmount = 10;
int limitStart = limitAmount*page - limitAmount;
List<Contact> contacts = new ArrayList<Contact>(person.getContacts());
double tally = Math.ceil(contacts.size()/10.0d);
int totalPages = (int)tally;
int records = contacts.size();
StringBuilder sb = new StringBuilder();
sb.append("{\"page\":\"").append(page).append("\", \"records\":\"").append(records).append("\", \"total\":\"").append(totalPages).append("\", \"rows\":[");
boolean first = true;
for (Contact c: contacts) {
sb.append(first ? "" : ",");
if (first) {
first = false;
}
sb.append(String.format("{\"id\":\"%s\", \"cell\":[\"%s\", \"%s\", \"%s\"]}",c.getId(), c.getId(), c.getContactType().getName() ,c.getContactValue()));
}
sb.append("]}");
return sb.toString();
}
To fix the issue with pagination you need to replace the following block of code
for (Contact c: contacts) {
sb.append(first ? "" : ",");
if (first) {
first = false;
}
sb.append(String.format("{\"id\":\"%s\", \"cell\":[\"%s\", \"%s\", \"%s\"]}",c.getId(), c.getId(), c.getContactType().getName() ,c.getContactValue()));
}
with:
for (int i=limitStart; i<Math.min(records, limitStart+limitAmount); i++){
Contact c = contacts[i];
sb.append(first ? "" : ",");
if (first) {
first = false;
}
sb.append(String.format("{\"id\":\"%s\", \"cell\":[\"%s\", \"%s\", \"%s\"]}",c.getId(), c.getId(), c.getContactType().getName() ,c.getContactValue()));
}
Another option is using loadonce:true to let the jqGrid handle pagination and sorting. In this case you don't need to make changes described above
I apologize if my vocabulary is off on the following question.
I have an SQL Database that has multiple relationships to tables within that database. I've created a DataContext for this database and create a repository of functions used to call it's data.
My question is, because of the relationships (Multiple Linked tables).
Should I create my own class object to hold the results and only grab the needed table's column data like the following:
public IQueryable<VM_userLogs> getUserLogsVM(Nullable<DateTime> startDate, Nullable<DateTime> endDate)
{
if (startDate == null) {
startDate = Convert.ToDateTime("01-01-1900");
}
if (endDate == null) {
endDate = Convert.ToDateTime("01-01-2900");
}
IQueryable<VM_userLogs> logs = from l in ctx.tools_trt_userLogs
where l.timeStamp >= startDate & l.timeStamp <= endDate
select new VM_userLogs {
LOG_ID = l.logId,
NTLOGIN = l.ntLogin,
PRODUCT = l.productName,
SEGMENT = l.segmentName,
PRIORITY = l.priority,
GROUP = l.groupName,
ANSWER = l.answerText,
TIMESTAMP = l.timeStamp,
URL = l.url
};
return logs;
}
or can I just call the underlying object from the datacontext and NOT take a big performance hit... Like the following:
public IQueryable<tools_trt_userLogs> getUserLogs(Nullable<DateTime> startDate, Nullable<DateTime> endDate)
{
if (startDate == null)
{
startDate = Convert.ToDateTime("01-01-1900");
}
if (endDate == null)
{
endDate = Convert.ToDateTime("01-01-2900");
}
IQueryable<tools_trt_userLogs> logs = from l in ctx.tools_trt_userLogs
where l.timeStamp >= startDate & l.timeStamp <= endDate
select l;
return logs;
}
While looking though some code of the project I'm working on, I've come across a pretty hefty method which does
the following:
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
if (data != null)
{
if (data.A == null)
{
data.A = fieldName;
_dataRepository.InsertOrUpdate(data);
return "A";
}
if (data.B == null)
{
data.B = fieldName;
_dataRepository.InsertOrUpdate(data);
return "B";
}
// keep going data.C through data.Z doing the exact same code
}
}
Obviously having 26 if statements just to determine if a property is null and then to update that property and do a database call is
probably very naive in implementation. What would be a better way of doing this unit of work?
Thankfully C# is able to inspect and assign class members dynamically, so one option would be to create a map list and iterate over that.
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
List<string> props = new List<string>();
props.Add("A");
props.Add("B");
props.Add("C");
if (data != null)
{
Type t = typeof(data).GetType();
foreach (String entry in props) {
PropertyInfo pi = t.GetProperty(entry);
if (pi.GetValue(data) == null) {
pi.SetValue(data, fieldName);
_dataRepository.InsertOrUpdate(data);
return entry;
}
}
}
}
You could just loop through all the character from 'A' to 'Z'. It gets difficult because you want to access an attribute of your 'data' object with the corresponding name, but that should (as far as I know) be possible through the C# reflection functionality.
While you get rid of the consecutive if-statements this still won't make your code nice :P
there is a fancy linq solution for your problem using reflection:
but as it was said before: your datastructure is not very well thought through
public String DataField(int id, string fieldName)
{
var data = new { Z = "test", B="asd"};
Type p = data.GetType();
var value = (from System.Reflection.PropertyInfo fi
in p.GetProperties().OrderBy((fi) => fi.Name)
where fi.Name.Length == 1 && fi.GetValue(data, null) != null
select fi.Name).FirstOrDefault();
return value;
}
ta taaaaaaaaa
like that you get the property but the update is not yet done.
var data = _dataRepository.Find(id);
If possible, you should use another DataType without those 26 properties. That new DataType should have 1 property and the Find method should return an instance of that new DataType; then, you could get rid of the 26 if in a more natural way.
To return "A", "B" ... "Z", you could use this:
return (char)65; //In this example this si an "A"
And work with some transformation from data.Value to a number between 65 and 90 (A to Z).
Since you always set the lowest alphabet field first and return, you can use an additional field in your class that tracks the first available field. For example, this can be an integer lowest_alphabet_unset and you'd update it whenever you set data.{X}:
Init:
lowest_alphabet_unset = 0;
In DataField:
lowest_alphabet_unset ++;
switch (lowest_alphabet_unset) {
case 1:
/* A is free */
/* do something */
return 'A';
[...]
case 7:
/* A through F taken */
data.G = fieldName;
_dataRepository.InsertOrUpdate(data);
return 'G';
[...]
}
N.B. -- do not use, if data is object rather that structure.
what comes to my mind is that, if A-Z are all same type, then you could theoretically access memory directly to check for non null values.
start = &data;
for (i = 0; i < 26; i++){
if ((typeof_elem) *(start + sizeof(elem)*i) != null){
*(start + sizeof(elem)*i) = fieldName;
return (char) (65 + i);
}
}
not tested but to give an idea ;)
I was wondering if someone could help me in generating a linq query for the following scenario.
Here are the classes with the relevant properties:
public class Employee
{
IList<Employee> DirectReports { get; set;}
IList<BonusPlan> BonusPlans { get; set;}
BonusPlanTemplate BonusPlanTemplate { get; set;}
}
public class BonusPlan
{
FiscalPeriod FiscalPeriod { get; set; }
Employee Employee { get; set;}
}
I'm trying to create a method:
IEnumerable<Employee> GetDirectReportsWithoutBonusPlansCreatedForFiscalPeriod(FiscalPeriod fiscalPeriod)
So basically I have this to get the directreports with bonus plans for a particular fiscal period:
var query = from dr in DirectReports
from bp in dr.BonusPlans
where bp.Employee.BonusPlanTemplate != BonusPlanTemplate.Empty &&
bp.FiscalPeriod==fiscalPeriod
select dr;
IList<Employee> directReportsWithBonusPlansCreated = query.ToList();
Then I get all of the DirectReports that should have bonus plans setup (indicated by having a BonusPlanTemplate assigned) that aren't in the list from the previous query.
var query2 = from dr in DirectReports
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty &&
!directReportsWithBonusPlansCreated.Contains(dr)
select dr;
This produces the correct results but it seems like there must be another way. I'm not sure if I need to do this in two steps. Can someone please help me to combine these two linq queries and possibly make it more efficient. I have relatively little experience with Linq.
Do you need the first query for any other reason? If not, it's pretty easy:
var query = from dr in DirectReports
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty
&& !dr.BonusPlans.Any(bp => bp.FiscalPeriod == fiscalPeriod)
select dr;
You could make your life easier use an extra method in Employee:
public bool HasBonusPlanForPeriod(FiscalPeriod period)
{
return BonusPlans.Any(bp => bp.FiscalPeriod == fiscalPeriod);
}
Then your original first query becomes:
var query = from dr in DirectReports
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty &&
dr.HasBonusPlanForPeriod(fiscalPeriod)
select dr;
IList<Employee> directReportsWithBonusPlansCreated = query.ToList();
and the second query becomes:
var query = from dr in DirectReports
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty &&
!dr.HasBonusPlanForPeriod(fiscalPeriod)
select dr;
IList<Employee> directReportsWithBonusPlansCreated = query.ToList();
This is a tricky one...first I thought "Oh it's an outer join...use DefaultIfEmpty". Then I realized you were doing a select many (that's what the two from clauses boil down to). So I did a search for DefaultIfEmpty combined with SelectMany and came up with this gem. Applied to your scenario we get
var query =
from dr in DirectReports
from bp in dr.BonusPlans.DefaultIfEmpty()
where dr.BonusPlanTemplate != BonusPlanTemplate.Empty &&
bp.FiscalPeriod==fiscalPeriod &&
bp==null
select dr;
See if that works for you.