Can I execute a scalar query in EF 4.1? - asp.net

Is it possible to execute a scalar-valued query using EF 4.1?
I've tried:
ObjectQuery<int> query = new ObjectQuery<int>("select count(*) from myTable", _context);
var result = query.Execute(MergeOption.NoTracking);
return result.FirstOrDefault();
but it returns an error: The query syntax is not valid. Near term '*'
Is the only way to execute a scalar-valued query to call a stored proc?

It seems to me that you are thinking of entity framework as an "ADO.net 2.0" rather than the ORM that it is.
Rather than using it to execute SQL queries, I'd recommend using the standard entity framework Data container and using a LINQ query, as is intended with entity framework. Then it would simply be something like
myDataContainerInstance.myTable.Count()
ObjectQuery isn't analogous to the ADO.net command and doesn't execute SQL statements. Instead it is used to define queries against the object model directly. The (*) isn't valid because it isn't SQL.

Related

Is it possible to convert DQL query builder to query builder?

I have a tree structure, it is managed by Gedmo\Tree. I want to make complex update for one field in subtree, this update requires join with another table, it is not supported by DQL. So I want to get DQL builder by Gedmo\Tree repository method childrenQueryBuilder, convert it to QueryBuilder and add update statement.
$dqlQueryBuilder = $repository->childrenQueryBuilder($node, ...);
$dqlQueryBuilder->resetDQLParts(['select', 'orderBy']);
$queryBuilder = convert($dqlQueryBuilder);
$queryBuilder->leftJoin('...', 'lj');
$queryBuilder->update('node.update', 'concat(node.field, lj.field)');
I know that I can write custom QueryBuilder, I just wonder if such conversions are possible by doctrine builtin tools or some 3-rd party libraries.
There's no such thing as SQLQueryBuilder in Doctrine, there's only QueryBuilder which is an DQL Query Builder. What you can do is to convert DQL to SQL by doing
$stringSql = $queryBuilder->getQuery()
->getSQL();
Once you have it you might play with native sql and then execute it as a raw sql.
Note: I'm not sure what exact DB Specific statement you mean, but there's a possibility to map DB Specific functions to DQL by making use of FunctionNode class. Once you have your function mapped to DQL you might accomplish it with DQL only.
Check documentation on how to work with custom DB functions in DQL

Tables with schema using SqliteDialect.Provider

In my test project I register a connection using ":memory" connection string and SqliteDialect.Provider as provider. When trying to run tests that execute arbitrary sql (I have a complex join statement so I cannot use a typed query) I get an error that the table do not exist. In my query I print "SELECT * FROM xxx.Table1" but when looking at the code generated from a typed query I can see that it is "SELECT * FROM xxx_Table1". I need to use schemas for the production code, so is there a way to force ORMLite for Sqlite to generate schemas and not just name prefixes when using the attribute [Schema("xxx")] on my domain models?
SQLite doesn't have schemas so they're simulated by prefixing the schema name before the table name. However this should be a transparent implementation detail for SQLite :memory: DBs as the same table name will be used when creating or querying the table.
If you're creating Custom SQL you should use the tableName returned from:
var modelDef = typeof(Table1).GetModelMetadata();
var tableName = db.GetDialectProvider().GetTableName(modelDef);
var sql = $"SELECT * FROM {tableName}";

Entity Framework 5, Code First, Full Text Search but IQueryable via CreateQuery?

I am using .NET 4.5 and EF 5 with Code First approach and now I need to implement Full Text Search.
I have already read a lot about it and so far my conclusions are:
Stored procedures nor Table Value Functions can not be mapped with Code First.
Still I can call them using dynamic sql
dbContext.Database.SqlQuery<Movie>(Sql, parameters)
But this returns IEnumerable and I want IQueryable so that I can do more filtering before fetching the data from db server. I know I can send those parameters to Db function but I don't want that.
What I have found that could fulfill my needs is CreateQuery function from IObjectContextAdapter that looks like this(Select All just for test):
IQueryable<Movie> result = ((IObjectContextAdapter)dbContext).ObjectContext.CreateQuery<Movie>("SELECT * FROM Movie");
However executing this throws Exception"
'System.Data.EntitySqlException was unhandled
HResult=-2146232006
Message=The query syntax is not valid. Near term '*', line 1, column 9.'
So the questions are:
Why do I get this exception and can it be fixed ?
If not is there any way with Code First to do FTS that returns IQueryable ?
Try it like this
ObjectQuery<Movie> query =
objectContext.CreateQuery<Movie>(#"SELECT VALUE movie FROM Movies");
As for why see these links
Differences from Transact-SQL Unlike Transact-SQL, Entity SQL does not
support use of the * argument in the SELECT clause. Instead
Entity SQL Reference - SELECT
"SELECT VALUE" - value keyword in LINQ/Entity Framework query

Entity Framework - Where Clause

Let's say i have a table named User.
When I use the Entity Framework to get the records i do like this:
var db = new Context();
var users = db.Users;
It return all the users in my table. OK. If i do this:
var fooUsers = db.Users.Where(u => u.Name == 'foo');
It will give me all the users with name 'foo'. OK. My question is:
The entity framework make a query like:
select * from user where name = 'foo'
Or it load all the users and filter them on the server with lambda expression?
The Sql submitted to your database will contain your where clause. You can use SQL Server Profiler to watch as queries are submitted to your DB.
Entity Framework will translate such a query into a "Store Expression." That is, it will generate a database query -- assuming your data storage is a database -- that will be somewhat similar to the query you included in your question. It very well may name the columns, however, and there are likely to be some other differences.
From here http://msdn.microsoft.com/en-us/library/cc853327.aspx
When you create an ObjectQuery or LINQ query, the query may not be executed immediately. Query execution is deferred until the results are needed, such as during a foreach (C#) or For Each (Visual Basic) enumeration or when it is assigned to fill a List collection. Query execution begins immediately when you call the Execute method on an ObjectQuery or when you call a LINQ method that returns a singleton query, such as First or Any. For more information, see Object Queries and Query Execution (LINQ to Entities).
So when your query has a WHERE clause it will just load the results filtered by the database with the where.

Is this LINQ statment vulnerable to SQL injection?

Is this LINQ statment vulnerable to SQL injection?
var result = from b in context.tests
where b.id == inputTextBox.Text
select b;
where context is an Entity and tests is a table.
I'm trying to learn LINQ and I thought that the benefit of it was that it wasn't vulnerable to sql injection, but some stuff I've see has said differently. Would I need to parametrize this LINQ statement to make it safer? If so, How?
Also would this be considered linq to sql or linq to entities?
Short answer: LINQ is not vulnerable to SQL injection.
Long answer:
LINQ is not like SQL. There's a whole library behind the scenes that builds SQL from expression trees generated by compiler from your code, mapping the results to objects—and of course it takes care of making things safe on the way.
See LINQ to SQL FAQ:
Q. How is LINQ to SQL protected from
SQL-injection attacks?
A. SQL injection has been a significant risk for traditional SQL
queries formed by concatenating user
input. LINQ to SQL avoids such
injection by using SqlParameter in
queries. User input is turned into
parameter values. This approach
prevents malicious commands from being
used from customer input.
Internally, it means that when LINQ to SQL queries the database, instead of using plain values, it passes them as SQL parameters, which means they can never be treated as executable code by the database. This is also true for most (if not all) ORM mappers out there.
Compare these two approaches (totally pseudo-code):
string name = "' ; DROP DATABASE master --"
run ("SELECT * FROM Authors WHERE Name = '" + name + "'") // oops!
// now we'd better use parameters
SqlParameter name = new SqlParameter ("#name", "' ; DROP DATABASE master --")
run ("SELECT * FROM Authors WHERE Name = #name", name) // this is pretty safe
I suggest you dive deeper into what LINQ statements actually mean and when and how they get translated to the real SQL. You may want to learn about LINQ standard query operator translation, deferred execution, different LINQ providers et cetera. In case of LINQ, much like any abstraction technology, it is both fascinating and incredibly useful to know what's happening behind the scenes.
P.S. Everytime I see a question about SQL injection I can't help but remember this webcomic.
LINQ uses parameterized queries so it is not generally susceptible to SQL injection. Your example, for instance, isn't vulnerable.
The LINQ to Entities provider uses parametrized queries and is completely safe against SQL injection.
No. LINQ to Entities and LINQ to SQL handle the generation of SQL Queries to avoid SQL Injection. You can use LINQPad if you're curious to see what SQL statement gets generated when you run this query with various inputs.
Whether it's LINQ to SQL or LINQ to Entities depends on what your context object is, and cannot be determined from this code snippet.
The only time you need to worry about SQL injection in LINQ is if you're using the ExecuteQuery method to run a custom SQL query (see here). But at that point, you've moved away from the Language-INtegrated Query, and back into the world of generating your own strings.
LINQ To SQL generates a parameterised query so it protects against SQL injection attacks
Linq paramaterizes all queries, so isn't susceptible to SQL injection attacks. However you should still validate all of your user input as otherwise you will leave yourself open to cross site scripting attacks.

Resources