Db.Deliveries.Where(d => d.CrewId != null).GroupBy(d => new {d.Crew, d.Date}).OrderBy(d => d.Key).ToList()
How to pass the result of this code to View? Code is valid. What type must have View?
var Deliveries = Db.Deliveries.Where(d => d.CrewId != null).GroupBy(d => new {d.Crew, d.Date}).OrderBy(d => d.Key).ToList(); //It`s Ok.
List<IGrouping<{Crew:Crew, Date:DateTime}, Delivery>> Deliveries = Db.Deliveries.Where(d => d.CrewId != null).GroupBy(d => new {d.Crew, d.Date}).OrderBy(d => d.Key).ToList(); //It`s wrong.
List<IGrouping<{Crew, DateTime}, Delivery>> //This type is wrong too.
Or is exists any solution of this problem, without using anonymious types?
Sorry for my bad English, Thanks for any help!
Because you use an anonymous type in your GroupBy the result the type exists only virtually.
Either use
#model dynamic
or define a type for your result
public class GroupedDelivery{
public Crew Crew {get;set;}
public DateTime Date {get;set;}
public List<Delivery> Deliveries {get;set;}
}
Map the type in a Select after the GroupBy.
List<GroupedDelivery> Deliveries = Db.Deliveries.Where(d => d.CrewId != null)
.GroupBy(d => new {d.Crew, d.Date})
.Select(p => new GroupedDelivery{
Crew = p.Key.Crew,
Date = p.Key.Date,
Deliveries = p.Select(x => x).ToList()
})
.OrderBy(d => d.Crew).ThenBy(p => p.Date).ToList();
Related
public IEnumerable<Temp_Order> Get_Temp(string id)
{
//List<Temp_Order> data = new List<Temp_Order>();
IEnumerable<Temp_Order> data = db.Temp_Order
.Join(db.Items,
t_id => t_id.ItemId,
I_id => I_id.ItemId,
(t_id, I_id) => new { t_id.Quantity, I_id.ItemName })
.Where(x => x.ItemName == id);
return data;
}
In this method I want IEnumerable<Temp_Order>. So I will use this in controller and return to the view.
I'm getting this error:
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?) E:\WORK\Projects\RMS_Live\RMS_Live\Models\Order.cs
The Join is converting your query to an IEnumerable of an anonymous type. Add a Select on the end to cast is back to Temp_Order:
public IEnumerable<Temp_Order> Get_Temp(string id)
{
//List<Temp_Order> data = new List<Temp_Order>();
IEnumerable<Temp_Order> data = db.Temp_Order
.Join(db.Items, t_id => t_id.ItemId, I_id => I_id.ItemId, (t_id, I_id) => new { t_id.Quantity, I_id.ItemName })
.Where(x => x.ItemName == id)
.Select(a => new Temp_Order
{
ItemName = a.ItemName,
Property2 = a.Property2,
//snip
});
return data;
}
EDIT:
You indicate in the comments that you want all properties from both Temp_Order and Item which means you need another class. You can get away without creating another class, but it's much simpler in the long run. So first make your class, 2 ways spring to mind, you either replicate all the properties you need or just return the 2 objects, I'll use the latter:
public class OrderItem
{
public Temp_Order Temp_Order { get; set; }
public Item Item { get; set; }
}
Now your function becomes this:
public IEnumerable<OrderItem> Get_Temp(string id)
{
IEnumerable<OrderItem> data = db.Temp_Order
.Join(db.Items,
t_id => t_id.ItemId,
I_id => I_id.ItemId,
(t_id, I_id) => new OrderItem
{
Temp_Order = t_id,
Item = I_id
})
.Where(x => x.ItemName == id);
return data;
}
And in your view, make sure you set the model type to IEnumerable<OrderItem> and you can access all the properties like this:
#Model.Temp_Order.ItemName
I have the following repository method:-
public AccountDefinition GetCustomer2(int id)
{ var c = entities.AccountDefinitions.Where(p => p.ORG_ID == id)
.Include(a => a.SDOrganization)
.Include(a2 => a2.SiteDefinitions)
.Include(a3 => a3.SDOrganization.AaaPostalAddresses)
.Include(a4 => a4.SiteDefinitions.Select(a5 => a5.DepartmentDefinitions.Select(a6 => a6.SDUsers.Select(a7 => a7.AaaUser.AaaContactInfoes)))).SingleOrDefault();
return c; }
But when I comment some code I found that the generated SQL statement when calling the Action method will be the same:-
public AccountDefinition GetCustomer2(int id)
{ var c = entities.AccountDefinitions.Where(p => p.ORG_ID == id)
// .Include(a => a.SDOrganization)
// .Include(a2 => a2.SiteDefinitions)
.Include(a3 => a3.SDOrganization.AaaPostalAddresses)
.Include(a4 => a4.SiteDefinitions.Select(a5 => a5.DepartmentDefinitions.Select(a6 => a6.SDUsers.Select(a7 => a7.AaaUser.AaaContactInfoes)))).SingleOrDefault();
return c; }
So does this mean when I navigate to a nested Navigation property , then EF will automatically retrieve parent navigation properties also? . so for example when i write .Include(a3 => a3.SDOrganization.AaaPostalAddresses) , then there is no need to write .Include(a => a.SDOrganization)
In a nutshell yes, it has to otherwise there is no way for you to traverse to that navigation property
EG, the only way to access AccountDefinition.SDOrganization.AaaPostalAddresses is if SDOrganization is not null.
Having said that my personal preference is to make this intermediate inclusion explicit by listing it anyway. While this has no functional benefit its a reminder that this property will also be returned
I have the following in an MVC4 app. I want to filter the load by both keys, there could be many to many but both the keys together represent a unique row. The goal to to explicitly load these collections only when needed and filter by both sides of the relationship.
I have the following Entity.DBContext, it works but only for the UserId key.
context.UserProfiles.Include(o => o.CoachOfOrginizations).Where(p => p.UserId == UserId).Single()
Also this loads all of them, but of course doesnt filter at all, just showing you so you know that I set up my fluent code properly.
context.Entry(this).Collection(t => t.AdministratorOfOrginizations).Load();
modelBuilder.Entity<UserProfile>()
.HasMany(p => p.CoachOfOrginizations)
.WithMany(t => t.Coaches)
.Map(mc =>
{
mc.ToTable("OrganizationCoaches");
mc.MapLeftKey("UserProfileID");
mc.MapRightKey("OrganizationID");
});
CoachOfOrginizations is the following property on UserProfile.
public ICollection<Organization> CoachOfOrginizations { get; set; }
What i would like is to filter my original .Include above based on Organization.ID (the other key) and the currently used key p.UserId. I've tried the following and it doesn't work, any advice? "this" is the UserProfile object.
context.Entry(this)
.Collection(b => b.CoachOfOrginizations)
.Query()
.Where(p => p.ID == orgID)
.Load();
You can do both filtering in a single query. See conditional includes.
var query = context.UserProfiles
.Where(p => p.UserId == UserId)
.Select(p => new { p, Orgs = p.CoachOfOrginizations.Where(o => o.ID == orgID) });
var profiles = query.AsEnumerable().Select(a => a.p);
I want to be able to select multiple columns and loop through the retrieved rows and store the selected fields in a string.
Something like select a.firstname, a.lastname from customer where a.id = '123' and loop through the retireved rows and have them write to a string like
FirstName = John; LastName = Doe
FirstName = Steve; LastName = Smith
I have linq statement as
IList<string> strgradeandbatch = new List<string>();
strgradeandbatch = context.GradeAndBatches
.Where(T => T.RequestGuid == request.ItemGuid)
.Select(T => new{T.GradeName, T.Batch}).ToList();
Obviously this is wrong, and not sure how to do it.Thanks for your help in advance
I think you are almost correct. Just remove IList<string> strgradeandbatch = new List<string>() and use anonymous type var strgradeandbatch.
string GradeName, Batch;
var strgradeandbatch = context.GradeAndBatches
.Where(T => T.RequestGuid == request.ItemGuid)
.Select(T => new{T.GradeName, T.Batch}).ToList();
foreach(var item in strgradeandbatch)
{
GradeName = item.GradeName;
Batch = item.Batch;
}
(Note:If you use anonymous type, you can't return this value from the method)
The Select method projects the query results into a list of an anonymous type objects, so it can be used with a list for strings.
One solution is to create a new class
public class Grade
{
public string GradeName {get; set;}
public string Batch {get; set;}
}
Which is going to be used with the Select method
var strgradeandbatch = context.GradeAndBatches
.Where(T => T.RequestGuid == request.ItemGuid)
.Select(T => new Grade
{
GradeName = T.GradeName,
Batch = T.Batch
}).ToList();
Hi I i try to use a ToExpando solution to use anonymous classes in razor views.
I use this solution -> Dynamic Anonymous type in Razor causes RuntimeBinderException
I'll write what i did:
I added a file Extensions.cs where i put following code:
public static class Extensions
{
public static ExpandoObject ToExpando(this object anonymousObject)
{
IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
IDictionary<string, object> expando = new ExpandoObject();
foreach (var item in anonymousDictionary)
expando.Add(item);
return (ExpandoObject)expando;
}
}
I wrote a query that receive a tuples from database in controller method:
IEnumerable<dynamic> articles = (from p in db.Articles.Where(p => p.user_id == 2)
select new
{
p.article_id,
p.title,
p.date,
p.category,
AverageScore = db.Articles_Scores
.Where(o => o.user_id == p.user_id && p.article_id == o.article_id)
.Average(m => m.score)
}).AsEnumerable()
.Select(r => r.ToExpando());
int ii = 0;
foreach(var it in articles) {
// HERE I CAN READ EVERYTHING
ii = it.article_id;
}
return View(articles);
In view I declare a model:
#model IEnumerable<dynamic>
And I try to get every tuples:
#foreach (dynamic item in Model) {
// some code
#item.article_id // HERE IS EXCEPTION
}
In the foreach line I got an Exception:
RuntimeBinderException: 'System.Dynamic.ExpandoObject' does not contain a definition for 'article_id'
What did I do wrong?
You need to call .AsEnumerable() or .ToList() first to force ToExpando to run on the client.
Try:
dynamic articles = (from p in db.Articles.Where(p => p.user_id == 2_
select new
{
p.article_id,
p.title,
p.date,
p.category,
AverageScore = db.Articles_Scores
.Where(o => o.user_id == p.user_id && p.article_id == o.article_id)
.Average(m => m.score)
}).AsEnumerable()
.Select(r => r.ToExpando());
Edit: Make sure you declare dynamic not var
Edit 2: In your for look, you're declaring var again. Change it to:
#foreach (dynamic item in Model) {
// some code
#item.article_id // HERE IS EXCEPTION
}
Ok, building on the first two answers, I added another extension method that I'm surprised I don't see here:
public static List<ExpandoObject> ToExpandoList<T>(this IEnumerable<T> ie) {
return ie.Select(o => o.ToExpando()).ToList();
}
And now in my view I have code like this, and it works just fine using Razor.
var peoples = from f in "tom dick susan roberto".Split(' ')
select new { FirstName = f, Age = f.Length };
ViewBag.People = peoples.ToExpandoList();
The problem is HtmlHelper.AnonymousObjectToHtmlAttributes(), it's replacing
'_' with '-' for the property name. Look at the comment for the method.