I'm trying to create a generic repository. For some reason, having a parameter in the Match() clause does not seems to work. Anyone know what the problem might be? My code looks like this (I'm a C#/.net Developer):
private IEnumerable<T> GetNodCollectionByLabel<T>(string nodLabel)
{
IEnumerable<T> entityList = new List<T>();
entityList = _graphClient.Cypher
.Match("(entity:{nodLabel})")
.WithParam("nodLabel", nodLabel)
.Return(entity => entity.As<T>())
.Results;
return entityList.ToArray();
}
The exception is:
SyntaxException: Invalid input '{': expected whitespace or a label name (line 1, column 15 (offset: 14)) "MATCH (entity:{nodLabel})" ^
.withParam() is for the Cypher parameters as they meant, not for the labels.
http://neo4j.com/docs/stable/cypher-parameters.html
You cannot use parameters for labels.
One approach for you is to use String.Format();
private IList<string> GetAllLabels()
{
return _graphClient.Cypher
.Match("(n)")
.Return<List<string>>("DISTINCT labels(n)")
.Results;
}
private bool isValidNode(string name)
{
return GetAllLabels().Contains(name.Trim());
}
private IEnumerable<T> GetNodCollectionByLabel<T>(string nodLabel)
{
IEnumerable<T> entityList = new List<T>();
if (!isValidNodeLabel(nodLabel))
{
return Enumerable.Empty<T>();
}
var statement = String.Format("(entity:{0})", nodLabel);
entityList = _graphClient.Cypher
.Match(statement)
.Return(entity => entity.As<T>())
.Results;
return entityList.ToArray();
}
Try this:
private IEnumerable<T> GetNodCollectionByLabel<T>(string nodLabel)
{
IEnumerable<T> entityList = new List<T>();
entityList = _graphClient.Cypher
.Match("(entity:nodLabel)")
.WithParam("nodLabel", nodLabel)
.Return(entity => entity.As<T>())
.Results;
return entityList.ToArray();
}
If you really have a param named "nodLabel" it will return some data.
The problem here was that you were looking for a node like this:
MATCH (entity:{nodLabel}) ...
but you have to specify the node label if you are using :, so you got a parsing error, because you did not specified a label for the node you were matching.
Related
I have a dart list of objects, every of which contains book_id property, and I want to find an element of that list by the book_id field.
Use firstWhere method: https://api.flutter.dev/flutter/dart-core/Iterable/firstWhere.html
void main() {
final list = List<Book>.generate(10, (id) => Book(id));
Book findBook(int id) => list.firstWhere((book) => book.id == id);
print(findBook(2).name);
print(findBook(4).name);
print(findBook(6).name);
}
class Book{
final int id;
String get name => "Book$id";
Book(this.id);
}
/*
Output:
Book2
Book4
Book6
*/
Null-Safe approach (handling no-element error)
If the searched item might or might not be in the array, with null safety I personally prefer to use .where on lists - it filters through the array and returns a list.
var myListFiltered = myList.where((e) => e.id == id);
if (myListFiltered.length > 0) {
// Do stuff with myListFiltered.first
} else {
// Element is not found
}
The benefit of this approach is that you'll always get an array and there won't be an issue with element not being found or trying to return null through orElse callback:
The return type 'Null' isn't a 'FooBar', as required by the closure's context.
Refactoring the finder logic into a helper method
Since the task of finding an element by id in a list of objects is quite a common one, I like to extract that logic into helpers file, for example:
class Helpers {
static findById(list, String id) {
var findById = (obj) => obj.id == id;
var result = list.where(findById);
return result.length > 0 ? result.first : null;
}
}
And use it like this:
var obj = Helpers.findById(myList, id);
if (obj == null) return; //? Exn: element is not found
A lot has been said already, but I want to add my best way to do this. if it's possible that the item doesn't exist in the list, import the iterable extension and use firstWhereOrNull1 on the list.
import 'package:collection/src/iterable_extensions.dart';
myList.firstWhereOrNull((item) => item.id == id))
You should add orElse to avoid exeption:
list.firstWhere(
(book) => book.id == id,
orElse: () => null,
});
To avoid having to add orElse to every use of firstWhere, with Dart 2.7+, you can create a handy little extension to handle this:
extension IterableX<T> on Iterable<T> {
T safeFirstWhere(bool Function(T) test) {
final sublist = where(test);
return sublist.isEmpty ? null : sublist.first;
}
}
Which can then be used as such:
final books = List<Book>.generate(10, (id) => Book(id));
final matchingBooks = books.safeFirstWhere((book) => book.id == id);
void main(){
List lights=[
{"id":1,"color":"yellow"},
{"id":2,"color":"green"},
{"id":3,"color":"red"}
];
int searchId = 2;
var colr = lights.firstWhere((x) => x['id'] == searchId, orElse:() => {"color" : "Color Not found"})['color'];
print(colr);
}
The above code searches the obj list, using firstWhere. If not found returns text 'Color not found'
Given a build definition, I extract the following pieces from it:
m_template = (DynamicActivity)WorkflowHelpers.DeserializeWorkflow(buildDefinition.Process.Parameters);
Properties = m_template.Properties.ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase);
Metadata = WorkflowHelpers.GetCombinedMetadata(m_template).ToDictionary(m => m.ParameterName);
m_parameters = WorkflowHelpers.DeserializeProcessParameters(buildDefinition.ProcessParameters)
Now I wish to know the value of an arbitrary process parameter.
My current code is:
public ParameterValue GetParameterValue(string name)
{
object propValue;
var valueType = GetParameterType(name, out propValue);
object value;
if (!m_parameters.TryGetValue(name, out value))
{
value = propValue;
}
return new ParameterValue(valueType, value);
}
private Type GetParameterType(string name, out object value)
{
value = null;
if (Properties != null)
{
DynamicActivityProperty property;
if (Properties.TryGetValue(name, out property))
{
var inArgument = property.Value as InArgument;
if (inArgument != null)
{
if (inArgument.Expression != null)
{
var exprString = inArgument.Expression.ToString();
if (!exprString.StartsWith(": VisualBasicValue<"))
{
value = exprString;
}
}
return inArgument.ArgumentType;
}
if (property.Value != null)
{
value = property.Value;
return property.Value.GetType();
}
var typeName = property.Type.ToString();
if (typeName.StartsWith(IN_ARGUMENT_TYPE_NAME_PREFIX))
{
typeName = typeName.Substring(IN_ARGUMENT_TYPE_NAME_PREFIX.Length, typeName.Length - IN_ARGUMENT_TYPE_NAME_PREFIX.Length - 1);
return Type.GetType(typeName, true);
}
return property.Type;
}
}
return typeof(string);
}
Unfortunately, this code stumbles for parameters satisfying all of the following conditions:
The parameter value is wrapped as InArgument<T>.
T is a non primitive type, for example string[]
The build definition does not override the value inherited from the process template.
What happens is that:
Because the value is non primitive exprString.StartsWith(": VisualBasicValue<") and I do not know how to handle it. Hence propValue is null.
Because the value is not overridden by the build definition !m_parameters.TryGetValue(name, out value) and hence I just return propValue.
As a result my logic returns null. But it is wrong! For example, I have a string[] parameter which has a list of string in the process template, but my logic returns null for the reasons explained.
So, what is the proper way to compute it?
You can use the following code (included in another link) to get value and type of one process parameter:
TfsTeamProjectCollection tfctc = new TfsTeamProjectCollection(new Uri("http://tfsservername:8080/tfs/DefaultCollection"));
IBuildServer bs = tfctc.GetService<IBuildServer>();
IBuildDetail[] builds = bs.QueryBuilds("teamprojectname", "builddefinitionname");
foreach (var build in builds)
{
var buildefinition = build.BuildDefinition;
IDictionary<String, Object> paramValues = WorkflowHelpers.DeserializeProcessParameters(buildefinition.ProcessParameters);
string processParametersValue = paramValues["argument1"].ToString();
Console.WriteLine(processParametersValue);
}
Also have a check on this case: TFS 2010: Why is it not possible to deserialize a Dictionary<string, object> with XamlWriter.Save when I can use XamlReader for deserializing
I am looking for a way to get the key correspondent of the value with error. I can use foreach to get all errors in ModelState but how to associate it with your respective keys to get these names (keys names or index)?
You can iterate the ModelState (which is a ModelStateDictionary) and look at the keys, they correspond to the properties
Yishai's answer is not that straightforward for me, so I thought of leaving the following for others ending up here.
The following is a method I wrote to return all ModelStateDictionary errors, including the key where the error was found.
public static String GetErrorsJoined(this ModelStateDictionary modelStateDictionary, String separator = ". ")
{
String errorsJoined = String.Empty;
List<String> errors = new List<string>();
try
{
foreach(KeyValuePair<String, ModelState> keyValuePair in modelStateDictionary)
{
if (keyValuePair.Value.Errors.Count > 0)
{
Int32 keyDelimiterIndex = keyValuePair.Key.IndexOf('.');
String realKey = (keyDelimiterIndex > -1 && keyDelimiterIndex + 1 <= keyValuePair.Key.Length - 1) ? keyValuePair.Key.Substring(keyDelimiterIndex + 1) : keyValuePair.Key;
IEnumerable<String> keyErrors = keyValuePair.Value.Errors.Select(error => String.Format("{0}{1}{2}", error.ErrorMessage, separator, error.Exception.Message));
errors.Add(String.Format("Field [{0}]: {1}", realKey, String.Join(separator, keyErrors)));
}
}
errorsJoined = String.Join(separator, errors);
}
catch (Exception ex)
{
//do something
}
return errorsJoined;
}
This code has been simplified for this example.
The query is actually returned from a service, which is why I would prefer to write the method this way.
[HttpGet]
public PageResult<ExceptionLog> Logging(ODataQueryOptions<ExceptionLog> options)
{
var query = from o in _exceptionLoggingService.entities.ExceptionDatas
select new ExceptionLog {
ExceptionDataId = o.ExceptionDataId,
SiteId = o.SiteId,
ExceptionDateTime = o.ExceptionDateTime,
StatusCode = o.StatusCode,
Url = o.Url,
ExceptionType = o.ExceptionType,
ExceptionMessage = o.ExceptionMessage,
Exception = o.Exception,
RequestData = o.RequestData
};
var results = options.ApplyTo(query) as IEnumerable<ExceptionLog>;
var count = results.LongCount();
return new PageResult<ExceptionLog>(results, Request.GetNextPageLink(), count);
}
The above code errors on "results.LongCount()" with the following Exception:
SqlException: The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE operator.
It appears that I'm getting an exception with when trying to page, like this "$top=2". Everything works fine if my querystring is like this "$filter=ExceptionDataId gt 100".
Since ExceptionData (the Entity) matches ExceptionLog (business model) I can do something like this as a workaround:
[HttpGet]
public PageResult<ExceptionLog> Logging(ODataQueryOptions<ExceptionData> options)
{
var query = from o in _exceptionLoggingService.entities.ExceptionDatas
orderby o.ExceptionDateTime descending
select o;
var results = from o in options.ApplyTo(query) as IEnumerable<ExceptionData>
select new ExceptionLog {
ExceptionDataId = o.ExceptionDataId,
SiteId = o.SiteId,
ExceptionDateTime = o.ExceptionDateTime,
StatusCode = o.StatusCode,
Url = o.Url,
ExceptionType = o.ExceptionType,
ExceptionMessage = o.ExceptionMessage,
Exception = o.Exception,
RequestData = o.RequestData
};
return new PageResult<ExceptionLog>(results, Request.GetNextPageLink(), results.LongCount());
}
But this doesn't completely work for me because it's a little hackish and I can't use the service's method which already gives me an IQueryable.
Another thing to note, is if the Logging method is converted to IQueryable, everything works correctly. But I need to return the Count with the query so I have to return a PageResult.
This is the workaround I'm using. I only apply the filter from the ODataQueryOptions and I manually apply the Top and Skip.
First I created some extension methods:
using System;
using System.Collections.Generic;
using System.Linq;
namespace System.Web.Http.OData.Query
{
public static class ODataQuerySettingsExtensions
{
public static IEnumerable<T> ApplyFilter<T>(this IQueryable<T> query, ODataQueryOptions<T> options)
{
if (options.Filter == null)
{
return query;
}
return options.Filter.ApplyTo(query, new ODataQuerySettings()) as IEnumerable<T>;
}
public static IEnumerable<T> ApplyTopAndTake<T>(this IEnumerable<T> query, ODataQueryOptions<T> options)
{
IEnumerable<T> value = query;
if (options.Top != null)
{
value = value.Take(options.Top.Value);
}
if (options.Skip != null)
{
value = value.Skip(options.Skip.Value);
}
return value;
}
}
}
Now my method looks like this:
[HttpGet]
public PageResult<ExceptionLog> Logging(ODataQueryOptions<ExceptionLog> options)
{
// GetLogs returns an IQueryable<ExceptionLog> as seen in Question above.
var query = _exceptionLoggingService.GetLogs()
.ApplyFilter(options);
var count = query.Count();
var results = query.ApplyTopAndTake(options);
return new PageResult<ExceptionLog>(results, Request.GetNextPageLink(), count);
}
I am working on getting the results of this sql query in LINQ
SELECT DISTINCT(Type)
FROM Product
WHERE categoryID = #catID
this is my repository query:
public IQueryable<ProdInfo> GetProdInfo()
{
var data = from u in db.Prod
select new ProdInfo
{
PID = u.PID,
CatID = u.CatID,
LastChanged = u.LastChanged,
ChangedBy = u.ChangedBy,
Type = u.Type,
};
return data;
}
filter:
public static IQueryable<ProdInfo> GetDistinctProdType(this IQueryable<ProdInfo> qry,int CatID)
{
return from p in qry
where p.CatID.Equals(CatID)
select p;
}
I need the filter to return the distinct prod type? How can i do this?
Simply like this:
public static IQueryable<ProdType> GetDistinctProdType(
this IQueryable<ProdInfo> query,
int categoryId)
{
return (from p in query
where p.CatID == categoryId
select p.Type).Distinct();
}
Note that I've changed the return type - it should match whatever the type of ProdInfo.Type is.
You may find it more readable to use the extension methods for the whole query if the query expression itself is reasonably simple:
public static IQueryable<ProdType> GetDistinctProdType(
this IQueryable<ProdInfo> query,
int categoryId)
{
return query.Where(p => p.CatID == categoryId)
.Select(p => p.Type)
.Distinct();
}
return (from p in qry
where p.CatId.Equals(CatID)
select p.Type).Distinct();
This matches what your provided SQL Query should be doing.