C sharp Dapper ms access query like parameters - ms-access

I have a list of parameters : numericPartList : 029%, 035% for example.
As mentioned in the code, with only 1 parameter it works, but more, no...
public static List<tLicencie> GetDepartement(List<string> numericPartList)
{
ConnectionStringSettings connex = ConfigurationManager.ConnectionStrings["MaConnection"];
string connString = connex.ProviderName + connex.ConnectionString;
using (OleDbConnection con = new OleDbConnection(connString))
{
string sql;
if (numericPartList.Count < 2)
{
sql = "select * from tLicencie where NOCLUB like #numericPartList "; // Works !
}
else
{
sql = "select * from tLicencie where NOCLUB like #numericPartList "; // Does not Work
}
return (List<tLicencie>)con.Query<tLicencie>(sql, new { numericPartList });
}
}
I get an error message :
Syntax error (comma) in expression 'NOCLUB like (# numericPartList1, # numericPartList2)'. "
How to solve this problem?
A solution for the moment: I add DapperExtentions then
var pga = new PredicateGroup { Operator = GroupOperator.Or, Predicates = new List<IPredicate>() };
pga.Predicates.Add(Predicates.Field<tLicencie>(f => f.NOCLUB, Operator.Like, "029%"));
pga.Predicates.Add(Predicates.Field<tLicencie>(f => f.NOCLUB, Operator.Like, "035%"));
IEnumerable<tLicencie> list = con.GetList<tLicencie>(pga);

The dapper list expansion is only intended for use with in, i.e. it would expand:
where foo in #x
to
where foo in (#x0, #x1, #x2)
(or some other variants, depending on the scenario).
It cannot be used with like in this way, as it will give invalid SQL; you would need to compose your SQL and parameters in a more manual fashion, perhaps using DynamicParameters which works more like a dictionary; i.e. you would need to loop in such a way as to construct
where (foo like #x0 or foo like #x1 or foo like #x2)

Related

how hibernate deal with like keyword in query sentence

Here met a hesitation about the way hibernate dealing with like keyword in query sentence.This's a small snippet in DaoImpl and see it first:
public List<T> findBySQL(String sql, String... params){
SQLQuery query = getSession().createSQLQuery(sql);
query.addEntity(clazz);
for (int i = 0; i < params.length; i++){
query.setParameter(i, params[i]);
}
List<T> list = query.list();
return list;
}
ok! without any doubt and use it in below controller:
#RequestMapping(value = "/getFirst/{var}", produces = "application/json; charset=utf-8")
public #ResponseBody Site getFirst(#PathVariable String var){
String fr = "select * from Food f where f.resname = ?";
List<Site> siteList = siteService.findBySQL(fr, var);
Site first = siteList.get(0);
return first;
}
here is the result:{"src":"http://p0.meituan.net/350.214/deal/ac8ba922d7a6030325976fb31e51b4ce38985.jpg","resname":"哈哈派"}
but when i change such sql sentence like this using like and without amending anything else:
String fr = "select * from Food f where f.resname like '%?%'";
List<Site> siteList = siteService.findBySQL(fr, var);
redeploy and run, exception appear:
HTTP Status 500 - Request processing failed; nested exception is org.hibernate.QueryParameterException: Position beyond number of declared ordinal parameters. Remember that ordinal parameters are 1-based! Position: 1
but i don't think it's the parameter index problem, maybe something error or maybe like can not be used like such way? so i wonder how hibernate deal with 'like' keyword?
You should add the wildchar(%) to the parameter and not the query. So modify your query as below.
String fr = "select * from Food f where f.resname like ? ";
List<Site> siteList = siteService.findBySQL(fr, "%"+var+"%");
OR
String fr = "select * from Food f where f.resname like ? ";
List<Site> siteList = siteService.findBySQL(fr, new String[]{"%"+var+"%"});

PDO query does not return data when inserting date as variable

Im trying to get a hold of OOP and PDO. Did some tutorials. In the tutorial i got the query method (so thats not mine...)
but im having troubles with a pdo query
I want to select orders from the database matching a date..... de date comes from a datepicker and returns 2012-12-16 for example therefor
$dateInputQuery = date("Y-m-d", strtotime(Input::get('datepick')));
$data = $order->getAllOrders('order', 'WHERE DATE(orderdate) = DATE({$dateInputQuery})', false, false);
the strange thing is that when i replace the WHERE clause to WHERE DATE(orderdate) = \'2013-12-16\' it returns all the data but when inserting my date like above it does not....
in the db class the method looks like this
public function getAll($table, $where = NULL, $orderSort = NULL, $limit = NULL) {
$this->query("SELECT * FROM {$table} {$where} {$orderSort} {$limit}")->error();
return $this;
}
and query method in db class
public function query($sql, $params = array()) {
//reset error
$this->_error = false;
if ($this->_query = $this->_pdo->prepare($sql)) {
$x = 1;
if (count($params)) {
foreach ($params as $param) {
$this->_query->bindValue($x,$param);
$x++;
}
}
if ($this->_query->execute()) {
$this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
} else {
$this->_error = true;
}
}
return $this;
}
why is this ?
Your immediate problem is caused the fact that $dateInputQuery is unquoted. Date is a string literal and should be quoted. And even though you can easily add quotes around it you really shouldn't do this. See next point.
order is a reserved word in MySQL, therefore the table name should be put in backticks
$data = $order->getAllOrders('`order`', "WHERE DATE(orderdate) = DATE('$dateInputQuery')", false, false);
^ ^ ^ ^
You're not leveraging parameter binding in query() function. Instead on top of it you're using query string interpolation leaving your code vulnerable to sql injections and diminishing the usage of prepared statements. When you use parameter binding you no longer need to quote parameter values.
Your sql query is not index-friendly. You shouldn't apply any functions (in your case DATE()) to the column you're searching on (orderdate). Instead you can rewrite your condition to apply necessary transformations/calculations to the arguments which are constants.
You should avoid using SELECT *. Read Which is faster/best? SELECT * or SELECT column1, colum2, column3, etc and Why is using '*' to build a view bad?
That being said your query should look something like
$sql = "SELECT order_id, orderdate, ...
FROM `order`
WHERE orderdate >= ?
AND orderdate < ? + INTERVAL 1 DAY";
And you should execute it
$this->query($sql, array($dateInputQuery, $dateInputQuery));
Instead of passing whole clauses (e.g. WHERE) you should pass values

Rails Search 3.2 Returns all instead of specific Query

I have a simple search method installed in my Rails app that I want to be called from ajax, in another controller view.
Right now one looks like so:
class CensusController < ApplicationController
def search
#census = Census.where("'NBRHD_NAME' like ?", "%#{params[:search]}%")
render :json => #census.to_json
end
end
And in my other View/Controller
google.maps.event.addListener(kmlLayer, 'click', function(kmlEvent) {
var text = kmlEvent.featureData.name;
var offset = kmlEvent.latLng;
showInInfoWindow(text, offset);
map.panTo(kmlEvent.latLng);
map.setZoom(13);
//console.log(kmlEvent);
showInContentDiv(text);
});
function showInInfoWindow(text, offset) {
var content = "<div>" + text + "</div>";
var infoWindow = new google.maps.InfoWindow({
content: content,
position: offset
});
infoWindow.open(map);
}
function showInContentDiv(neighborName) {
var query = neighborName;
var url = "census/search?query=" + query;
$.getJSON(url, function(data) {
console.log(url);
var neigh = data;
for (var i in neigh.object)
{
console.log(neigh);
}
});
I just want the neighborhood name returned and matched to the one in my database, instead all Database names are returned in the JSON format. Is there something I am doing wrong?
Again I am running Rails 3.2 with MySQL2 gem
SQL uses single quotes for string literals so this query:
#census = Census.where("'NBRHD_NAME' like ?", "%#{params[:search]}%")
is really asking for all rows where the string literal 'NBRHD_NAME' contains params[:search]. Presumably you want to look at the column NBRHD_NAME rather than the string 'NBRHD_NAME' so you should say:
#census = Census.where("`NBRHD_NAME` like ?", "%#{params[:search]}%")
or
#census = Census.where("NBRHD_NAME like ?", "%#{params[:search]}%")
AFAIK, MySQL's case sensitivity for columns depends on the configuration so you should use the backticked version to be safe if you're working with column names that really were created in upper case. Note that backtick-quoting for SQL identifiers is a MySQLism, standard SQL uses double quotes ("NBRHD_NAME") for such purposes and SQL Server uses brackets ([NBRHD_NAME]).
I just noticed this in your JavaScript:
var url = "census/search?query=" + query;
That would suggest that params[:query] contains what you're looking for but your controller is looking at params[:search]. The result is that your SQL says like '%%'. So fix up your quoting and then look at the right thing in params:
#census = Census.where("`NBRHD_NAME` like ?", "%#{params[:query]}%")

exception in Linq to sql

my query is :
var ReadAndUnreadMessages =
(from m in MDB.Messages
orderby m.Date descending
where m.ID_Receive == (Guid)USER.ProviderUserKey && m.Delete_Admin == false
select new AllMessages()
{
id = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Message,
parent = (Guid)(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Message_Parent,
sender = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Sender,
receiver = (Guid)USER.ProviderUserKey,
subject = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Subject.Subject1.ToString() == "Other" ?
(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Other_Subject
:
(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Subject.Subject1.ToString(),
body = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body.Length > 26 ?
(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body.Substring(0, 25) + "..."
:
(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body,
date = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Date.ToShortDateString(),
read =(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).IsRead,
finished = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).IsFinished,
count = MessageClass.LoadAll(m.ID_Message).Count
}).ToList();
and exception is :
The argument 'value' was the wrong type. Expected 'Message'. Actual 'System.Object'.
what does meaning it?
LoadMessageChildren :
public static ArrayList LoadMessageChildren(Guid Parent)
{
ArrayList arr = new ArrayList();
Guid id = Parent;
while (id != Guid.Empty)
{
arr.Add(LoadMessage(id));
try
{
id = (Guid)MDB.Messages.Single(a => a.ID_Message_Parent == id).ID_Message;
}
catch
{
id = Guid.Empty;
}
}
return arr;
}
LoadMessage :
public static Message LoadMessage(Guid id)
{
var mess = from m in MDB.Messages
where m.ID_Message == id
select m;
return mess.Single();
}
The code is unreadable, and as a bad case of code repetition (and multiple executions of LoadMessageChildren).
For starters, consider the following:
from m in MDB.Messages
orderby m.Date descending
where m.ID_Receive == (Guid)USER.ProviderUserKey && m.Delete_Admin == false
let children = LoadMessageChildren(m.ID_Message)
let lastChildMessage = children.Last()
select new AllMessages()
{
id = lastChildMessage.ID_Message,
...
}
This may solve your problem, as it is might be caused by using the [] indexer.
Aside from that, it is not clear the posted code is causing the exception.
The only thing I see you using LoadChildMessages() for in the end is to get the child message count... Unless I am wrong I would think you could write it as a join. You doing a lot of queries with in queries that don't seem necessary and are probably causing multiple hits to the database. My question to that would be why isn't there a relationship in your dmbl/sql database so that LinqToSql knows to create a property as a List<Message> ChildMessages
But here is my take:
var query = from message in MDB.Messges
join childmessage in MDB.Messages.Where(child => child.ID_Message_Parent == message.ID_Message) into childMessages
from childMessage in childMessages.DefaultIfEmpty() // This creates a
// left outer join so you get parent messages that don't have any children
where message.ID_Receive == (Guid)USER.ProviderUserKey && message.Delete_Admin == false
select new AllMessages()
{
id = message.ID_Message,
parent = message.ID_Message_Parent,
sender = message.ID_Sender,
receiver = (Guid)USER.ProviderUserKey,
subject = message.Subject.Subject1.ToString() == "Other" ?
message.Other_Subject
:
message.Subject.Subject1.ToString(),
body = message.Body.Length > 26 ?
message.Body.Substring(0, 25) + "..."
:
message.Body,
date = message.Date.ToShortDateString(),
read =message.IsRead,
finished = message.IsFinished,
count = childMessage.Count() // This might have to be this
//count = childMessage == null ? 0 : childMessage.Count()
};
var ReadAndUnreadMessages = query.ToList();
But it's hard to say because I can't run the code... Please respond and let me know if this works.
Note: May I suggest using a class that links to your DataContext.Log property that writes the generated TSQL code to the debugger window. Here is an article on writing your own. It has really help me know when I am making unnecessary calls to the database.
The error is most likely caused by the use of the ArrayList.
The problem is that LINQ was designed to work with generic collections that implement the System.Collections.Generic.IEnumerable<T> interface. The ArrayList is a nongeneric collection that internally stores everything as an Object. So when you retrieve something from the ArrayList you need to cast it to a Message.
Looking at your error message it looks like somewhere a Message object is expected, but the instance in your ArrayList (an Object) is not casted to a Message object when that reference occurs. Also, the ArrayList does not implement the IEnumerable<T> interface which might get you into trouble in certain situations also.
How to fix it?
I suggest changing the implementation of your LoadMessageChildren to use a generic list (List<Message>):
public static List<Message> LoadMessageChildren(Guid Parent)
{
List<Message> arr = new List<Message>();
Guid id = Parent;
while (id != Guid.Empty)
{
arr.Add(LoadMessage(id));
try
{
id = (Guid)MDB.Messages.Single(a => a.ID_Message_Parent == id).ID_Message;
}
catch
{
id = Guid.Empty;
}
}
return arr;
}
You will have to make also change the code that interacts with the generic list in terms of retrieving/referencing items. But that is just syntax. Since equivalent methods for dealist with lists and items exist.
There are also advantages in terms of performance and compile-time validation for switching from ArrayList to List<T>. The ArrayList is basically an inheritance from version 1.0 of the .Net Framework when there was no support for generics and it just get kept in the framework probably for compatibility reasons.
There are greater benefits for using generics.
UPDATED ANSWER:
The "Method 'System.Collections.Generic.List'1[Message] LoadMessageChildren(System.Guid)' has no supported translation to SQL" exception that you are getting is caused by the fact that your LoadMessageChildren method is not mapping to a stored procedure or a user defined function in your database.
You cannot have any regular C# method call inside your LINQ to SQL queries. The LINQ to SQL object model interprets a method found inside your query as either a stored procedure or a user defined function. So the engine is basically looking for a method called LoadMessageChildren that maps to a stored procedure or a user defined function in your database. Because there are no mappings, it tells you that no supported translation to SQL was found. The LINQ to SQL object model link shows you how to use method attributes to map a method that executes a stored procedure.
You have a few choices now:
create stored procedures of your regular C# method calls
rewrite your LINQ query to use joins to select child messages

Linq: Simple Boolean function returns linq Exception

I have a Linq query that looks something like this:
var query = from x in table where SomeFunctionReturnsBool() select;
private bool SomeFunctionReturnsBool()
{
return true;
}
This returns and exception that says "SomeFunctionReturnsBool has no supported translation to SQL". I get that this is because it wants to treat "SomeFunctionReturnsBool" as an expression to evaluate as SQL, but it can't.
Although this Linq query isn't complicated, the real ones are. How can I accomplish what I'm trying to do here, which is to break out pieces of the query to hopefully make it more readable?
Jeff
UPDATE
Good answers. I am trying now to work with expressions instead, but this code gets me "cannot resolve method Where(lambda expression)":
var query = from x in table where SomeFunctionReturnsBool() select x;
private Expression<Func<EligibilityTempTable, bool>> SomeFunctionReturnsBool
{
return (x) => true;
}
Another way is to use Expression<Func<YourType, bool>> predicate...
var query = from x in table where SomeFunctionReturnsBool() select;
Edit: I don't usually do it the way I've shown above... I was just getting that from the code above. Here is the way I usually implement it. Because then you can tack on additional Enumerable methods or comment them out during debugging.
var results = table.Where(SomeFunctionReturnsBool())
.OrderBy(yt => yt.YourProperty)
//.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts...
//.Take(pageSize)
.ToList(); //Finally executes the query...
private Expression<Func<YourType, boo>> SomeFunctionReturnsBool()
{
return (YourType yt) => yt.YourProperty.StartsWith("a")
&& yt.YourOtherProperty == true;
}
I prefer to use the PredicateBuilder which allows you to build an expression to be used in your Where...
You can do this in LINQ-to-SQL by creating a UDF mapped to the data-context; this involves writing TSQL, and use ctx.SomeFunctionblah(...).
The alternative is to work with expression trees - for example, it could be:
Expression<Func<Customer, bool>> SomeFunc() {
return c => true; // or whatever
}
and use .Where(SomeFunc()) - is that close enough? You can't use the query syntax in this case, but it gets the job done...
Added dodgy Where method to show how you might use it in query syntax. I don't suggest this is fantastic, but you might find it handy.
using System;
using System.Linq;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
using (var ctx = new NorthwindDataContext())
{
ctx.Log = Console.Out;
// fluent API
var qry = ctx.Customers.Where(SomeFunc("a"));
Console.WriteLine(qry.Count());
// custom Where - purely for illustration
qry = from c in ctx.Customers
where SomeFunc("a")
select c;
Console.WriteLine(qry.Count());
}
}
static IQueryable<T> Where<T>(this IQueryable<T> query,
Func<T, Expression<Func<T, bool>>> predicate)
{
if(predicate==null) throw new ArgumentNullException("predicate");
return query.Where(predicate(default(T)));
}
static Expression<Func<Customer, bool>> SomeFunc(string arg)
{
return c => c.CompanyName.Contains(arg);
}
}
Basically, "out of the box", you can't have LINQ-to-SQL execute queries that have custom functions in them. In fact only some native methods that can be translated to SQL can be used.
The easiest way around this can unfortunately affect performance depending on how much data you're bringing back from the DB.
Basically, you can only use custom functions in WHERE statments if the data has already been loaded into memory, i.e, SQL have already executed.
The quickest fix for your example would look like this:
var query = from x in table.ToList() where SomeFunctionReturnsBool() select;
Notice the ToList(). It executes the SQL and puts the data into memory. You can now do whatever you want in the WHERE statement/method.
I would just break them out like so:
Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true;
var query = from x in table where someTreeThatReturnsBool select x;
You could create functions that pass around expression trees.
Don't use query syntax for this.
var query = table.Where( x => SomeFunction(x) );