RavenDB SelectMany not supported - linq

I am trying to find one or more documents in RavenDB based on the values of a child collection.
I have the following classes
public class GoldenDocument
{
public GoldenDocument()
{
LinkedDocuments = new List<LinkedDocument>();
MergeMatchFields = new List<MergeMatchField>();
}
public string Id { get; set; }
public Guid SourceRowId { get; set; }
public List<MergeMatchField> MergeMatchFields { get; set; }
public List<LinkedDocument> LinkedDocuments { get; set; }
}
And the class that is in the collection MergeMatchFields
public class MergeMatchField
{
public string Id { get; set; }
public Guid OriginId { get; set; }
public string Name { get; set; }
public MatchType MatchType { get; set; }
public double MatchPerc { get; set; }
public string Value { get; set; }
}
In a List<MergeFields> mergeFields collection I have values that is not stored in RavenDB yet. Values are compared to values in a RavenDB document for find if it is a possible match by executing the following query:
using (var session = documentStore.OpenSession())
{
var docs = from gd in session.Query<GoldenDocument>()
from mf in gd.MergeMatchFields
from tf in mergeFields
where mf.Name == tf.Name
&& JaroWinklerCalculator.jaroWinkler(mf.Value, tf.Value) > .90d
&& !string.IsNullOrEmpty(mf.Value)
select gd;
}
I understand that ravenDB does not support SelectMany() so how would I go about getting the results from the Document store?

Create an index for this that would output the values you want to query on.
Note that you can't just execute arbitrary code the way you do here: JaroWinklerCalculator.jaroWinkler(mf.Value, tf.Value) > .90d
But you can use fuzzy queries, and they will do the same.

Related

how to use projection in the include extension method in ef core?

I want to able to select certain entity properties (columns from db) in the include statement of queryable object. My query looks like below but I m getting error Lambda expression used inside Include is not valid
var samuraiWithQuotesQueryable = _context.Samurais.AsQueryable()
.Include(s => s.Quotes.Select(x => new { x.Text }));
// additional filters followed by getting the list
var samuraiList = samuraiWithQuotesQueryable.ToList();
Samurai and Quote entities look like below
public class Samurai
{
public Samurai()
{
Quotes = new List<Quote>();
}
public int Id { get; set; }
public string Name { get; set; }
public List<Quote> Quotes { get; set; }
}
public class Quote
{
public int Id { get; set; }
public string Text { get; set; }
public Samurai Samurai { get; set; }
public int SamuraiId { get; set; }
}
Wondering if this is possible with the IQueryable object?

Trying to Populate ViewModel List from Linq query MVC "List doesn't contain definiton for ..."error"

I am (trying to) build a multiple choice test application that will pass a list of multiple choice questions (select lists) from the controller to a view.
Then populate the view using a foreach loop, post the answers back to the controller, check them and increment the score for each correct answer and then update the db.
I am trying to populate the view model list using a Linq query (to keep my controller thin, I am doing this via a method in my Service layer).
Models
Questions (db first)
namespace AccessEsol.Models
{
using System;
using System.Collections.Generic;
public partial class Question
{
public Question()
{
this.ExamDets = new HashSet<ExamDet>();
}
public int QuID { get; set; }
public string Text1 { get; set; }
public string Text2 { get; set; }
public string CorrectAnswer { get; set; }
public string Foil1 { get; set; }
public string Foil2 { get; set; }
public string Foil3 { get; set; }
public string Level_ { get; set; }
public string GrammarPoint { get; set; }
public virtual ICollection<ExamDet> ExamDets { get; set; }
}
}
Exam
namespace AccessEsol.Models
{
using System;
using System.Collections.Generic;
public partial class Exam
{
public Exam()
{
this.Candidates = new HashSet<Candidate>();
this.ExamDets = new HashSet<ExamDet>();
}
public int ExamID { get; set; }
public string Name { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public int AdminID { get; set; }
public string StartLevel { get; set; }
public virtual Administrator Administrator { get; set; }
public virtual ICollection<Candidate> Candidates { get; set; }
public virtual ICollection<ExamDet> ExamDets { get; set; }
}
}
There is also a model for Candidate that contains the CandID:
And the view model that uses these models:
namespace AccessEsol.Models
{
public class ExamQuestionsViewModel
{
public int QuID { get; set; }
public int CandID { get; set; }
public int ExamId { get; set; }
public string Text1 { get; set; }
public string Text2 { get; set; }
public string CorrectAnswer { get; set; }
public string Foil1 { get; set; }
public string Foil2 { get; set; }
public string Foil3 { get; set; }
public string Level { get; set; }
public string GrammarPoint { get; set; }
public virtual ICollection<ExamDet> ExamDets { get; set; }
}
}
This is the method that is to populate the view model:
public static List<ExamQuestionsViewModel> AddQuestions()
{
AccessEsolDataEntities db = new AccessEsolDataEntities();
string questionLevel = GetLevel();
int currentCand = GetCandID();
int currentExam = GetExamID();
//model = new DataAccess().Populate();
var qu = (from a in db.Questions
where a.Level_ == questionLevel
select a).ToList();
List<ExamQuestionsViewModel> exam = new List<ExamQuestionsViewModel>();
foreach (var IDs in exam)
{
currentCand = exam.CandID;
currentExam = exam.ExamId;
}
return (exam);
}
The error message I am getting is
'System.Collections.Generic.List<AccessEsol.Models.ExamQuestionsViewModel>'
does not contain a definition for 'ExamId' and no extension method
'ExamId' accepting a first argument of type
'System.Collections.Generic.List<AccessEsol.Models.ExamQuestionsViewModel>' could be found (are you missing a using directive or an assembly
reference?
What am I doing wrong here? All feedback much appreciated.
Please try this instead of your foreach:
foreach (var IDs in exam)
{
currentCand = IDs.CandID;
currentExam = IDs.ExamId;
}

Joining in LINQ to select a sublist within a list

I have two classes as follows:
public class HRM_SERVICE_PERD_BNFT_DTLModel
{
public string SRVC_PERD_BNFT_CODE { get; set; }
public string RTR_BNFT_CODE { get; set; }
public string RTR_BNFT_NAME { get; set; }
public string RTR_BNFT_CALC_MODE { get; set; }
public string SAL_HEAD_CODE { get; set; }
public string SAL_HEAD_NAME { get; set; }
public string RTR_BNFT_IN_PERCENT { get; set; }
public string RTR_BNFT_AMOUNT { get; set; }
public string RTR_BNFT_INACTV_DATE { get; set; }
public short? RTR_BNFT_SLNO { get; set; }
}
public class HRM_RETIREMENT_BENEFITModel : BaseModel
{
public string RTR_BNFT_CODE { get; set; }
public string RTR_BNFT_NAME { get; set; }
public string RTR_BNFT_SRTNM { get; set; }
public string RTR_BNFT_REM { get; set; }
public short? RTR_BNFT_SLNO { get; set; }
}
Now I want to select data from the first model for a specific 'SRVC_PERD_BNFT_CODE', then I need to select the 'RTR_BNFT_NAME' from the second table for all the filtered data along with some other value from the first model. I'm trying kind of joining, but not getting the name. It's showing system.collection.string instead of value.
Here is what I'm trying so far:
public List<HRM_SERVICE_PERD_BNFT_DTLModel> GetBenefitData(string mstcode)
{
var model2 = DataContext.HRM_SERVICE_PERD_BNFT_DTL.AsEnumerable().Where(m => m.SRVC_PERD_BNFT_CODE == mstcode).Select(s=>s).ToList();
var model = DataContext.HRM_SERVICE_PERD_BNFT_DTL.AsEnumerable().Where(m => m.SRVC_PERD_BNFT_CODE == mstcode)
.Select(s => new HRM_SERVICE_PERD_BNFT_DTLModel
{
RTR_BNFT_CODE = s.RTR_BNFT_CODE,
RTR_BNFT_SLNO = s.RTR_BNFT_SLNO,
RTR_BNFT_CALC_MODE = s.RTR_BNFT_CALC_MODE,
RTR_BNFT_AMOUNT = (s.RTR_BNFT_AMOUNT).ToString(),
RTR_BNFT_NAME = (from x in model2
join c in DataContext.HRM_RETIREMENT_BENEFIT on x.RTR_BNFT_CODE equals c.RTR_BNFT_CODE into p
from b in p.AsEnumerable()
select b.RTR_BNFT_NAME).ToList().ToString(),
RTR_BNFT_IN_PERCENT = (s.RTR_BNFT_IN_PERCENT).ToString()
}).ToList();
return model;
}
What I'm doing wrong? Please help.
Following is suspicious.
.ToList().ToString()
Remove the ToString part and replace it with something like FirstorDefault, then it should work.
Reason for getting something like System.Collection.String is that List<T>.ToString() is usually typename until it is overridden in some way.
Following minimal snipped produce System.Collections.Generic.List1[System.String]`
List<String> list = new List<String>();
var str = list.ToString();
Console.WriteLine(str); //System.Collections.Generic.List`1 [ System.String ]

Linq query to select items in list from another list

I have a dictionary and a list.
AllMeta: is a dictionary<string, WikiMeta>
Meta: is a list<WikiMeta>
public class WikiMeta
{
public string ContentTitle { get; set; }
public string PageTitle { get; set; }
public string PageMetaDescription { get; set; }
public List<WikiArticle> Articles = new List<WikiArticle>();
public List<WikiGroup> Groups = new List<WikiGroup>();
}
public class WikiGroup
{
public string Name { get; set; }
}
I need to select values from AllMeta where AllMeta.Values.Group == Meta.Group returning a list of WikiMeta.
However, I'm struggling to construct the syntax (lambda), so any help would be appreciated.
try this:
List<WikiMeta> wikis= AllMeta.Values
.Where(allmeta =>
Meta.Any(meta=> meta.Group == allmeta.Group))
.ToList();
where I've assumed following:
public class WikiMeta
{
public string Name { get; set; }
public string Group { get; set; }
}
public IDictionary<string,WikiMeta> AllMeta { get; set; }
public List<WikiMeta> Meta { get; set; }
make sure you referenced System.Linq namespace i.e.
using System.Linq;

Entity Framework/LINQ: Selecting columns from multiple tables?

Models:
public class User
{
[Key]
public int UserId { get; set; }
public string UserName { get; set; }
}
public class Resource
{
[Key]
public int ResourceId { get; set; }
public string ResourceName { get; set; }
public string ResourceDescription { get; set; }
}
public class UserResource
{
[Key, Column(Order=0)]
public int UserId { get; set; }
[Key, Column(Order=1)]
public int ResourceId { get; set; }
public int ResourceQuantity { get; set; }
}
I want to select "ResourceName" from Resource model and "ResourceQuantity" from UserResource model for a given "UserId". Also, once selected, do I need a brand new model to carry only those two specified columns?
Also note that UserResource model has a composite key so I am confused as to how to make the join... Is this right?
var userResources =
from r in imDB.Resources
join ur in imDB.UserResources
on r.ResourceId equals ur.ResourceId
select new { r.ResourceName, ur.ResourceQuantity };
Hence you're using Code first you can create your models are as below by using EF conventions.
public class User {
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Resource> Resources { get; set; }
}
public class Resource {
public int Id { get; set; }
public string ResourceName { get; set; }
public int ResourceQuantity { get; set; }
public virtual ICollection<User> Users {get;set;}
}
Then EF will generate your junction table is as UsersResources.You don't need to create additional model as you did.EF will look after that.
When using POCOs with EF, if you mark your navigation properties as
virtual you can use additional EF supports like Lazy Loading. So in
general use a virtual keyword in navigation properties considered to
be a good practice.
UPDATE
You may try something like below:
Method 1 : Method based syntax
imDB.Resources.Where(r => r.Users.Any(u => u.UserId == userId))
Method 2 : Query based syntax
from r in imDB.Resources
from u in r.Users
where u.UserId == userId
select r;
I hope this will help to you.

Resources