I have an issue that's causing me a lot of headache. I've already googled a solution some days ago, but I didn't found it yet, if one of you guys could help me, it would be great!
I have this method to take the SQL statement for me:
private static string GetClause<T>(IQueryable<T> clause) where T : BaseEntity
{
string snippet = "FROM [dbo].[";
string sql = clause.ToString();
string sqlFirstPart = sql.Substring(sql.IndexOf(snippet));
sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", "");
sqlFirstPart = sqlFirstPart.Replace("[Extent1].", "");
return sqlFirstPart;
}
But this doesn't work when I try to use some filter (e.g. where), cause it returns me some ""#p_linq_{0}"." instead of the values. I know these are the parameters of my query, but where are they stored?
I use this for batch delete purposes on the EF5 Code First.
If you create a query with a param like this:
var name = "xxx";
var query = ctx.Persons.Where(x => x.FirstName == name);
Then you can get the sql statement and parameters like this:
var oq = ((ObjectQuery<Person>)query);
var trace = oq.ToTraceString();
var p = oq.Parameters;
Use the param name "p_linq_{0}" without the # as an index on p, p["p_linq_{0}"].
Related
I am using SqlKata purely to build sql queries in C#. I am wanting to take the output of my built up Query, get the raw (compiled) sql string, and execute it against SQL.
I thought this would do it:
var factory = new QueryFactory(null, new SqlServerCompiler());
var query = new Query();
...
var sqlText = factory.Compiler.Compile(query).Sql;
But this gives this:
SELECT TOP (#p0) [AllStarFull].[GameNumber], [AllStarFull].[LeagueId], [AllStarFull].[PlayedInGame] FROM [AllStarFull]
This throws an exception because (#p0) is a param, and not the actual value.
In the documentation, it mentions to bring in Logger but I don't really need logging functionality (right now).
https://sqlkata.com/docs/execution/logging
var db = new QueryFactory(connection, new SqlServerCompiler());
// Log the compiled query to the console
db.Logger = compiled => {
Console.WriteLine(compiled.ToString());
};
var users = db.Query("Users").Get();
Is there anyway to get the raw sql string from the Query with all params populated?
If you need just to build the SQL there is no need to include the SqlKata.Execution package (which is include the QueryFactory class).
The simplest way is:
using SqlKata;
using SqlKata.Compilers;
// Create an instance of SQLServer
var compiler = new SqlServerCompiler();
var query = new Query("Users").Where("Id", 1).Where("Status", "Active");
SqlResult result = compiler.Compile(query);
string sql = result.Sql;
List<object> bindings = result.Bindings; // [ 1, "Active" ]
as mentioned in the docs you can use the result.ToString() to get the full query
var sql = result.ToString();
but this is not a good practice, the correct way is to use the parameterized query with bindings to execute it.
taken from https://sqlkata.com/docs#compile-only-example
If you are injecting QueryFactory dependency, you can use its compiler:
var query = new Query("Users")... etc
var rawSQL = queryFactory.Compiler.Compile(query).RawSql;
I have a function with two strings. Can't figure out how to incorporate those two strings into a LINQ query.
Here is my function:
private void DataBind_GridView_Search(string OptionalArgsSortExpression = "", string OptionalArgsSortDirection = "")
{
List<mainSearchDataModel> Query = GetData();
if (Query != null)
{
/* Problem ... */
Query = from x in Query
orderby OptionalArgsSortExpression.ToString() OptionalArgsSortDirection.ToString()
select x;
/* Problem ... */
GridView_Search.DataSource = Query;
GridView_Search.DataBind();
}
Any comments would be highly appreciated.
This is the error I get. Also I am not using DLINQ.
'System.Linq.Enumerable.OrderBy(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
UPDATE:
Is there a way to ORDER a List or IEnumerable either one. It seems everything I try does not work.
There is a way to convert it to DataView but I run into trouble there as well and would rather not go that way.
You could try something like this (Provided that you use DLINQ, as Servy pointed out in his comment.):
var query = query.OrderBy(String.Format("{0} {1}",OptionalArgsSortExpression,OptionalArgsSortDirection));
You could use my OrderByString extension. It converts strings into calls to the actual OrderBy methods, so it is compatible with all Linq providers.
using OrderByExtensions;
Query = Query.OrderBy(OptionalArgsSortExpression.ToString()
+ " " + OptionalArgsSortDirection.ToString())
https://github.com/Grax32/OrderByString
https://www.nuget.org/packages/OrderByString/
You could go this route
GridView.DataSource = Query.OrderBy(o => o.Field1).ThenBy(t => t.Field2).ToList()
I've been looking into this for quite some time now and cannot figure out a resolution. I Originally Tried formatting A dynamic linq Statement as you can see here in this post
I declared a class:
public class DynamicHelper
{
public string FormattedLink(string DisplayText, string ID)
{
return "" + DisplayText + "";
}
public string FormattedLink(string DisplayText, int ID)
{
return "" + DisplayText + "";
}
}
After I inserted a new type in DynamicLinq into the predefinedTypes
,typeof(DynamicHelper) //around line 635
I have a program which is attempting to Invoke the FormattedLink inside of a dynamic linq select:
using (var Model = new MK3Entities())
{
DynamicHelper Dh = new DynamicHelper();
var TOrigin = (Model.Titles.Where("ID > 19632")
.Select("new(ID, #0.FormattedLink(ExtTitleID, ID) as ExtTitleID )", Dh) as System.Collections.IEnumerable)
.Cast<dynamic>().Take(10).ToList();
Console.ReadKey();
}
When I execute this program I get a runtime exception "LINQ to Entities does not recognize the method 'System.String FormattedLink(System.String, Int32)' method, and this method cannot be translated into a store expression."
Any Ideas on how to fix this... I just need simple formatting from Dynamic Select.
The error message is pretty self explanatory. The database doesn't know how to translate that method into SQL. You need to fetch the information that the method needs in your database query and then call that function on the results, rather than in the query.
I'm not sure why you need it to be dynamic, it seems the solution you present is very overly complicated. I would write it as:
using (var Model = new MK3Entities())
{
DynamicHelper Dh = new DynamicHelper();
var TOrigin = Model.Titles
.Where("ID > 19632")
.Select(t => new { ID = t.ID, ExtTitleID = t.ExtTitleId })
.Take(10)
.ToList() // Execute SQL Statement
.Select(t => new {ID = t.ID, Link = nh.FormattedLink(ExtTitleID, ID)})
.ToList();
Console.ReadKey();
}
I'm returning an List<anonymous'1> object instead of a dynamic object (because I've never had the need for dynamic objects) so you can adjust it accordingly.
I just solved similiar problem few hours back.
YOu need ToList() that works with Dynamic linq. Check out this thread: Can't find property or field on a dynamic object
Just copy paste those to your project, and later:
var TOrigin = (Model.Titles.Where("ID > 19632")
.ToAnonymousList()
.Select("new(ID, #0.FormattedLink(ExtTitleID, ID) as
ExtTitleID )", Dh) as System.Collections.IEnumerable);
I was wondering if we can convert a Linq Query on the Entity Framework and save the query to the database by converting it to an Expression Tree and Serializing. Can someone please help me on this and point me in a right direction whether this can be done or not. Any help is greatly appreciated on this.
Thanks,
Ajay.
i released a library for that purpose just yesterday. Serialize.Linq. It serializes linq expressions to xml, json or binary.
using System.Linq.Expressions
using Serialize.Linq.Extensions;
Expression<Func<Person, bool>> query = p => p.LastName == "Miller"
&& p.FirstName.StartsWith("M");
Console.WriteLine(query.ToJson());
Console.WriteLine(query.ToXml());
You could turn the query into a string and then save the string.
This is from an answer by Nick Berardi:
var result = from x in appEntities
where x.id = 32
select x;
var sql = ((System.Data.Objects.ObjectQuery)result).ToTraceString();
The sql generated by the query could be stored and re-used.
Use Sprint.Filter.OData. It converts a Func<T,bool> into string and back to code.
Sample:
public class TestSprintOData
{
public static void Run()
{
// Parse a Func into string
var query = Filter.Serialize<User>(u => u.IsActive && u.Email.Contains("#gmail.com"));
// It'll generate the string "IsActive and substringof('#gmail.com', Email)"
// Convert back to Expression, perhaps on server
var query2 = Filter.Deserialize<User>(query);
// Compiles to Func, so you can use as delegate to Where
var f = query2.Compile();
var list = new List<User>
{
new User{Name="Johnny", IsActive = true, Email = "johnny#gmail.com"},
new User{Name="abc", IsActive = false, Email = ""},
new User{Name="dude", IsActive=true, Email = "dude#gmail.com"}
};
var result = list.Where(f);
}
}
class User
{
public string Name;
public string Phone;
public string Login;
public string Email;
public bool IsActive;
}
You can also use it as a Nuget Package
You may want to consider using Entity SQL rather than LINQ in this case. Entity SQL is a string query that works against your EF conceptual model rather than directly against the database.
I am currently developing a WPF project in c#. The project takes a string (newMemoryRFID) which is defined when the page is initialised and uses it in a query. Like so
var query =
from c in MemoryData.Memory
where c.RFID == newMemoryRFID
select c;
this.DataContext = query;
this.View = ((CollectionView)(CollectionViewSource.GetDefaultView(this.DataContext)));
This produces an empty DataContext
However when I use test data which is the same as what newMemoryRFID would be the query i.e.
var query =
from c in MemoryData.Memory
where c.RFID == "0F02D76B05"
select c;
this.DataContext = query;
this.View = ((CollectionView)(CollectionViewSource.GetDefaultView(this.DataContext)));
The query gets the correct record. As you may be able to tell I'm not the best programmer so the simpler your answer the better. And thanks very much in advance
This is the time to use your debugger. It sounds like newMemoryRFID isn't set to "0F02D76B05" at the time that query is created.
If you can't step into it, at least do
Debug.WriteLine(string.Format("newMemoryRFID = {0}", newMemoryRFID);
before the line
var query = ...
Try trimming the string both at the beginning and end for possible whitespace which would fail the string match.