How to get Neo4JClient to perform a bulk insert - c#

When running the following code I receive an exception "CypherTypeException: Collections containing mixed types can not be stored in properties." - What am I doing wrong, and what needs to change to make it work?
var wordObjs = new List<object>();
foreach (string word in WordGroups.GetAllWords())
{
wordObjs.Add(new { Value = word});
}
GraphClient.Cypher
.Create("(word:Word {words})")
.WithParam("words", new { words = wordObjs})
.ExecuteWithoutResults();

One solution would be use a concrete class
private class Value {
public string Value {get;set;}
}
and use new List<Value>() instead, I think the client is having trouble with the anonymous nature of your List.

Related

Advise to optimize the following code in a better way

I have some data stored in a dictionary where the values are basically a list of objects with few attributes in them. Right now I'm looping through as following to get the data stored in a specific attribute. These data are then added into a drop down list (unity UI dropdown)
foreach (KeyValuePair<string, List<NameIDValuePair>> kvp in TeamValuePair)
{
List<NameIDValuePair> list = kvp.Value;
if(kvp.Key == teamNames.options[teamNames.value].text)
{
foreach (var rec in list)
{
screenNamesDropDown.options.Add(new TMP_Dropdown.OptionData { text = rec.ScreenName });
}
}
}
teamNames and screenNamesDropDown are dropdown elements part of my unity UI.
The structure of the NameIdValuePair looks as follows:
public class NameIdValuePair
{
public string ScreenName { get; private set; }
public string ScreenId { get; private set; }
}
I would like to optimize this piece of code in a better way using linq - so that it's a bit more readable. Since I'm pretty new to linq, i'm not really sure if I'm using the right keywords when searching for suggestions but so far I haven't had much success in finding any helpful suggestion.
Thanks
As mentioned before instead of looping a Dictionary - where we already know that the keys are unique - you could simply use Dictionary.TryGetValue
// do this only once!
var key = teamNames.options[teamNames.value].text;
if (TeamValuePair.TryGetValue(key, out var list))
{
foreach(var item in list)
{
screenNamesDropDown.options.Add(new TMP_Dropdown.OptionData(item.ScreenName));
}
}
and then actually the only place where you could use Linq if you really want to would maybe be in
var key = teamNames.options[teamNames.value].text;
if (TeamValuePair.TryGetValue(key, out var list))
{
screenNamesDropDown.options.AddRange(list.Select(item => new TMP_Dropdown.OptionData(item.ScreenName)));
}
if this makes it better to read is questionable though.
And in general the question would also be if you always want to Add (AddRange) to the screenNamesDropDown.options or if you maybe want to actually replace the options. Then instead of AddRange you could do
screenNamesDropDown.options = list.Select(item => new TMP_Dropdown.OptionData(item.ScreenName)).ToList();

Another class property call from base class list

I have a two class properdata and pprosecnddata both classes having property
I want to access product property from properdata class list object. How is it possible,below is my sample code
pupilc class ProperData
{
public string code{get;set;}
public List<ProSecndData>Secnd{get;set;}
}
public class ProSecndData
{
public string product{get;set;}
}
I am trying to call property like that
class Program
{
static void Main(string[] args)
{
ProperData.Secnd.Product = "Hello";
}
}
you cannot directly access property of Secnd as it is a list
you need to iterate or select the index of the List<Secnd>
you must initialize Secnd first and Secnd should have items in the list
properData.Secnd = new List<ProSecndData>();
so it can be access via
foreach(var second in properData.Secnd)
{
second.product = "hello";
}
//or
for(var i = 0; i < proderData.Secnd.Count(); i++)
{
properData.Secnd[i].product = "hello";
}
//or
var index = //0-length of list;
properData.Secnd[index].product = "hello";
if you want to have items first then add first on your Secnd List
properData.Secnd = new List<ProSecndData>();
properData.Secnd.Add(new ProSecndData{ product = "hello"});
then you now can iterate the list by using methods above
You are trying to access list as a single object, which is not possible.
you need to create single instance of your list class and then you can add string in that single instance.
properData.Secnd = new List<ProSecndData>();
ProSecndData proSecndData = new ProSecndData();
proSecndData.product = "Hello";
properData.Secnd.Add(proSecndData);
Actually I know the answer already, you have not created a constructor to initialise your List.
I'm guessing you get a object null ref error?
Create the constructor to initialise your list and it should be fine.
But in future, please post the error message (not the whole stack, just the actual error) as well as all the code required to repeat the issue. Otherwise you run the risk of getting your question deleted
(It should be deleted anyway because it could be considered a "what is a null ref err?" question).
Also you are accessing an item in a list like the list is that item (should be more like: ProperData.Secnd.elementAt(0).product, please also note the capitalisation of 'product' in the model vs your code.

How to use dynamic Linq with List<dynamic> object

I have a List of dynamic objects that I am trying to use dynamic Linq on. I am using dynamic objects because I do not know the properties that will be coming into the object. Linq works on my dynamic object, but, to avoid giant hard coding if statements, I would like to use dynamic Linq to search my list. The top half of the code snippet works but I need it to work dynamically so I can create a query string from my properties and filter that way.
public List<dynamic> GetFilteredLocationData(List<dynamic> locationData, string searchTerm){
//Does work
List<dynamic> totalResults = locationData.Where(x => x.Street.ToLower().Contains(searchTerm.ToLower()) ||
x.Street.ToLower().Contains(searchTerm.ToLower()) ||
x.Zip.ToLower().Contains(searchTerm.ToLower()));
//Does not work
var testQueryString = "(Street == \"king\")";
var testResult = locationData.Where(testQueryString);
return totalResults;
}
The runtime error I receive: No property or field 'Street' exists in type 'Object'
That error makes sense as object by default doesn't contain 'Street' but I'd expect the dynamic Linq to behave like the code above it. Is there something I am doing wrong here, or should I take a different approach? I can provide more detail if needed.
Thanks in advance!
Finally I got a working solution! It may not be the most efficient but it works for my needs and allows me to keep the dynamic nature I was hoping to retain. The solution was to drop Linq entirely and use a good old for-each loop. The Important part was the IDictionary which allowed me to search each row for the key value pair. This is the same functionality I was going for, just ditched linq.
public List<dynamic> GetFilteredLocationData(List<dynamic> locationData, string searchTerm){
List<dynamic> totalResults = new List<dynamic>();
List<string> locationProperties = new List<string> {"dynamic properties here, this was filled by call to DB for info pertaining to certain location combined with unique data"}
foreach (var locData in locationData)
{
var currentLoc = locData;
var currentLocDict = (IDictionary<string, object>)currentLoc;
bool containsSearchTerm = CheckIfLocationContainsSearch(currentLocDict, allLocationProperties, searchTerm);
if (containsSearchTerm)
{
totalResults.Add(locData);
}
}
}
public bool CheckIfLocationContainsSearch(IDictionary<string,object> location, List<string> locationProperties, string searchTerm){
foreach (var locProp in locationProperties)
{
if (location[locProp].ToString().ToLower().Contains(searchTerm))
{
return true;
}
}
return false;
}

How to get a String in a StringList ? C#

I have a small problem with my Exchange Appointment. The idea is to sync a meeting from sharepoint calendar to the personal exchange calendar.
I have this StringList in my CalendarItem Class:
private StringList m_Category;
public StringList Category { get { return m_Category; } }
And there it should go:
Microsoft.Exchange.WebServices.Data.Appointment xApointment = new Appointment(m_Service)
xApointment.Categories = xItem.Category; //xItem = Instance of CalendarItem
In the Microsoft.Exchange.WebService.Data.Appointment I have the predefinied StingList Categories.
What happens now is that I'm parsing through an XML File which looks like:
<listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:z="#RowsetSchema"
xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<rs:data ItemCount="1">
<z:row ows_ContentTypeId="0x010200C5A7325634A3154BB8249D1C36246E00"
ows_Title="Test GetAllViewFields"
ows_Location="Testhausen"
ows_EventDate="2014-12-15 08:00:00"
ows_EndDate="2014-12-15 09:00:00"
ows_Description="Ein Test meeting"
ows_fAllDayEvent="0"
ows_fRecurrence="0"
ows_EventType="0"
ows_RecurrenceID="2014-12-15 08:00:00"
ows_Duration="3600"
ows_ParticipantsPicker=""
***ows_Category="Geschäftlich"***
And than I'm parsing this whole XML Code as a String and check if the name is there:
private void initFromXmlAttribute(System.Xml.Linq.XAttribute x)
{
string AttributeName = x.Name.LocalName.Replace("ows_", "");
try
{
if
(AttributeName == "Category")
{
m_Category= x.Value; //Error implicite convert not possible StringList to String
return;
}
The Error is because m_Category = StringList and x.Value = String.
Does anyone has an idea how to solve this little issue?
I am not familiar with class StringList, but I guess it a Collection.
You can simply initialize a new StringList with the string inside it :
m_Category = new StringList() { x.Value };
Assuming you are asking about this class, you'll see that its constructor accepts an IEnumerable<string>, so you can write:
m_Category=new StringList(new[]{x.Value});
StringList implements IEnumerable so you can also use the collection initializer syntax:
m_Category=new StringList{x.Value};
This creates the class in two steps - first creates an empty object and then calls Add for each item in the initializer
You should be able to create a new Stringlist with the desired values (StringList inherits from List(Of String), so it's quite straightforward:
myStringList = new StringList()
myStringList.add(x.Value)
Btw since you are effectively setting your "Category" Property you might want to consider including a "set" statement to your property instead of modifying your private variable directly. In fact you can skip defining your private variable completely by using:
public StringList Category { get; set; }
Category = new StringList()
The compiler will do the rest for you.

What are alternatives to declaring data structure in functions?

Is there a good existing or upcoming alternative in C# to declaring data structures in methods? It's possible to use anonymous types, but there are difficulties with declaring them. Let's say I have a hypothetical class:
class ThingsManager
{
private void DoThings(IEnumerable<Thing> things)
{
var thingLocations = new Dictionary<string, string>();
foreach(var thing in things)
{
// some complicated logic and checks for current thing;
// if current thing satisfies all conditions:
var thingName = thing.Name;
var thingLocation = location; // taken somewhere from upper lines
thingLocations.Add(thingName, thingLocation);
}
// ... later
foreach(var thingLocation in thingLocations)
{
// here I don't know what is the key and what does the value mean.
// I could use Linq and anonymous types, but sometimes it is clearer
// to use foreach if the logic is complicated
}
}
}
Now, what I'd like to see:
class ThingsManager
{
private void DoThings(IEnumerable<Thing> things)
{
struct ThingLocations
{
string ThingName {get;set;}
string Location {get;set;}
}
var thingLocations = new List<ThingLocations>();
foreach(var thing in things)
{
// some complicated logic and checks for current thing;
// if current thing satisfies all conditions:
var thingName = thing.Name;
var thingLocation = location; // taken somewhere from upper lines
thingLocations.Add(new ThingLocation(thingName, thingLocation));
}
// ... later
foreach(var thingLocation in thingLocations)
{
// now here I can use thingLocation.ThingName
// or thingLocation.Location
}
}
}
I could also declare the structure in the class, but it doesn't make sense to use it anywhere except in my function. It would be better if my function were the only place where I could use this data structure. I'm looking for a better way to handle such situations, or at least be able to declare anonymous types.
Anonymous types would help with the naming aspect, but you would have to translate the input into your anonymous type and the type would remain internal to the method scope.
// Assumes thingLocation comes from somewhere...
var thingLocations = things
.Select(t => new { ThingName = t.Name, Location = new ThingLocation(t.Name, thingLocation) } );
It is done using the Select extension method in order to project to an anonymous type.
You can declare anonymous types without linq, but you will find it annoying trying to add those to lists / dictionaries:
var me = new { Name = "Adam", Age = 27 };
I'm going on record to say that I wouldn't take this approach, personally I'd either use anonymous types, a Tuple<string, string>, or a custom type.
Failing all of that, and if you don't mind firing up the DLR, you could use an ExpandoObject:
class Thing
{
public string Name;
}
static void Main(string[] args)
{
var things = new List<Thing>() { new Thing { Name = "Adam" } };
var thingLocations = new List<dynamic>();
foreach (var thing in things)
{
dynamic location = new ExpandoObject();
location.Name = thing.Name;
location.Location = "here";
thingLocations.Add(location);
}
// ... later
foreach(var thingLocation in thingLocations)
{
Console.WriteLine(thingLocation.Name);
Console.WriteLine(thingLocation.Location);
}
Console.ReadLine();
}
This allows you to dynamically add properties as you need them by declaring them on the spot. You can then use these later because ExpandoObject provides the plumbing to the DLR when the DLR asks for a member by name.
C# does indeed support Anonymous Types, but the real answer is:
No, you can't do that in C#. Just declare the struct as private right above your method and forget about it.

Categories

Resources