How to create a List<Dictionary<string, string>> list from a linq query - linq

I have the following code that does what I want however I was wondering if there was a way to do the same thing directly from a linq query.
XElement xmlData = XElement.Parse(items.Xml);
var itemsNotSynched =
(from a in xmlData.Descendants(XName.Get("row", "#RowsetSchema"))
group a by new
{
employeeID = (string)a.Attribute("ows_EmployeeID"),
courseID = (string)a.Attribute("ows_CourseID"),
title = (string)a.Attribute("ows_LinkTitle")
} into ex
select new
{
ex.Key.title,
ex.Key.courseID,
ex.Key.employeeID
} into eb
select eb).ToArray();
List<Dictionary<string, string>> list = new List<Dictionary<string, string>>();
foreach(var item in itemsNotSynched)
{
Dictionary<string, string> itm = new Dictionary<string, string>();
itm.Add("employeeID", item.employeeID.ToString());
if(item.courseID != null)
{
itm.Add("courseID", item.courseID.ToString());
}
itm.Add("title", item.title.ToString());
list.Add(itm);
}
Thanks in advance,
-EC-
Edit 1.
I managed to get what I wanted with using the suggestion from SLaks... I'll give it another shot at the .Distinct()
XElement xmlData = XElement.Parse(items.Xml);
List<Dictionary<string,string>> itemsNotSynched =
(from a in xmlData.Descendants(XName.Get("row", "#RowsetSchema"))
group a by new
{
employeeID = (string)a.Attribute("ows_EmployeeID"),
courseID = (string)a.Attribute("ows_CourseID"),
title = (string)a.Attribute("ows_LinkTitle")
} into g
select new Dictionary<string, string>
{
{"employeeID", g.Key.employeeID },
{"courseID", g.Key.courseID },
{"title", g.Key.title}
} into f
select f).ToList();

select new Dictionary<string, string> {
{ "employeeID", ex.Key.title },
...
}

Using dot/fluent syntax, this is what I believe you want:
XElement xmlData = XElement.Parse(items.Xml);
List<Dictionary<string,string>> itemsNotSynched =
xmlData.Descendants(XName.Get("row", "#RowsetSchema"))
.Select(a => new
{
employeeID = (string)a.Attribute("ows_EmployeeID"),
courseID = (string)a.Attribute("ows_CourseID"),
title = (string)a.Attribute("ows_LinkTitle")
})
.Distinct()
.Select(a => new Dictionary<string, string>
{
{"employeeID", a.employeeID },
{"courseID", a.courseID },
{"title", a.title}
})
.ToList();
Distinct() accomplishes the same thing as grouping but only using the keys. As written, this Distinct() implementation is nearly identical to what you already had, but it may perform better and/or use less memory.

Related

elasticsearch nest stopword filter does not work

I am tiring to implement elasticsearch NEST client and indexing documents and SQL data and able to search these perfectly. But I am not able to apply stopwords on these records. Below is the code. Please note I put "abc" as my stopword.
public IndexSettings GetIndexSettings()
{
var stopTokenFilter = new StopTokenFilter();
string stopwordsfilePath = Convert.ToString(ConfigurationManager.AppSettings["Stopwords"]);
string[] stopwordsLines = System.IO.File.ReadAllLines(stopwordsfilePath);
List<string> words = new List<string>();
foreach (string line in stopwordsLines)
{
words.Add(line);
}
stopTokenFilter.Stopwords = words;
var settings = new IndexSettings { NumberOfReplicas = 0, NumberOfShards = 5 };
settings.Settings.Add("merge.policy.merge_factor", "10");
settings.Settings.Add("search.slowlog.threshold.fetch.warn", "1s");
settings.Analysis.Analyzers.Add("xyz", new StandardAnalyzer { StopWords = words });
settings.Analysis.Tokenizers.Add("keyword", new KeywordTokenizer());
settings.Analysis.Tokenizers.Add("standard", new StandardTokenizer());
settings.Analysis.TokenFilters.Add("standard", new StandardTokenFilter());
settings.Analysis.TokenFilters.Add("lowercase", new LowercaseTokenFilter());
settings.Analysis.TokenFilters.Add("stop", stopTokenFilter);
settings.Analysis.TokenFilters.Add("asciifolding", new AsciiFoldingTokenFilter());
settings.Analysis.TokenFilters.Add("word_delimiter", new WordDelimiterTokenFilter());
return settings;
}
public void CreateDocumentIndex(string indexName = null)
{
IndexSettings settings = GetIndexSettings();
if (!this.client.IndexExists(indexName).Exists)
{
this.client.CreateIndex(indexName, c => c
.InitializeUsing(settings)
.AddMapping<Document>
(m => m.Properties(ps => ps.Attachment
(a => a.Name(o => o.Documents)
.TitleField(t => t.Name(x => x.Name)
.TermVector(TermVectorOption.WithPositionsOffsets))))));
}
var r = this.client.GetIndexSettings(i => i.Index(indexName));
}
Indexing Data
var documents = GetDocuments();
documents.ForEach((document) =>
{
indexRepository.IndexData<Document>(document, DOCindexName, DOCtypeName);
});
public bool IndexData<T>(T data, string indexName = null, string mappingType = null)
where T : class, new()
{
if (client == null)
{
throw new ArgumentNullException("data");
}
var result = this.client.Index<T>(data, c => c.Index(indexName).Type(mappingType));
return result.IsValid;
}
In one of my document I have put a single line "abc" and I do not expect this to be returned as "abc" is in my stopword list. But On Searching Document It is also returning the above document. Below is the search query.
public IEnumerable<dynamic> GetAll(string queryTerm)
{
var queryResult = this.client.Search<dynamic>(d => d
.Analyzer("xyz")
.AllIndices()
.AllTypes()
.QueryString(queryTerm)).Documents;
return queryResult;
}
Please suggest where I am going wrong.

NHibernate GroupBy error

Good morning
I am pulling my hair on a simple linq query used for building a json:
JsonSerializer serializer = new JsonSerializer();
JObject myJSON = new JObject();
var result = new
{
test = from e in myTable
group e by new { e.col1, e.col2 } into g
select new
{
Code = g.Key.col1,
Name = g.Key.col2,
data = from e in myTable
where e.col1== g.Key.col1
select new
{
myField= e.field1
}
}
};
myJSON = JObject.FromObject(result, serializer);
When i tried that i got a:
System.NotImplementedException: The method or operation is not implemented.
at NHibernate.Linq.GroupBy.NonAggregatingGroupByRewriter.FlattenSubQuery(SubQueryExpression subQueryExpression, QueryModel queryModel).
My linq query does not look that complicated but i have exhausted all my attempts.
Your lights on that would be welcome.
Thanks
Sylvain
OK, finally found it. Just had to do the following:
JsonSerializer serializer = new JsonSerializer();
JObject myJSON = new JObject();
var result = new
{
test = from e in myTable.ToList()
group e by new { e.col1, e.col2 } into g
select new
{
Code = g.Key.col1,
Name = g.Key.col2,
data = from e in myTable
where e.col1== g.Key.col1
select new
{
myField= e.field1
}
}
};
myJSON = JObject.FromObject(result, serializer);
with a .ToList() on the first query.
Sylvain

How to iterate through GroupBy groups using Dynamic LINQ? [duplicate]

I am using Dynamic Linq helper for grouping data. My code is as follows :
Employee[] empList = new Employee[6];
empList[0] = new Employee() { Name = "CA", State = "A", Department = "xyz" };
empList[1] = new Employee() { Name = "ZP", State = "B", Department = "xyz" };
empList[2] = new Employee() { Name = "AC", State = "B", Department = "xyz" };
empList[3] = new Employee() { Name = "AA", State = "A", Department = "xyz" };
empList[4] = new Employee() { Name = "A2", State = "A", Department = "pqr" };
empList[5] = new Employee() { Name = "BA", State = "B", Department = "pqr" };
var empqueryable = empList.AsQueryable();
var dynamiclinqquery = DynamicQueryable.GroupBy(empqueryable, "new (State, Department)", "it");
How can I get back the Key and corresponding list of grouped items i.e IEnumerable of {Key, List} from dynamiclinqquery ?
I solved the problem by defining a selector that projects the Key as well as Employees List.
var eq = empqueryable.GroupBy("new (State, Department)", "it").Select("new(it.Key as Key, it as Employees)");
var keyEmplist = (from dynamic dat in eq select dat).ToList();
foreach (var group in keyEmplist)
{
var key = group.Key;
var elist = group.Employees;
foreach (var emp in elist)
{
}
}
The GroupBy method should still return something that implements IEnumerable<IGrouping<TKey, TElement>>.
While you might not be able to actually cast it (I'm assuming it's dynamic), you can certainly still make calls on it, like so:
foreach (var group in dynamiclinqquery)
{
// Print out the key.
Console.WriteLine("Key: {0}", group.Key);
// Write the items.
foreach (var item in group)
{
Console.WriteLine("Item: {0}", item);
}
}

Problem returning an IEnumerable<T>/IList<T>

I am having trouble to return an IEnumerable and IList, I cant do it!
I am using EF 4 with POCOs
Here's the whole method:
//public IList<Genre> GetGenresByGame(int gameId)
public IEnumerable<Genre> GetGenresByGame(int gameId)
{
using(var ctx = new XContext())
{
var results =
from t0 in ctx.GameGenres
join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
where t0.GameId == gameId && t1.CultureId == _cultureId
select new Genre
{
GenreId = t0.GenreId,
GenreName = t1.GenreName
};
return results.ToList();
}
}
I have tried different ways that I have found on the net.. but can't make it work!
Question 2:
I saw a screencast with Julie something, saying that "You should always return an ICollection" when using EF4.
Any thoughts about that ?
BR
EDIT:
When I load the page in Debug-mode i get these errors: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. OR The entity or complex type 'XModel.Genre' cannot be constructed in a LINQ to Entities query.
Genre must not be a L2EF type. Try this:
public IEnumerable<Genre> GetGenresByGame(int gameId)
{
using(var ctx = new XContext())
{
var resultList =
from t0 in ctx.GameGenres
join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
where t0.GameId == gameId && t1.CultureId == _cultureId
select new { t0.GenreId, t1.GenreName };
var genres = resultList.AsEnumerable().Select(o => new Genre
{
GenreId = o.GenreId,
GenreName = o.GenreName
});
return genres.ToList();
}
}
First an foremost if Genre is in the database you should select it? If you have FKs from Genre->GenreCultureDetails let me know and I can update the below, but from the looks of it you could do it like this:
using(var ctx = new XContext())
{
var results =
from g in ctx.Genre
join gcd in ctx.GenreCultureDetails on g.GenreId equals gcd.GenreId
where g.GameId == gameId && gcd.CultureId == _cultureId
select g;
return result.ToList();
}
Alternatively continue down your path select them into an annoynmous type, and then copy them. You can use select instead of convertall if you please.
IList<Genre> returnMe = Null;
using(var ctx = new XContext())
{
var results =
from t0 in ctx.GameGenres
join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
where t0.GameId == gameId && t1.CultureId == _cultureId
select new
{
GenreId = t0.GenreId,
GenreName = t1.GenreName
};
returnMe = results.ToList().ConvertAll(x=>new Genre(){
GenreId = x.GenreId,
GenreName = x.GenreName
}
);
}
return returnMe;

LINQ distinct join query

I am trying to get a distinct list of tags for a record. It sort of works except the tag name is always the first one repeated.
public EntityCollection<TagEntity> Tags
{
get
{
EntityCollection<TagEntity> x = new EntityCollection<TagEntity>()
{
new TagEntity(){Id=1, IsActive=true, Name="Tag1"},
new TagEntity(){Id=2, IsActive=true, Name="Tag2"},
new TagEntity(){Id=3, IsActive=true, Name="Tag3"},
new TagEntity(){Id=4, IsActive=true, Name="Tag1"},
new TagEntity(){Id=5, IsActive=true, Name="Tag5"},
new TagEntity(){Id=6, IsActive=true, Name="Tag6"},
};
return x;
}
}
public EntityCollection<StoryTagsEntity> StoryTags
{
get
{
EntityCollection<StoryTagsEntity> x = new EntityCollection<StoryTagsEntity>()
{
new StoryTagsEntity(){ TagId=1, StoryId=1},
new StoryTagsEntity(){ TagId=1, StoryId=2},
new StoryTagsEntity(){ TagId=2, StoryId=1},
new StoryTagsEntity(){ TagId=3, StoryId=1},
new StoryTagsEntity(){ TagId=2, StoryId=3},
new StoryTagsEntity(){ TagId=4, StoryId=1},
};
return x;
}
}
public List<string> FetchTagNamesByStory(bool? isActive, int StoryId)
{
var d = (from t in this.Tags
join st in this.StoryTags on t.Id equals st.StoryId
where t.IsActive == isActive.GetValueOrDefault() && st.StoryId == StoryId
select t.Name);
List<string> x = new List<string>();
foreach (var item in d)
{
x.Add(item);
}
return x;
}
Which results in a list of tags like this:
Tag1, Tag1, Tag1, Tag1
Where that should be:
Tag 1, Tag2, Tag3, Tag1
Any ideas?
You're joining t.Id to st.StoryId instead of st.TagId. If you pass in StoryId of 1, you'll always get Tag1.
You are correct, your join was wrong, also you can do the following:
public List<string> FetchTagNamesByStory(bool? isActive, int storyId)
{
return (from t in Tags
join st in StoryTags on t.Id equals st.TagId
where t.IsActive == isActive.GetValueOrDefault() && st.StoryId == storyId
select t.Name).ToList();
}

Resources