How to use #JDBCDBColumn for typ ahead in xpages - oracle

Using Notes 9 and extension library's data controls...
I want to use the #JDBCDbColumn() to get the type ahead values from an Oracle table.
Is that possible at all? Does it work the same way the standard DBColumn in the type ahead?
Note that the DBColumn is looking in a huge table, but I specify a where clause that should filter what the JDBCDBColumn returns.
Somehow, nothing happens. Work sfine with Notes data though, but I need to get this working with the Oracle data.
Thanks!
Update 1: Code I have...
#JdbcExecuteQuery(
"oracle",
"select distinct postal_code from cifadmin.postal_codes where postal_code like '"
+ getComponent("CodePostal").getValue() + "%'")
Update 2: Here is the code I have right now, but it doesn't return anything:
var CodePostal = getComponent("rsSearchQuery").getValue();
if(!!CodePostal) {
var params = [CodePostal];
var a = #JdbcDbColumn("oracle", "postal_codes", "postal_code", "postal_code like ?", params);
return #Unique(a);
} else {
return "--";
}

OK, I got it working thanks to all your comments and a bit of intuition!!!
Here is the working code:
var sql = "SELECT DISTINCT POSTAL_CODE FROM cifadmin.POSTAL_CODES WHERE POSTAL_CODE LIKE'" + getComponent("PostalCode").getValue() +"%' ORDER BY POSTAL_CODE";
var res = #JdbcExecuteQuery("oracle", sql);
var values = new Array();
while (res.next()) {
values.push(res.getString("POSTAL_CODE"));
}
return values;
The thing that got it working was when I have forced 'values' as an array. Without that, it just doesn't work.
Picky and sensitive, XPages are!!!
Thanks to all for your help ;)

Just tested it the first time ever: works fine for me except I didn't use a WHERE clause in my sample and another type of DB here.
<xp:inputText id="inputText1" styleClass="form-control">
<xp:typeAhead mode="partial" minChars="1" ignoreCase="true">
<xp:this.valueList><![CDATA[#{javascript:#JdbcDbColumn("postgres", "xpagesdemo.names", "lastname")}]]></xp:this.valueList>
</xp:typeAhead>
</xp:inputText>
See live demo here: http://www.notesx.net/postgres.nsf/typeahead.xsp

Ben, I think you mean you want to put the wildcard to the end of the parameter? Not sure of your data and if you are entering an exact match? Did you try:
var params = [CodePostal+ "%"];
Also, not sure if you need to enter "cifadmin.postal_codes" for your table as you did in your sql?
Howard

Related

Google AppMaker: Fetch a MAX value

I am not able to fetch a max value from a number field in AppMaker. The field is filled with unique integers from 1 and up. In SQL I would have asked like this:
SET #tKey = (SELECT MAX(ID) FROM GiftCard);
In AppMaker I have done the following (with a bit help from other contributors in this forum) until now, and it returns tKey = "NaN":
var tKey = google.script.run.MaxID();
function MaxID() {
var ID_START_FROM = 11000;
var lock = LockService.getScriptLock();
lock.waitLock(3000);
var query = app.models.GiftCard.newQuery();
query.sorting.ID._descending();
query.limit = 1;
var records = query.run();
var next_id = records.length > 0 ? records[0].ID : ID_START_FROM;
lock.releaseLock();
return next_id;
}
There is also a maxValue() function in AppMaker. However, it seems not to work in that way I use it. If maxvalue() is better to use, please show :-)
It seems that you are looking in direction of auto incremented fields. The right way to achieve it would be using Cloud SQL database. MySQL will give you more flexibility with configuring your ids:
ALTER TABLE GiftCard AUTO_INCREMENT = 11000;
In case you strongly want to stick to Drive Tables you can try to fix your script as follow:
google.script.run
.withSuccessHandler(function(maxId) {
var tKey = maxId;
})
.withFailureHandler(function(error) {
// TODO: handle error
})
.MaxID();
As a side note I would also recommend to set your ID in onBeforeCreate model event as an extra security layer instead of passing it to client and reading back since it can be modified by malicious user.
You can try using Math.max(). Take into consideration the example below:
function getMax() {
var query = app.models.GiftCard.newQuery();
var allRecords = query.run();
allIds = [];
for( var i=0; i<allRecords.length;i++){
allIds.push(allRecords[i].ID);
}
var maxId = Math.max.apply(null, allIds);
return maxId;
}
Hope it helps!
Thank you for examples! The Math.max returned an undefined value. Since this simple case is a "big" issue, I will solve this in another way. This value is meant as a starting value for a sequence only. An SQL base is better yes!

How to make Case-In-Sensitive with Linq

EDIT:
Also like to know:
what if; if i have a data that is not upper case? or have mixed of upper or lower case? how you will handle this?
i am trying to query my resultset
IQueryable<CategoryObject> filteredCategories = _catRepo.GetAllEmployees();
filteredCategories = filteredCategories.Where(c=> c.CategoryName.Contains("Blocks"));
However, i don't get any result becuase the CategoryName is For(Upper Case) in the database. I have no idea how to use contains to filter case insensitive string? I want basically if someone type like;
filteredCategories = filteredCategories.Where(c=> c.CategoryName.Contains("Blocks"));
OR
filteredCategories = filteredCategories.Where(c=> c.CategoryName.Contains("blocks"));
OR
filteredCategories = filteredCategories.Where(c=> c.CategoryName.Contains("blocKS"));
The result should be the same
Try
filteredCategories = categoriesList.Where(c=> c.CategoryName.ToUpper().Contains("BLOCKS"));
That'll remove any case issues.
You can also try:
filteredCategories = categoriesList.Where(c=> c.CategoryName.IndexOf("blocks", StringComparison.OrdinalIgnoreCase) != -1);
First way, as said before - use ToUpper():
var filterString = "bLoCkS"
filteredCategories = categoriesList.Where(c=> c.CategoryName.ToUpper().Contains(filterString.ToUpper()));
Another way - use Case Insensetive collation (Changing SQL Server collation to case insensitive from case sensitive?) in your database (table, field).

How to query for columns in EF using a list of column names as string?

Let's say I have a table that I can query with EF + LINQ like this:
var results = dbContext.MyTable.Where(q => q.Flag = true);
Then, I know that if I want to limit the columns returned, I can just add a select in that line like this:
var results = dbContext.MyTable
.Select(model => new { model.column2, model.column4, model.column9 })
.Where(q => q.Flag == true);
The next step that I need to figure out, is how to select those columns dynamically. Said another way, I need to be able to select columns in a table withoutknowing what they are at compile time. So, for example, I need to be able to do something like this:
public IEnumerable<object> GetWhateverColumnsYouWant(List<string> columns = new List<string{ "column3", "column4", "column999"})
{
// automagical stuff goes here.
}
It is important to keep the returned record values strongly typed, meaning the values can't just be dumped into a list of strings. Is this something that can be accomplished with reflection? Or would generics fit this better? Honestly, I'm not sure where to start with this.
Thanks for any help.
I think you want some dynamic linq, Im no expert on this but i THINK it will go something like this
public static IEnumerable<object> GetWhateverColumnsYouWant(this IQueriable<T> query, List<string> columns = new List<string{ "column3", "column4", "column999"})
{
return query.Select("new (" + String.Join(", ", columns) + ")");
}
See scott Gu's blog here http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx and this question System.LINQ.Dynamic: Select(" new (...)") into a List<T> (or any other enumerable collection of <T>)
You could probably also do this by dynamically composing an expression tree of the columns youre wanting to select but this would be substantially more code to write.

Multiple rows update without select

An old question for Linq 2 Entities. I'm just asking it again, in case someone has came up with the solution.
I want to perform query that does this:
UPDATE dbo.Products WHERE Category = 1 SET Category = 5
And I want to do it with Entity Framework 4.3.1.
This is just an example, I have a tons of records I just want 1 column to change value, nothing else. Loading to DbContext with Where(...).Select(...), changing all elements, and then saving with SaveChanges() does not work well for me.
Should I stick with ExecuteCommand and send direct query as it is written above (of course make it reusable) or is there another nice way to do it from Linq 2 Entities / Fluent.
Thanks!
What you are describing isnt actually possible with Entity Framework. You have a few options,
You can write it as a string and execute it via EF with .ExecuteSqlCommand (on the context)
You can use something like Entity Framework Extended (however from what ive seen this doesnt have great performance)
You can update an entity without first fetching it from db like below
using (var context = new DBContext())
{
context.YourEntitySet.Attach(yourExistingEntity);
// Update fields
context.SaveChanges();
}
If you have set-based operations, then SQL is better suited than EF.
So, yes - in this case you should stick with ExecuteCommand.
I don't know if this suits you but you can try creating a stored procedure that will perform the update and then add that procedure to your model as a function import. Then you can perform the update in a single database call:
using(var dc = new YourDataContext())
{
dc.UpdateProductsCategory(1, 5);
}
where UpdateProductsCategory would be the name of the imported stored procedure.
Yes, ExecuteCommand() is definitely the way to do it without fetching all the rows' data and letting ChangeTracker sort it out. Just to provide an example:
Will result in all rows being fetched and an update performed for each row changed:
using (YourDBContext yourDB = new YourDBContext()) {
yourDB.Products.Where(p => p.Category = 1).ToList().ForEach(p => p.Category = 5);
yourDB.SaveChanges();
}
Just a single update:
using (YourDBContext yourDB = new YourDBContext()) {
var sql = "UPDATE dbo.Products WHERE Category = #oldcategory SET Category = #newcategory";
var oldcp = new SqlParameter { ParameterName = "oldcategory", DbType = DbType.Int32, Value = 1 };
var newcp = new SqlParameter { ParameterName = "newcategory", DbType = DbType.Int32, Value = 5 };
yourDB.Database.ExecuteSqlCommand(sql, oldcp, newcp);
}

Using LINQ to SQL and chained Replace

I have a need to replace multiple strings with others in a query
from p in dx.Table
where p.Field.Replace("A", "a").Replace("B", "b").ToLower() = SomeVar
select p
Which provides a nice single SQL statement with the relevant REPLACE() sql commands.
All good :)
I need to do this in a few queries around the application... So i'm looking for some help in this regard; that will work as above as a single SQL hit/command on the server
It seems from looking around i can't use RegEx as there is no SQL eq
Being a LINQ newbie is there a nice way for me to do this?
eg is it possible to get it as a IQueryable "var result" say and pass that to a function to add needed .Replace()'s and pass back? Can i get a quick example of how if so?
EDIT: This seems to work! does it look like it would be a problem?
var data = from p in dx.Videos select p;
data = AddReplacements(data, checkMediaItem);
theitem = data.FirstOrDefault();
...
public IQueryable<Video> AddReplacements(IQueryable<Video> DataSet, string checkMediaItem)
{
return DataSet.Where(p =>
p.Title.Replace(" ", "-").Replace("&", "-").Replace("?", "-") == checkMediaItem);
}
Wouldn't it be more performant to reverse what you are trying to do here, ie reformat the string you are checking against rather than reformatting the data in the database?
public IQueryable<Video> AddReplacements(IQueryable<Video> DataSet, string checkMediaItem)
{
var str = checkMediaItem.Replace("-", "?").Replace("&", "-").Replace("-", " "));
return DataSet.Where(p => p.Title == str);
}
Thus you are now comparing the field in the database with a set value, rather than scanning the table and transforming the data in each row and comparing that.

Resources