Is there a way to convert LINQ queries into XSLT? the same way LINQ can be converted to SQL?
I mean if i have a solid well defined XML(Conforms to an XSD) is there a way to compile the stuff under System.Linq.Expressions into XSLT in regard to that XML?
Thank you.
To Dimitries request I'll try to elaborate a little... Basically I have some data in one place (it's basically to chunks of xml serializable data), and I need to process them, I need to combine and process them.
Both the incoming original data , and the output result data, are XML serializable, and conform to a well defined XSD.
I want to generate the processing logic dynamically - someplace else. And allow my user to change and play around with the processing. I can represent the processing it self easily with Expression trees. Expression trees are similar to parse trees and can capture program code. This is the way linq to SQL works it converts expression trees to SQL queries.
Since all the income data and the output are both a well defined XML I can do the transformation easily with XSLT, but I'm not familiar with XSLT enough to write a dynamic XSLT generator. So I thought I could build the transformations in C# and convert them into XSLT.... again its not general purpose C#, but probably specific queries over a well defined data provider.
For the example sake:
(Not real code)
var schemas = XSchemaSet.Load("a","b");
var doc = XDocument.Load("File",schemas);
var result = from node in doc.Nodes
where node.Name == "Cats" || node.Name == "Dogs"
select (new Node(){Name = "Animal Owner", Value = node.Owner)
var newDoc = new XDocument().AddNodes(result);
newDoc.Validate(schemas);
Basically I want something that will function like that... I can write that in a single linq query if I use IQueryable.Aggregate
Yes, you can implement your own query provider, which uses XSLT internally, if you can figure out how to query with XSLT.
Why not just use Linq2XML?
It operates on XDocument and XElement
or alternatively if you want people to define transforms using xlst why not just execute an xslt against the document in code?
I dont see how having a Linq2XSLT would help solve a problem without recreating it in a different form
Related
Using the latest version (2.14) is there any way to view the bson query document generated by a specific linq query?
I want to do this for two reasons:
debugging queries
copying them to run in another mongo client like compass
I know I can enable profiling, but I can't see any way to guarantee a query you find in the mongo log was generated by a specific line of code or query. Plus it's a bit long winded to do it via profiling.
You have 2 options to get MQL query from LINQ request:
Install lately released query analyzer. As I know it may not be 100% accurate if you use global static serialization configuration.
Configure CommandStartedEvent event subscriber and analyze Command document. Pay attention that you may need to remove some technical fields like $db (maybe few more) that might not be parsed by compass correctly, you will see it in the exception message if any.
#dododo answer is the right and best one, I'm just adding some code here which works for option 2:
var settings = MongoClientSettings.FromUrl(new MongoUrl(#"mongodb://localhost"));
settings.ClusterConfigurator = builder =>
{
builder.Subscribe<CommandStartedEvent>(x =>
{
var queryDocument = x.Command;
});
};
var client = new MongoClient(settings);
I have the situation that filtering condition on collection is quite long. And I prefer to write it by hand and using the mongoDb RunCommandAsync method in C# driver to get the Bson Document as result then Deserialize it back to object.
As the doc said it will return a BsonDocument, instead of a Cursor to iterate with.
I made a small test from a collection with some dummy filter condition as below, and i got ~215k docs from robo 3T, but when it comes to RunCommandAsync in c#, it default return 101 document. I attempted to increase the batchSize to 200.000, but the execution can only return ~22k docs(which i guess it's the limitation of 4MB per batch operation).
var cmdDoc = #"{
'find': 'NotificationHistories',
'filter': {'CreatedTime': {$exists: true}}
'batchSize': 200000,
'singleBatch': true
}";
var cmd = new JsonCommand<BsonDocument>(cmdDoc);
var res = await database.RunCommandAsync(cmd, ReadPreference.PrimaryPreferred, CancellationToken.None);
So my final question is:
Is there anyway we can execute raw query that could handle all the numerous of documents ?
The result can be any of Cursor, BsonDocument, Array of BsonDocument,...
Or there's just no possible way to workaround this but use the normal Find or Aggregate method of Collection ?
Any clue would be appriciate, since i felt its quite long and cumbersome writing those especially with Unwind, Group, Lookup,...
101 records is a number of records in the firstBatch of your cursor, iterating of next records(batch by batch) should be done via getMore command (but I think it's a wrong that you think in this way, I see no reason to avoid a regular way).
I have a list of strings that are search Queries.
I want to see if a string from the database contains anyone of those terms in the Query. I'd like to do this on one line of code, that doesn't make multiple calls to the database. This should work but I want it to be more optimized.
var queries = searchQuery.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries).Distinct();
var query = context.ReadContext.Divisions.AsQueryable();
queries.ForEach(q => {
query = query.Where(d => (d.Company.CompanyCode + "-" + d.Code).Contains(q));
});
Is there a function that can do this better or a more optimal way of writing that?
There are two issues with your proposed solution:
Most LINQ to SQL providers don't understand string.Contains("xyz") so the provider will either throw an exception or fetch all the data to your machine. The right thing to do is to use SqlMethods.Like as explained in Using contains() in LINQ to SQL
Also, the code you show will check whether the division contains all of the specified strings.
To implement the 'any' behavior you need to construct a custom expression, which will not be possible using plain C#. You would need to look at the System.Linq.Expressions namespace: https://msdn.microsoft.com/en-us/library/system.linq.expressions(v=vs.110).aspx
It is possible, but quite involved.
I have some trouble with LINQ. In my program I generate a SQL search query like
select * from emp "where empId=1 and empname='abc'"
(where the quoted text is generated in my code). I can pass the generated "where empId..." string text to the SQL query.
I'd like to do the same thing in LINQ - I want to pass this string as the search criteria i.e. something like
var employee=from a in Employee.AsEnumerable()
"where empId=1 and empname='abc'"
select a;
Is this possible? Thanks in advance.
You can take the base query (in your case Employee.AsEnumerable()) and use the logic you use to generate the string to compose a new query. For example:
if(/*your logic for generating the string "where empId=1" here*/)
{
query = query.Where(a.empId == 1);
}
if(/*your logic for generating the string "empname='abc'" here*/)
{
query = query.Where(a.empname == "abc");
}
The resulting query object will have all the operators composed. However as others have said this is not trivial in the general case. It is not trivial with SQL strings either. If all you need to generate are several filters it will work but if you need complex expressions it will be a problem.
101 LINQ Samples
It's pretty hard, unless you intend to employ:
Dynamic code compilation, or
You are willing to create a (very complicated) parser to analyze the query and call the respective linq extension methods
I personally have no experience in the latter. As for the former, it is a bit tricky and can go nastily wrong if you don't do proper caching and security checks. Executable code injection is very dangerous.
I think you had better use different methods to filter content using methods like Where() if the number of queries can be predetermined or return to SQL if not. Usually you don't need to do this unless the query is manually entered by the user.
using xmltextreader, how would I load a hashtable.
XML:
<base><user name="john">2342343</user><user name="mark">239099393</user></base>
This was asked before but it was using some funky linq that I am not fully comfortable with just yet.
Well, the LINQ to XML solution is really easy, so I suggest we try to make you comfortable with that instead of creating a more complex solution. Here's the code, with plenty of explanation...
// Load the whole document into memory, as an element
XElement root = XElement.Load(xmlReader);
// Get a sequence of users
IEnumerable<XElement> users = root.Elements("user");
// Convert this sequence to a dictionary...
Dictionary<string, string> userMap = users.ToDictionary(
element => element.Attribute("name").Value, // Key selector
element => element.Value); // Value selector
Of course you could do this all in one go - and I'd probably combine the second and third statements. But that's about as conceptually simple as it's likely to get. It would become more complicated if you wanted to put error handling around the possibility that a user element might not have a name, admittedly. (This code will throw a NullReferenceException in that case.)
Note that this assumes you want the name as the key and id as value. If you want the hashtable the other way round, just switch the order of the lambda expressions.