Dapper DynamicParameters - sql-server-2016

I'm using Dapper with C#. I'm trying to dynamically build a query, the columns involved, and parameters, but I'm getting an error. Here is the sample code:
private List<string> columns = new List<string>();
private List<string> values = new List<string>();
Dictionary<string, string> parameters = new Dictionary<string, string>();
// We dynamically determine columns to add:
columns.Add("AssetName");
values.Add("#AssetName");
parameters.Add("#AssetName", "test value");
string sql = #$"insert into foo ({String.Join(",", columns)}) values({String.Join(",", values)});";
var params = new DynamicParameters(params);
connectionObject.Execute(sql, params);
The error I get is: Must declare the scalar variable "#AssetName".
Where have I gone wrong?
If I replace the execute line with:
connectionObject.Execute(sql, new { AssetName = "test" });
Then the query runs without error.
Note: In the dictionary I tested without and without the # in the key.

I found the issue. The Dictionary's values must be of type object:
Dictionary<string, string> parameters = new Dictionary<string, object>();
Also, it seems the dictionary keys don't need the leading "#".

Related

Graph traversal name to graph name mapping

Is there any API using which I can get graphTraversalName to graphName mapping defined in the script?
I am using the below messy code but it's error-prone if both graphs are using the same underlying storage.
Map<String, String> graphTraversalToNameMap = new ConcurrentHashMap<String, String>();
while(traversalSourceIterator.hasNext()){
String traversalSource = traversalSourceIterator.next();
String currentGraphString = ( (GraphTraversalSource) graphManager.getAsBindings().get(traversalSource)).getGraph().toString();
graphNameTraversalMap.put(currentGraphString, traversalSource);
}
Iterator<String> graphNamesIterator = graphManager.getGraphNames().iterator();
while(graphNamesIterator.hasNext()){
String graphName = graphNamesIterator.next();
String currentGraphString = graphManager.getGraph(graphName).toString();
String traversalSource = graphNameTraversalMap.get(currentGraphString);
graphTraversalToNameMap.put(traversalSource, graphName);
}
Does gremlinExecutor.getScriptEngineManager().getBindings().entrySet() provide order guarantee? I can iterate over this and populate my map
Is there any API using which I can get graphTraversalName to graphName mapping defined in the script?
No. They share the same namespace in Gremlin Server so the relationship gets lost programmatically. You would need to do something like what you are doing but I wouldn't rely on toString() of a Graph for equality. Perhaps use the Graph instance itself? Although that might not work either depending on your situation and what you want for equality as you could have two different Graph configurations pointed at the same data and want to resolve those as the same graph. I'm also not sure that any approach will work generally for all graph systems. Anyway, I think I'd experiment with using Map<Graph, String> graphTraversalToNameMap for your case and see how that goes.
Does gremlinExecutor.getScriptEngineManager().getBindings().entrySet() provide order guarantee?
No as it is backed by a ConcurrentHashMap. You would have to provide your own order.
Underlying storage details can be obtained from the configuration object and can be used for the mapping, sample code:
public class GraphTraversalMappingUtil {
public static void populateGraphTraversalToNameMapping(GraphManager graphManager){
if(graphTraversalToNameMap.size() != 0){
return;
}
Iterator<String> traversalSourceIterator = graphManager.getTraversalSourceNames().iterator();
Map<StorageBackendKey, String> storageKeyToTraversalMap = new HashMap<StorageBackendKey, String>();
while(traversalSourceIterator.hasNext()){
String traversalSource = traversalSourceIterator.next();
StorageBackendKey key = new StorageBackendKey(
graphManager.getTraversalSource(traversalSource).getGraph().configuration());
storageKeyToTraversalMap.put(key, traversalSource);
}
Iterator<String> graphNamesIterator = graphManager.getGraphNames().iterator();
while(graphNamesIterator.hasNext()) {
String graphName = graphNamesIterator.next();
StorageBackendKey key = new StorageBackendKey(
graphManager.getGraph(graphName).configuration());
graphTraversalToNameMap.put(storageKeyToTraversalMap.get(key), graphName);
}
}
}
For full code, refer: https://pastebin.com/7m8hi53p

Lucene's WordnetSynonymParser

I am trying to use Lucene's WordnetSynonymParser class to create a synonym filter, but I'm not sure which of the prolog files I'm meant to be passing into the parse() function.
The documentation says:
See http://wordnet.princeton.edu/man/prologdb.5WN.html for a
description of the format.
so I've downloaded the prolog files, but I'm not sure which ones I should be passing in, and how I go about it.
Could someone please point me in the right direction?
Thanks for your help
EDIT:
Thanks to femtoRgon for pointing me in the direction of wn_s.pl. I have now got the following code:
Analyzer tempanalyzer = new SimpleAnalyzer(Version.LUCENE_40);
WordnetSynonymParser synparser = new WordnetSynonymParser(true, true, tempanalyzer);
FileReader doctoread = new FileReader("wn_s.pl");
synparser.parse(doctoread);
SynonymMap synmap = synparser.build();
Analyzer analyzer = new Analyzer() {
#Override
protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
EnglishAnalyzer enganalyzer = new EnglishAnalyzer(Version.LUCENE_40);
CharArraySet engstopset = enganalyzer.getDefaultStopSet();
Tokenizer source = new StandardTokenizer(Version.LUCENE_40, reader);
TokenStream filter = new SynonymFilter(source, synmap, true);
filter = new StandardFilter(Version.LUCENE_40, filter);
filter = new LowerCaseFilter(Version.LUCENE_40, filter);
filter = new StopFilter(Version.LUCENE_40, filter, engstopset);
/*TokenStream filter = new StandardFilter(Version.LUCENE_40, source);
filter = new LowerCaseFilter(Version.LUCENE_40, filter);
filter = new StopFilter(Version.LUCENE_40, filter, engstopset);*/
return new TokenStreamComponents(source, filter);
}
};
which I then plan on passing into IndexWriterConfig, however I get the following compile error:
IndexFilesDB.java:133: cannot find symbol
symbol : method parse(java.io.FileReader)
location: class org.apache.lucene.analysis.synonym.WordnetSynonymParser
synparser.parse(doctoread);
I still don't fully understand WordnetSynonymParser, is it an error to do with the class or it just a simple error where the file is not being passes in correctly?
Thanks for your help.
wn_s.pl contains the synset pointers (that is, it defines groups of synonyms), which is what you need for a synonym filter, to my knowledge. I'd start with that.

Fastest way to get the properties of umbraco documents

I am working on search functionality for a website designed through umbraco. I am using Examine to fetch the search results. Here is my code:
var Searcher = ExamineManager.Instance.SearchProviderCollection["ExternalSearcher"];
var searchCriteria = Searcher.CreateSearchCriteria(BooleanOperation.Or);
var query = searchCriteria.Field("tags", searchTerm.Fuzzy(0.5f)).Compile();
var searchResults = Searcher.Search(query);
With this method i can only get the nodes in which the search term belongs.But I want to directly fetch the whole value from the property.
I want to know what is the fastest way to fetch all the values from the same property in all the nodes.
I have finally managed to get the values directly from the property.This is the code I have used:
List<string> nodesList = new List<string>();
var Searcher = ExamineManager.Instance.SearchProviderCollection["ExternalSearcher"];
var searchCriteria = Searcher.CreateSearchCriteria(BooleanOperation.Or);
var query = searchCriteria.Field("tags", queryString.Fuzzy(0.5f)).Compile();
var searchResults = Searcher.Search(query);
foreach (var item in searchResults)
{
string paths = ((Examine.SearchResult)item).Fields["tags"];
nodesList.Add(paths);
}
using ((Examine.SearchResult)item).Fields["tags"] gets the property value directly.
If you want to costumize your search you need to define a new index set with the properties that you actually want to search on the /config/examineIndex.config file.
Quite well explained in this post.

NHibernate CreateSqlQuery() result to an ObservableCollection

I've the following:
using (ISession session = Config.SessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
// This is a System.Collections.ArrayList,contains all my records returned from the session
var list = session.CreateSQLQuery(selectQuery).List();
// I want to put these records in an ObservableCollection of a specific Type
// Something like htis:
MyCollection = new ObservableCollection<MyType>(list);
}
}
This is not working and casting isn't an option here. Is there any way to put my retrurned list to the ObservableCollection?
I've got my ObservableCollection filled by using the following:
var query = session.CreateSQLQuery(selectQuery).AddEntity(typeof(MyType));
myObservableCollection = new ObservableCollection<MyType>(query.List<MyType>());
The List() returns ArrayList. Each value in ArrayList has some value which is type of object.
It can not be converted into directly any specific class. so create a mapping file then only you can get list of your required object.

BuildCommands argument in Rob Conery's Massive

I am using Rob Conery's Massive.
The method List<DbCommand> BuildCommands(params object[] things), according to the methods comments, is supposed to take objects that "can be POCOs, Anonymous, NameValueCollections, or Expandos". But this:
var x = new { Id = new Guid("0F66CDCF-C219-4510-B81A-674CE126DD8C"), Name = "x", DisplayName = "y" };
myTable.BuildCommands(x);
Results in an InvalidCastException. Which reasonable since in the Massive.cs a cast from the passed in anonymous type to an ExpandoObject is attempted.
Why does the comment state you can pass in anything? Is there some other way to build commands from non-ExpandoObjects?
Here's some more code:
public static void ThisFails()
{
DynamicModel myTable = new DynamicModel("myConnectionString", tableName: "dbo.MyTable", primaryKeyField: "Id");
var updateMe = new { Id = new Guid("DF9A2F1B-3556-4EAC-BF2B-40E6821F3394"), Name = "abcx", DisplayName = "x" };
var commands = myTable.BuildCommands(updateMe); // This fails
myTable.Execute(commands);
}
public static void ThisSucceeds()
{
DynamicModel myTable = new DynamicModel("myConnectionString", tableName: "dbo.MyTable", primaryKeyField: "Id");
dynamic updateMe = new ExpandoObject();
updateMe.Id = new Guid("DF9A2F1B-3556-4EAC-BF2B-40E6821F3394");
updateMe.Name = "abcx";
updateMe.DisplayName = "x";
var commands = myTable.BuildCommands(updateMe);
myTable.Execute(commands);
}
The code that fails results in:
Unable to cast object of type
'<>f__AnonymousType03[System.Guid,System.String,System.String]' to
type <br/>
'System.Collections.Generic.IDictionary2[System.String,System.Object]'.
It's thrown from the first line in your method
public virtual DbCommand CreateUpdateCommand(dynamic expando, object key)
{
var settings = (IDictionary<string, object>)expando;
...
To me it looks like there should be a call to your extension method ToExpando before CreateUpdateCommand is called?
I think this is why people make methods private and public :). You're not supposed to call BuildCommands directly (though the code you have here still should work). I have a feeling there might be a bug that was committed in a patch.
That said - I believe this will work if you call myTable.Update() or myTable.Insert().
This last part answers the question - in terms of a possible "issue" - let's take that to Github.