Linq assign to a List<> List Binding - linq

I'm getting this error at running time:
Exception Details: System.InvalidOperationException: Unhandled binding type: ListBinding
Choice_A, _b,_C are strings
'Choices' is List
var qs = (from questions in dc.Survey_Questions
where questions.Survey_ID == surveyid
select new SQuestions
{
QuestionID = questions.Question_ID,
Description = questions.Description,
Choice_A = questions.Choice_A,
Choice_B = questions.Choice_B,
Choice_C = questions.Choice_C,
**Choices = {questions.Choice_A, questions.Choice_B,
questions.Choice_C}**
}).ToList();
Basically I'd like to know how I assign to List Choices values of Choice_A,Choice_B, Choice_C.
Thanks in advance.

You can try this. If you already have the following two classes
public class Question
{
public int Question_ID { get; set; }
public int Survey_ID { get; set; }
public String Description { get; set; }
public String Choice_A { get; set; }
public String Choice_B { get; set; }
public String Choice_C { get; set; }
}
public class SQuestions
{
public int QuestionID { get; set; }
public String Description { get; set; }
public String Choice_A { get; set; }
public String Choice_B { get; set; }
public String Choice_C { get; set; }
public List<String> Choices { get; set; }
}
Then the LINQ Query will be
var qs = (from question in dc.Survey_Questions
where question.Survey_ID == surveyid
select new SQuestions
{
QuestionID = question.Question_ID,
Description = question.Description,
Choice_A = question.Choice_A,
Choice_B = question.Choice_B,
Choice_C = question.Choice_C,
Choices = new List<string>(new String[] { question.Choice_A,question.Choice_B, question.Choice_C })
}).ToList();

LINQ to Entities does not support this binding syntax. You should be able to do this, though:
qs = (from questions in dc.Survey_Questions
where questions.Survey_ID == surveyid
select new SQuestions
{
QuestionID = questions.Question_ID,
Description = questions.Description,
Choice_A = questions.Choice_A,
Choice_B = questions.Choice_B,
Choice_C = questions.Choice_C,
Choices = new List<string> {questions.Choice_A, questions.Choice_B,
questions.Choice_C}
}).ToList();

Related

.net core ef saving related data results in error SqlException: Cannot insert explicit value for identity column in table

Following this guide, I have tried to do the same in my web app:
var content = new Content()
{
IsActive = true,
Link = new Link()
{
DateCreated = DateTime.UtcNow,
LinkName = model.Name,
LinkDesc = model.Description,
LinkPath = model.LinkPath,
IsActive = true
}
};
_context.Contents.Add(content);
_context.SaveChanges();
This throws an error:
SqlException: Cannot insert explicit value for identity column in
table 'Links' when IDENTITY_INSERT is set to OFF.
But it works if I do this:
var content = new Content() {
IsActive = true
}
_context.Contents.Add(content);
_context.SaveChanges();
var link = new Link()
{
DateCreated = DateTime.UtcNow,
LinkName = model.Name,
LinkDesc = model.Description,
LinkPath = model.LinkPath,
IsActive = true,
ContentId = content.ContentId
};
_context.Links.Add(link);
_context.SaveChanges();
content.LinkId = link.LinkId;
_context.SaveChanges();
These are the models:
public class Content
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ContentId { get; set; }
public int? LinkId { get; set; } = null;
[ForeignKey("LinkId")]
public virtual Link Link { get; set; }
public DateTime DateCreated { get; set; } = DateTime.UtcNow;
public bool IsActive { get; set; }
}
public class Link
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int LinkId { get; set; }
[MaxLength(300)]
public string LinkDesc { get; set; }
[MaxLength(50)]
[Required]
public string LinkName { get; set; }
public DateTime DateCreated { get; set; } = DateTime.UtcNow;
public bool IsActive { get; set; }
[MaxLength(500)]
public string LinkPath { get; set; }
public int ContentId { get; set; }
[ForeignKey("ContentId")]
public virtual Content Content { get; set; }
}
Am I missing anything? Why would the first code try to insert a value to LinkId?

Max value LINQ using class

I've got this class
public class Materiale
{
public string IdMateriale { get; set; }
public string GenereMateriale { get; set; }
public string Categoria { get; set; }
public string Modello { get; set; }
public string Tipo { get; set; }
public string NumSerie { get; set; }
public int Anno { get; set; }
public string DittaCostruttrice { get; set; }
public string Note { get; set; }
public List<Controllo> Controlli = new List<Controllo>();
}
public class Controllo
{
public string IdControllo { get; set; }
public DateTime DataControllo { get; set; }
public string IdMateriale { get; set; }
public string Utente { get; set; }
public string Stato { get; set; }
public string Note { get; set; }
}
I want to query a list of "Materiale" filtering "Controlli". I need to retrieve all properties of the "Materiale" class and only one property of the "Controllo" class (the one named "Stato"). From the list "Controlli" I need the one that has the most recent "DataControllo" property.
I try this in a LINQ query but I receive an error (Max doesn't exist in the current context)
List<Materiale> m = new List<Materiale>();
List<Materiale> m2 = (from ma in m
from c in ma.Controlli
where c.DataControllo == Max(c.DataControllo)
select new
{
ma, c.Stato
}).ToList();
Can someone help me
#Christos is correct, here is my version with let in query syntax:-
List<Materiale> m2 = from m in MaterialeList
let RecentControllo = m.OrderByDescending(x => x.DataControllo)
.FirstOrDefault()
select new Materiale
{
IdMateriale = m.IdMateriale,
GenereMateriale = m.GenereMateriale,
//Similarily other properties of Materiale here
Stato = RecentControllo != null ? RecentControllo.Stato : ""
}).ToList();
I think that you need something more simple like the following one:
List<Materiale> m2 = from ma in m
let mostRecentControllo = ma.Controlli
.OrderByDescending(c=>c.DataControllo)
.FirstOrDefault()
select new
{
Materiale = ma,
Stato = mostRecentControllo != null
? mostRecentControllo.Stato : null
}).ToList();
I have supposed that each Materiale's Controlli list contains Controllo with the same IdMateriale.

Linq ORM map Object to 3 level Object

I have object like this. This include Group Question (QG), 1 group question has many Question(Q), 1 question has many answer.
public class CrmQuestionAnswer
{
public long QgId { get; set; }
public string QgName { get; set; }
public int QgMIndex { get; set; }
public int QgMdf { get; set; }
public string QgDescription { get; set; }
public long QId { get; set; }
public long QParentId { get; set; }
public string QName { get; set; }
public string QDescription { get; set; }
public int QMindex { get; set; }
public int QMdf { get; set; }
public bool IsMainQuestion { get; set; }
public bool IsTitle { get; set; }
public int QTypeId { get; set; }
public long AnswerId { get; set; }
public string AnswerName { get; set; }
public string AnswerValue { get; set; }
public int AnswerMdf { get; set; }
public int AnswerMIndex { get; set; }
public string AnswerDescription { get; set; }
public long? LinkQuestionId { get; set; }
}
I want to use Linq to map List CrmQuestionAnswer to List QuestionGroupView
public class QuestionGroupView:Title
{
public List<CrmQuestionView> Questions;
}
public class CrmQuestionView: Title
{
public long? ParentId;
public bool? IsMainQuestion;
public bool? IsTitle;
public long? LinkQuestionId;
public List<CrmAnswerView> Answers;
}
public class CrmAnswerView : Title
{
public long? LinkQuestionId;
}
Title is base class:
public class Title
{
public long Id { get; set; }
public string Name { get; set; }
public int MIndex { get; set; }
public int Mdf { get; set; }
public int Type { get; set; }
public string Description { get; set; }
}
I use this code:
public List<QuestionGroupView> GetListQuestionsAnswers(long themaId)
{
var questionAnswerDao = new CrmQuestionAnswerDao();
var questionAnswerlist = questionAnswerDao.GetByThemasId(themaId);
//map List CrmQuestionAnswer -> List QuestionGroupView: 3 level
var listquestiongroup = questionAnswerlist
.OrderBy(t => t.QgMIndex)
.ThenBy(t => t.QMindex)
.GroupBy(t => t.QgId)
.Select(GetQuestionGroup)
.ToList();
return listquestiongroup;
}
private static QuestionGroupView GetQuestionGroup(IGrouping<long, CrmQuestionAnswer> grouping)
{
var group = grouping.First();
var question = new QuestionGroupView
{
Id = group.QgId,
Name = group.QgName,
Description = group.QgDescription,
Mdf = group.QgMdf,
MIndex = group.QgMIndex,
Questions = grouping
.Select(p => new CrmQuestionView
{
Id = p.QId,
Name = p.QName,
Description = p.QDescription,
Mdf = p.QMdf,
MIndex = p.QMindex,
Type = p.QTypeId,
ParentId = p.QParentId,
IsMainQuestion = p.IsMainQuestion,
IsTitle = p.IsTitle,
Answers = grouping//**This line is wrong**
.GroupBy(g => g.QId)
.Select(GetTitle)
.ToList()
})
.ToList()
};
return question;
}
private static CrmAnswerView GetTitle(IGrouping<long, CrmQuestionAnswer> grouping)
{
var group = grouping.First();
var answer = new CrmAnswerView
{
Id = group.AnswerId,
Name = group.AnswerName,
Description = group.AnswerDescription,
MIndex = group.AnswerMIndex,
Mdf = group.AnswerMdf,
Type = group.QTypeId,
LinkQuestionId = group.LinkQuestionId,
};
return answer;
}
This is data get from server Data
My code gets right Group question (2 group) with right List question, but it gets wrong list answer from data.
Can some help me ?
Best regards

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.

most efficient Entity Framework Code First method of flattening / projecting parent entity with specific child

I have a parent entity Widget with core members and multiple WidgetTranslation children that have language translated members i.e. Description text available in English, French, German etc.
e.g.
public class Widget
{
public int Id { get; set; }
public string Code { get; set; }
public virtual ICollection<WidgetTranslation> WidgetTranslations { get; set; }
}
public class WidgetTranslation
{
public int WidgetId { get; set; }
public virtual Widget Widget { get; set; }
public int LanguageId { get; set; }
public virtual Language Language { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Summary { get; set; }
}
What is the most efficient method of querying the widget collection, flattening for a given LanguageId & projecting to a TranslatedWidget DTO
public class TranslatedWidget
{
public int Id { get; set; }
public string Code { get; set; }
public int LanguageId { get; set; }
public virtual Language Language { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Summary { get; set; }
}
Given languageId I've started with
DbSet.Select(w => new TranslatedWidget
{
Id = w.Id,
Code = w.Code,
LanguageId = w.LanguageId,
Name = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Name,
Description = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Description,
Summary = w.WidgetTranslations.First(wt=>wt.LanguageId == languageId).Summary
});
But I've a feeling this is inefficient and won't scale for more properties on WidgetTranslation.
Thanks
Use SelectMany to flatten structures via a single join:
var widgetQuery = from w in dbSet.Widgets
from wt in w.WidgetTranslations
where wt.Language == languageId
select new TranslatedWidget
{
Id = w.Id,
Code = w.Code,
LanguageId = w.LanguageId,
Name = wt.Name,
Description = wt.Description,
Summary = wt.Summary
});
I'm assuming here that you only have a single translation for each widget in a given language.
I would move Name, Description and Summary into a nested class of your DTO...
public class TranslatedWidgetTranslation
{
public string Name { get; set; }
public string Description { get; set; }
public string Summary { get; set; }
}
public class TranslatedWidget
{
public int Id { get; set; }
public string Code { get; set; }
public int LanguageId { get; set; }
public TranslatedWidgetTranslation Translation { get; set; }
}
Then you can project into that class and need First only once which would result in only one TOP(1) subquery in SQL instead of three:
DbSet.Select(w => new TranslatedWidget
{
Id = w.Id,
Code = w.Code,
LanguageId = languageId,
Translation = w.WidgetTranslations
.Where(wt => wt.LanguageId == languageId)
.Select(wt => new TranslatedWidgetTranslation
{
Name = wt.Name,
Description = wt.Description,
Summary = wt.Summary
})
.FirstOrDefault()
});
You must use FirstOrDefault here, First is not supported in a LINQ-to-Entities projection.
If you don't want that nested type you can project into anonymous types first and then convert into your final class, but the code will be a bit longer:
DbSet.Select(w => new
{
Id = w.Id,
Code = w.Code,
LanguageId = languageId,
Translation = w.WidgetTranslations
.Where(wt => wt.LanguageId == languageId)
.Select(wt => new
{
Name = wt.Name,
Description = wt.Description,
Summary = wt.Summary
})
.FirstOrDefault()
})
.AsEnumerable()
.Select(x => new TranslatedWidget
{
Id = x.Id,
Code = x.Code,
LanguageId = x.LanguageId,
Name = x.Translation != null ? x.Translation.Name : null,
Description = x.Translation != null ? x.Translation.Description : null,
Summary = x.Translation != null ? x.Translation.Summary : null
});

Resources