This method is not supported against a materialized query result - c#

Take a look at my code here:
public static ItemType GetItem(int id)
{
ItemType it = new ItemType();
using (var context = matrix2.matrix2core.DataAccess.Connection.GetContext())
{
var q = (from ci in context.Item
where ci.ID == id
let TemplateID = ci.TemplateID
let Groups = from x in context.CriteriaGroup
where x.TemplateID == TemplateID
select new
{
x
}
let CriteriaItems = from x in context.CriteriaItem
where Groups.Select(y => y.x.ID).Contains(x.CriteriaGroupID)
select new
{
x
}
select new
{
ci.ID,
ci.Name,
ci.CategoryID,
ci.Description,
ci.ItemValue,
TemplateID,
Groups,
CriteriaItems,
ItemValues = from x in context.ItemValue
where x.ItemID == id
select new
{
x,
CriteriaID = x.CriteriaItem.Criteria.ID
}
}).FirstOrDefault();
if (q != null)
{
it.ID = q.ID;
it.CategoryID = q.CategoryID;
it.Name = q.Name;
it.TemplateID = q.TemplateID;
it.Description = q.Description;
it.CriteriaGroups = new List<CriteriaGroupType>();
it.CriteriaItems = new List<CriteriaItemType>();
it.ItemValues = new List<ItemValueType>();
foreach (var x in q.ItemValues)
{
ItemValueType ivt = new ItemValueType();
ivt.CriteriaItemID = x.x.CriteriaItemID;
ivt.CriteriaID = x.CriteriaID;
ivt.Data = x.x.Data;
ivt.ID = x.x.ID;
ivt.ItemID = x.x.ItemID;
it.ItemValues.Add(ivt);
}
/////////error when I added the orderby clause
foreach (var x in q.Groups.OrderBy(x => x.x.SortOrder))
{
CriteriaGroupType cgt = new CriteriaGroupType();
cgt.ID = x.x.ID;
cgt.Name = !string.IsNullOrEmpty(x.x.Name) ? x.x.Name : "Group" + x.x.ID;
cgt.SortOrder = x.x.SortOrder;
cgt.TemplateID = x.x.TemplateID;
it.CriteriaGroups.Add(cgt);
}
/////////error when I added the orderby clause
foreach (var temp in q.CriteriaItems.OrderBy(x => x.x.SortOrder))
{
CriteriaItemType cit = new CriteriaItemType();
cit.ID = temp.x.ID;
cit.CriteriaGroupID = temp.x.CriteriaGroupID;
cit.GroupName = (temp.x.Name != null) ? temp.x.Name : "Group" + temp.x.ID;
cit.CriteriaID = temp.x.CriteriaID;
cit.CriteriaName = temp.x.Criteria.Name;
cit.Name = !string.IsNullOrEmpty(temp.x.Name) ? temp.x.Name : temp.x.Criteria.Name;
cit.Options = temp.x.Options;
it.CriteriaItems.Add(cit);
}
}
}
return it;
}
Instead of letting SQL handle the sorting (OrderBy) I wanted asp.net to do the sorting instead. I took the sorting out of the SQL linq query and put it on the foreach loop. When I did that I got the error. Is there a way to fix this?

You should be able to go from IQueryable to IEnumerable with a simple
var q2 = q.ToList();
What I meant of course was :
var groups = q.Groups.ToList();

Related

Linq query to get list inside list

Below is the query,
List<int> groupIdList = {1, 2};
var clientGroupData = from cge in base.context.Set<ClientGroupEngagement>()
join cg in base.context.Set<ClientGroup>() on cge.ClientGroupID equals cg.ClientGroupID
join cgu in base.context.Set<ClientGroupUser>() on cg.ClientGroupID equals cgu.ClientGroupID
join eng in base.context.Set<Engagement>() on cge.EngagementID equals eng.EngagementID
join cdc in base.context.Set<CountryDataCenter>()
on new { eng.CountryID, eng.EngagementVersion } equals new { cdc.CountryID, cdc.EngagementVersion }
join dc in base.context.Set<DataCenter>()
on cdc.DataCenterID equals dc.DataCenterID
join dcuri in base.context.Set<DataCenterURI>()
on new { dc.DataCenterID, cdc.EngagementVersion } equals new { dcuri.DataCenterID, dcuri.EngagementVersion }
join uritype in base.context.Set<URIType>()
on dcuri.URITypeID equals uritype.URITypeID
where groupIdList.Contains(cgu.ClientGroupID)
&& cg.IsActive
&& cdc.IsActive
&& dc.IsActive
&& dcuri.IsActive
&& uritype.IsActive
&& (dcuri.URITypeID == (int)URITypeEnum.WebUri || dcuri.URITypeID == (int)URITypeEnum.AppUri)
select new ClientGroupUserEngagementModel
{
EngagementId = cge.EngagementID,
EngagementDescription = eng.EngagementDescription,
EngagementStatusId = eng.EngagementStatusID,
ClientGroupId = cg.ClientGroupID,
ClientGroupGuid = cg.ClientGroupGUID,
ClientGroupName = cg.ClientGroupName,
UserId = cgu.ClientUserID,
FirstName = cgu.FirstName,
LastName = cgu.LastName,
IsGroupUserActive = cgu.IsActive,
LocatorDataModel = new LocatorDataModel
{
DatacenterId = cdc.DataCenterID,
DatacenterName = dc.DataCenterName,
EngagementVersion = cdc.EngagementVersion,
Uri = dcuri.URI,
UriTypeId = dcuri.URITypeID
},
};
var result = await clientGroupData.ToListAsync();
I am expecting list of LocatorDataModel in the result set. EngagementId is key which will be unique.
Currently it is pulling *2 records due to condition
(dcuri.URITypeID == (int)URITypeEnum.WebUri || dcuri.URITypeID == (int)URITypeEnum.AppUri)
How can get result like
Engagementid 1 : dataurl1 dataurl2
Engagementid 2: dataurl3 dataurl4, dataurl5
etc.
Any help is appreciated.
I think below sample code can help you:
var list = new[]
{
new { Engagementid = 1, Dataurl = "dataurl1"},
new { Engagementid = 1, Dataurl = "dataurl2"},
new { Engagementid = 2, Dataurl = "dataurl3"},
new { Engagementid = 2, Dataurl = "dataurl4"},
new { Engagementid = 2, Dataurl = "dataurl5"}
};
var result =
list.GroupBy(g => g.Engagementid)
.Select(c => new {Engagementid = c.Key, Dataurls = string.Join(",", c.Select(x=> x.Dataurl).ToList())})
.ToList();
That result will be:
[0]: { Engagementid = 1, Dataurls = "dataurl1,dataurl2" }
[1]: { Engagementid = 2, Dataurls = "dataurl3,dataurl4,dataurl5" }

Include Newest Note and Comment in List

I have to include both the newest Note and Comment with view model that I am passing to my list view but I cannot figure out how to include it in the view model.
I tried to do include but after I type p it will not give me a list of my properties for MinimumProductInfo which ProductNotes is a property for it.
Here is the controller code I am trying:
public ActionResult MinimumProductInfoList()
{
var Model = _minimumProductInfo.GetAll();
var Notes = db.ProductNotes.Where(p => p.NoteTypeFlag == "p").OrderByDescending(p => p.NoteDate).First();
var Comments = db.ProductNotes.Where(p => p.NoteTypeFlag == "c").OrderByDescending(p => p.NoteDate).First();
var Model = db.MinimumProductInfo.Include(p => p)
var ViewModel = Model.Select(x => new ProductInfoWithNoteList { MinimumProductInfoID = x.MinimumProductInfoID, ItemCode = x.ItemCode, MinimumOnHandQuantity = x.MinimumOnHandQuantity, MaximumOHandQuantity = x.MaximumOHandQuantity, MinimumOrderQuantity = x.MinimumOrderQuantity, LeadTimeInWeeks = x.LeadTimeInWeeks });
return View(ViewModel);
}
Everything else is working except now I need to include the latest note and latest comment in to my viewmodel
This is what I have now with WithMetta's help:
public ActionResult MinimumProductInfoList()
{
var productInfoViewModelCollection =
from x in db.MinimumProductInfo
let pnote =
(from inner_pnote in db.ProductNotes
where x.MinimumProductInfoID == inner_pnote.MinimumProductInfoID
&& inner_pnote.NoteTypeFlag == "p"
orderby inner_pnote.NoteDate
select inner_pnote).FirstOrDefault()
let cnote =
(from inner_cnote in db.ProductNotes
where x.MinimumProductInfoID == inner_cnote.MinimumProductInfoID
&& inner_cnote.NoteTypeFlag == "c"
orderby inner_cnote.NoteDate
select inner_cnote).FirstOrDefault()
select new ProductInfoWithNoteList
{
MinimumProductInfoID = x.MinimumProductInfoID,
ItemCode = x.ItemCode,
MinimumOnHandQuantity = x.MinimumOnHandQuantity,
MaximumOHandQuantity = x.MaximumOHandQuantity,
MinimumOrderQuantity = x.MinimumOrderQuantity,
LeadTimeInWeeks = x.LeadTimeInWeeks,
Comment = cnote.ToString(),
PermanentNote = pnote.ToString()
};
return View(productInfoViewModelCollection);
}
Maybe something like this using LINQ.
var productInfoViewModelCollection =
from x in db.MinimumProductInfo
where x != null
let pnote =
(from inner_pnote in db.ProductNotes
where inner_pnote != null
&& x.MinimumProductInfoID == inner_pnote.MinimumProductInfoID
&& inner_pnote.NoteTypeFlag == "p"
orderby inner_pnote.NoteDate descending
select inner_pnote).FirstOrDefault()
let cnote =
(from inner_cnote db.ProductNotes
where inner_cnote != null
&& x.MinimumProductInfoID == inner_cnote.MinimumProductInfoID
&& inner_cnote.NoteTypeFlag == "c"
orderby inner_cnote.NoteDate descending
select inner_cnote).FirstOrDefault()
select new ProductInfoWithNoteList {
MinimumProductInfoID = x.MinimumProductInfoID,
ItemCode = x.ItemCode,
MinimumOnHandQuantity = x.MinimumOnHandQuantity,
MaximumOHandQuantity = x.MaximumOHandQuantity,
MinimumOrderQuantity = x.MinimumOrderQuantity,
LeadTimeInWeeks = x.LeadTimeInWeeks,
Comment = cnote,
PermanentNote = pnote
};

IF statement inside a LINQ SELECT to include columns

Is it possible to include or exclude column within linq Select?
var numberOfYears = Common.Tool.NumberOfYear;
var list = users.Select(item => new
{
Id = item.Id,
Name= item.Name,
City= Item.Address.City.Name,
STATUS = Item.Status,
if(numberOfYears == 1)
{
Y1 = item.Records.Y1,
}
if(numberOfYears == 2)
{
Y1 = item.Records.Y1,
Y2 = item.Records.Y2,
}
if(numberOfYears == 3)
{
Y1 = item.Records.Y1,
Y2 = item.Records.Y2,
Y3 = item.Records.Y3,
}
}).ToList();
}
The idea is that i want to display Y1,Y2,Y3 only if has values
Thanks to the beauty of the dynamic keyword what you need is now possible in C#. Below an example:
public class MyItem
{
public string Name { get; set; }
public int Id { get; set; }
}
static void Main(string[] args)
{
List<MyItem> items = new List<MyItem>
{
new MyItem
{
Name ="A",
Id = 1,
},
new MyItem
{
Name = "B",
Id = 2,
}
};
var dynamicItems = items.Select(x => {
dynamic myValue;
if (x.Id % 2 == 0)
myValue = new { Name = x.Name };
else
myValue = new { Name = x.Name, Id = x.Id };
return myValue;
}).ToList();
}
This will return a list of dynamic objects. One with 1 property and one with 2 properties.
Try this approach:
var numberOfYears = Common.Tool.NumberOfYear;
var list = users.Select(item => new
{
Id = item.Id,
Name = item.Name,
City = Item.Address.City.Name,
STATUS = Item.Status,
Y1 = numberOfYears > 0 ? item.Records.Y1 : 0,
Y2 = numberOfYears > 1 ? item.Records.Y2 : 0,
Y3 = numberOfYears > 2 ? item.Records.Y3 : 0
}).ToList();
Instead of 0, add your default value or null.
Update:
According to your comments, the only option for you is to go dynamic. Here's example with dynamics:
var numberOfYears = 3;
var list = users.Select(x =>
{
dynamic item = new ExpandoObject();
item.Id = x.Id;
item.Name = x.Name;
item.Status = x.Status;
var p = item as IDictionary<string, object>;
var recordsType = x.Records.GetType();
for (var i = 1; i <= numberOfYears; ++i)
p["Y" + i] = recordsType.GetProperty("Y" + i).GetValue(x.Records);
return item;
}).ToList();
You can use the ExpandoObject like this:
var data = providers.Select(provider =>
{
dynamic excelRow = new ExpandoObject();
excelRow.FirstName = provider.FirstName ?? "";
excelRow.MiddleName = provider.MiddleName ?? "";
excelRow.LastName = provider.LastName ?? "";
// Conditionally add columns to the object...
if (someCondition)
{
excelRow.Property1ForCondition = provider.Property1ForCondition;
excelRow.Property2ForCondition = provider.Property2ForCondition;
}
excelRow.DueDate = provider.DueDate ?? null;
.
.
.
return excelRow;
});
Another variation of the above code can be:
var data = new List<ExpandoObject>();
providers.ForEach(provider =>
{
dynamic excelRow = new ExpandoObject();
excelRow.FirstName = provider.FirstName ?? "";
excelRow.MiddleName = provider.MiddleName ?? "";
excelRow.LastName = provider.LastName ?? "";
// Conditionally add columns to the object...
if (someCondition)
{
excelRow.Property1ForCondition = provider.Property1ForCondition;
excelRow.Property2ForCondition = provider.Property2ForCondition;
}
excelRow.DueDate = provider.DueDate ?? null;
.
.
.
data.Add(excelRow);
});

Linq with Left Join and multiples Key not Work

I need help please!
When I perform the following LINQ query, it works perfectly (shows results)
using (var db = new MyEntities())
{
var result = (from dc in db.ClassDiary
where dc.DesTurm == dataForm.DesTurma
&& dc.Module == dataForm.Module
&& dc.CodDisc == dataForm.CdDisc
orderby dc.NrDiary
select new ClassDiaryMod
{
Id = dc.ID,
NrDiary = dc.NrDiary,
NrStudant = dc.NrStudant,
DesTurma = dc.DesTurma,
CdDisc = dc.CodDisc,
CdTeac = dc.CodTeac,
TotalFoult = (from f in db.Foult
where
f.NrStudant == dc.NrStudant &&
f.Disc == dc.CodDisc
select new FoultMod
{
Foults = f.Foult
}).Sum(x => x.Foults)
}).ToList();
return result;
When I try to apply the left join with multiple key does not display results
using (var db = new FamespEntities())
{
var result = (from dc in db.ClassDiary
join fn in db.Foult
on new { dc.NrStudant, dc.CodDisc, dc.DesTurm }
equals new { fn.NrStudant, CodDisc = fn.Disc, DesTurm = fn.Desturm } into fn_join
from fn in fn_join.DefaultIfEmpty()
where dc.DesTurm == dataForm.DesTurm
&& dc.Module == dataForm.Module
&& dc.CodDisc == dataForm.CdDisc
orderby dc.NroDiary
select new ClassDiaryMod
{
Id = dc.Id,
NrDiary = dc.NroDiary,
NrStudant = dc.NrStudant,
DesTurm = dc.DesTurm,
CdDisc = dc.CodDisc,
CdTeac = dc.CodTeac,
FoultOfDay = fn.Foult,
TotalFoults = (from f in db.Foult
where
f.NrStudent == dc.NrStudant &&
f.Disc == dc.CodDisc
select new FoultMod
{
Foults = f.Foult
}).Sum(x => x.Foults)
}).ToList();
Like to understand why the first code works and the second does not.
Thank you so much
Your equals
on new { dc.NrStudant, dc.CodDisc, dc.DesTurm }
equals new { fn.NrStudant, CodDisc = fn.Disc, DesTurm = fn.Desturm }
Is not correct, it should be
on new { NrStudant = dc.NrStudant, CodDisc = dc.CodDisc, DesTurm = dc.DesTurm }
equals new { NrStudant = fn.NrStudant, CodDisc = fn.Disc, DesTurm = fn.Desturm }
so field comparison could work.

Most efficient way of loading data into LINQ object for search result type method

I currently have the following:
public IEnumerable<News> NewsItems
{
get { return from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select s; }
}
The problem is I only need to return the one property that actually has the data as well as the Title property, something similar to.
return from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select new {Title = s.Title, Data = //Description or Summary containing the data
How do I determine which one contains the search query?
UPDATE: I have this but it obviously hits the DB 3 times
var FoundInSummary = News.All().Any(x => x.Summary.Contains(SearchCriteria));
var FoundInDesc = News.All().Any(x => x.Description.Contains(SearchCriteria));
IEnumerable<NewsEventSearchResults> result = null;
if ((FoundInSummary && FoundInDesc) || (FoundInSummary))
{
result = (from s in News.All() where s.Summary.Contains(SearchCriteria) select new NewsEventSearchResults { Title = s.Title, Data = s.Summary, ID = s.ID }).AsEnumerable();
}
else if (FoundInDesc)
{
result = (from s in News.All() where s.Description.Contains(SearchCriteria) select new NewsEventSearchResults { Title = s.Title, Data = s.Description, ID = s.ID }).AsEnumerable();
}
return result;
UPDATE 2: Is this more efficent?
var ss = (from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select s).ToList();
List<NewsEventSearchResults> resultList = new List<NewsEventSearchResults>();
foreach (var item in ss)
{
bool FoundInSummary = item.Summary.Contains(SearchCriteria);
bool FoundInDesc = item.Description.Contains(SearchCriteria);
if ((FoundInSummary && FoundInDesc) || (FoundInSummary))
{
resultList.Add(new NewsEventSearchResults { Title = item.Title, Data = item.Summary, ID = item.ID });
}
else if (FoundInDesc)
{
resultList.Add(new NewsEventSearchResults { Title = item.Title, Data = item.Description, ID = item.ID });
}
}
What if they both contain the criteria? Or are they mutually exclusive? If so
Data = (s.Description != null ? s.Description : s.Summary)
I went with option 3

Categories