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

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?

Related

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;
}

Convert query expression to lambda in LINQPad4

While coding I had came across a LINQ query that I was able to accomplish in query syntax but not in lamda syntax. While this works fine in the application, I wanted to learn the query syntax for what I was trying to do.
Essentially, I have a database with views, CO_Leather_V and CO_LeatherSizeColor_V. I also have two classes, CuttingOrder and CuttingOrderDetail. CuttingOrderDetail contains entirely string,int and float properties. The CuttingOrder Class contains 2 string properties and a List of CuttingOrderDetails.
public class CuttingOrder
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public List<CuttingOrderDetail> details { get; set; }
}
public class CuttingOrderDetail
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public string itemCode { get; set; }
public string material { get; set; }
public string color { get; set; }
public string size { get; set; }
public int qty { get; set; }
public float squareFeet { get; set; }
public float squareFeetUsed { get; set; }
}
The query expression I used to get a list of all CuttingOrders with a given SalesOrder was
cos = (from l in db.CO_Leather_Vs
where l.orderNo == Globals.orderNo
select new Globals.CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = (
from d in db.CO_LeatherSizeColor_Vs
select new Globals.CuttingOrderDetail
{
cuttingOrderNo = d.orderNo
}
).ToList()
}).ToList();
I converted this to work in LINQPad with the following query, but I can't get anything to show on the lambda pane.
void Main()
{
var p = (from l in CO_Leather_V
select new CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = (
from d in CO_LeatherSizeColor_V
select new CuttingOrderDetail
{
cuttingOrderNo = d.OrderNo
}
).ToList()
}).ToList();
p.Dump();
}
// Define other methods and classes here
public class CuttingOrder
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public List<CuttingOrderDetail> details { get; set; }
}
public class CuttingOrderDetail
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public string itemCode { get; set; }
public string material { get; set; }
public string color { get; set; }
public string size { get; set; }
public int qty { get; set; }
public float squareFeet { get; set; }
public float squareFeetUsed { get; set; }
}
If anyone knows how to perform the linq query in lambda form or knows why LINQPad is unable to generate the lamda form it would be greatly appreciated.
This should work:
var p = CO_Leather_V.Select(l=> new CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = CO_LeatherSizeColor_V.Select(d=>new CuttingOrderDetail {cuttingOrderNo = d.OrderNo}).ToList()
}).ToList();
However, CO_LeatherSizeColor_V does not reference l, so you're going to get everything in that table, every time. You might want something like:
details = l.LeatherSizeColor.Select(d=>new CuttingOrderDetail {cuttingOrderNo = d.OrderNo}).ToList()
for that line instead.

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;

RavenDB SelectMany not supported

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.

Resources