Model class:
public class MonthlySalesOrders : BaseNopEntityModel
{
public ICollection<Nop.Core.Domain.Orders.OrderItem> Categories { get; set; }
}
Controller Action
private PagedList.IPagedList<MonthlySalesOrders> orderByDateAdded()
{
var ord = _orderService.SearchOrders();
var daylyOrderReport = (from o in ord.AsEnumerable()
group o by new { Quarter = ((o.CreatedOnUtc.CompareTo(DateTime.UtcNow.AddDays(-7)))) } into orGrp
select new MonthlySalesOrders
{ Categories = (ICollection<Nop.Core.Domain.Orders.OrderItem>)orGrp.Select(c => c.OrderItems)
})
return daylyOrderReport.ToPagedList(1, 10);
}
From above "controller action" I have used linq query to select orderlist from "orGrp group", and into "Model class" I have declared a public ICollection<Nop.Core.Domain.Orders.OrderItem> Categories { get; set; }, so when I build and ran the above code it displays following error messages.
Unable to cast object of type 'WhereSelectEnumerableIterator2[Nop.Core.Domain.Orders.Order,System.Collections.Generic.ICollection1[Nop.Core.Domain.Orders.OrderItem]]' to type 'System.Collections.Generic.ICollection`1[Nop.Core.Domain.Orders.OrderItem]'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidCastException: Unable to cast object of type 'WhereSelectEnumerableIterator2[Nop.Core.Domain.Orders.Order,System.Collections.Generic.ICollection1[Nop.Core.Domain.Orders.OrderItem]]' to type 'System.Collections.Generic.ICollection`1[Nop.Core.Domain.Orders.OrderItem]'.
Source Error:
Line 2374: var daylyOrderReport = (from o in ord.AsEnumerable()
Line 2375: group o by new { Quarter = ((o.CreatedOnUtc.CompareTo(DateTime.UtcNow.AddDays(-7)))) } into orGrp
Line 2376: select new MonthlySalesOrders
Line 2377: {
Line 2378: Year = orGrp.First().CreatedOnUtc.Year.ToString(),
and I want get category list from three level nested reference from orGrp like Categories =(ICollection<Nop.Core.Domain.Orders.OrderItem>) orGrp.Select(gb => gb.OrderItems.Select(s => s.Product.ProductManufacturers))
so please help me how can I do this.
You can use the ToList function which returns an IList which implements ICollection. Also, it looks like c.OrderItems is an enumerable of items, not a single item. If this is the case then you'll want to flatten list returned with SelectMany.
orGrp.SelectMany(c => c.OrderItems).ToList()
Related
I typically do mobile app development, which doesn't always have .Select. However, I've seen this used a bit, but I don't really know what it does or how it's doing whatever it does. It is anything like
from a in list select a // a.Property // new Thing { a.Property}
I'm asking because when I've seen code using .Select(), I was a bit confused by what it was doing.
.Select() is from method syntax for LINQ, select in your code from a in list select a is for query syntax. Both are same, query syntax compiles into method syntax.
You may see: Query Syntax and Method Syntax in LINQ (C#)
Projection:
Projection Operations - MSDN
Projection refers to the operation of transforming an object into a
new form that often consists only of those properties that will be
subsequently used. By using projection, you can construct a new type
that is built from each object. You can project a property and perform
a mathematical function on it. You can also project the original
object without changing it.
You may also see:
LINQ Projection
The process of transforming the results of a query is called
projection. You can project the results of a query after any filters
have been applied to change the type of the collection that is
returned.
Example from MSDN
List<string> words = new List<string>() { "an", "apple", "a", "day" };
var query = from word in words
select word.Substring(0, 1);
In the above example only first character from each string instance is selected / projected.
You can also select some fields from your collection and create an anonymous type or an instance of existing class, that process is called projection.
from a in list select new { ID = a.Id}
In the above code field Id is projected into an anonymous type ignoring other fields. Consider that your list has an object of type MyClass defined like:
class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
Now you can project the Id and Name to an anonymous type like:
Query Syntax:
var result = from a in list
select new
{
ID = a.Id,
Name = a.Name,
};
Method Syntax
var result = list.Select(r => new { ID = r.Id, Name = r.Name });
You can also project result to a new class. Consider you have a class like:
class TemporaryHolderClass
{
public int Id { get; set; }
public string Name { get; set; }
}
Then you can do:
Query Syntax:
var result = from a in list
select new TemporaryHolderClass
{
Id = a.Id,
Name = a.Name,
};
Method Syntax:
var result = list.Select(r => new TemporaryHolderClass
{
Id = r.Id,
Name = r.Name
});
You can also project to the same class, provided you are not trying to project to classes generated/created for LINQ to SQL or Entity Framework.
My summary is it takes results (or a subset of results) and allows you to quickly restructure it for use in the local context.
The select clause produces the results of the query and specifies the
"shape" or type of each returned element. For example, you can specify
whether your results will consist of complete Customer objects, just
one member, a subset of members, or some completely different result
type based on a computation or new object creation.
Source: http://msdn.microsoft.com/en-us/library/bb397927.aspx
There are a lot of possible uses for this but one is taking a complex object which of many other contains a property that is a string -- say Name -- and allows you to return an enumeration with just the entries of Name. I believe you can also do the opposite -- use that property ( for example) and create / return new type of object while passing in a property or properties.
It means "mapping". Map each element of a sequence to a transformed sequence. I hadn't comprehended its meaning before I looked at the image.
Where does the meaning of the word come from?
Simply, math! https://mathworld.wolfram.com/Projection.html
I just cannot understand why it works. I had this error
'object' does not contain a definition for 'type'
And it was because I was returning an anonymous type:
Connection db = new Connection();
public ActionResult Index()
{
ViewBag.query = from input in db.field
where input.ID_FIELD == 1
select new
{
type = input.FIELD_TYPE
};
return View();
}
#foreach (var item in ViewBag.query)
{
#item.type // Error here: 'object' does not contain a definition for 'type',
}
So I added a class to get the types
public class Types
{
public string type {get; set;}
// And bla blab bla
}
Good, no problem. But now I need a group by clouse, but I don’t know how to do it.
For example, see the example 2 of this link. As you can see, everything works great, but here he didn’t have to specify the type, and it worked OK.
The following is my example. How can I use Group By with LINQ?
group x by x.PropertyName into g will result in g being a collection of x objects with a property Key that will return the x.PropertyName value that was used to group the x objects
ViewBag.query = from input in db.field
where input.ID_FIELD == 1
group input by input.FIELD_TYPE into g
select new {
FieldType = g.Key,
Fields = g
};
I'm getting a strange error when running what appears to be a simple query.
return (from x in session.Query<Contact>()
.Where(x => x.Id == 10)
select new ContactIndexViewModel
{
Id = x.Id,
Name = x.BasicInfo.FirstName + " " + x.BasicInfo.LastName,
Filters = x.Filters
}).FirstOrDefault();
Is generating the following SQL
select
contact0_.[Id] as col_0_0_,
contact0_.[BasicInfoFirstName] as col_1_0_,
contact0_.[BasicInfoLastName] as col_2_0_,
. as col_3_0_,
filters1_.[Id] as column1_16_,
filters1_.Criteria1 as Criteria2_16_,
// .. .more filters1_ fields
filters1_.ContactId as ContactId16_
from
[MyServer].[dbo].[Contact] contact0_
inner join [MyServer].[dbo].[Filter] filters1_
on contact0_.[Id]=filters1_.ContactId
where
contact0_.[Id]=#p0
Notice the fourth column being selected. BasicInfo is a component and the select (in the query) includes all the fields defined in the ViewModel.
I am not having any other problems with the Contact or Filter objects in other parts of the application. Contact -> Filter has a one to many relationship.
Any idea's on how to debug or what may cause this?
UPDATE
If I remove the reference to Filters in the select, the problem goes away.
UPDATE Relevant Mappings
Contact
public partial class ContactMap : ClassMap<Contact>
{
/// <summary>Initializes a new instance of the <see cref="ContactMap"/> class.</summary>
public ContactMap()
{
Table("[MyServer].[dbo].[Contact]");
OptimisticLock.Version();
DynamicUpdate();
LazyLoad();
Id(x=>x.Id)
.Access.CamelCaseField(Prefix.Underscore)
.Column("[Id]")
.GeneratedBy.Identity();
Version(x=>x.RecordVersion)
.Access.CamelCaseField(Prefix.Underscore)
.Column("[RecordVersion]")
.CustomSqlType("timestamp")
.Not.Nullable()
.UnsavedValue("null")
.CustomType("BinaryBlob")
.Generated.Always();
Map(x=>x.Active).Access.CamelCaseField(Prefix.Underscore);
// other scalar properties
Component(x0=>x0.BasicInfo, m0=>
{
m0.Map(x1=>x1.FirstName).Column("[BasicInfoFirstName]").Access.CamelCaseField(Prefix.Underscore);
m0.Map(x1=>x1.LastName).Column("[BasicInfoLastName]").Access.CamelCaseField(Prefix.Underscore);
// other scalar properties
});
// other relationships
HasMany(x=>x.Searches)
.Access.CamelCaseField(Prefix.Underscore)
.Cascade.AllDeleteOrphan()
.Fetch.Select()
.Inverse()
.LazyLoad()
.KeyColumns.Add("ContactId");
}
}
Search
public partial class SearchMap : ClassMap<Search>
{
public SearchMap()
{
Table("[MyServer].[dbo].[Search]");
OptimisticLock.Version();
DynamicUpdate();
LazyLoad();
Id(x=>x.Id)
.Access.CamelCaseField(Prefix.Underscore)
.Column("[Id]")
.GeneratedBy.Identity();
Map(x=>x.Controller).Not.Nullable().Access.CamelCaseField(Prefix.Underscore);
Map(x=>x.Module).Not.Nullable().Access.CamelCaseField(Prefix.Underscore);
Map(x=>x.Name).Column("[Name]").Not.Nullable().Access.CamelCaseField(Prefix.Underscore);
References(x=>x.Contact)
.Access.CamelCaseField(Prefix.Underscore)
.Cascade.All()
.Fetch.Select()
.Columns("ContactId");
HasMany(x=>x.DataFilters)
.Access.CamelCaseField(Prefix.Underscore)
.Cascade.AllDeleteOrphan()
.Fetch.Select()
.Inverse()
.LazyLoad()
.KeyColumns.Add("SearchId");
}
}
Did you map Filters with FetchMode.Join?
By the way, it may be easier to create the ContactIndexViewModel in memory, with the trade off that it fetches too many columns from the database. On the other side, Get doesn't flush the session, which may be performance relevant.
var contact = session.Get<Contact>(10);
return new ContactIndexViewModel
{
Id = contact.Id,
Name = contact.BasicInfo.FirstName + " " + contact.BasicInfo.LastName,
Filters = contact.Filters
};
Your mapping for the table is unusual to me.
Table("[MyServer].[dbo].[Contact]");
Normally the server name is provided during configuration, the schema is stated separately, and the delimiters ("[...]") are set by NHibernate. I would map it as:
Schema("dbo");
Table("Contact");
That may be causing a parsing problem leading to the odd select. If that's not it, then I think it's a bug -- NHibernate should never issue a select without a table alias and column name.
This has been ruining my life for a few days now, time to ask...
I am using Entity Framework 4.0 for my app.
A Location (such as a house or office) has one or more facilities (like a bathroom, bedroom, snooker table etc..)
I want to display a checkbox list on the location page, with a checkbox list of facilities, with the ones checked that the location currently has.
My View Model for the facilities goes like this...
public class FacilityViewItem
{
public int Id { get; set; }
public string Name { get; set; }
public bool Checked { get; set; }
}
So when im passing the Location View Model to the UI, i want to pass a List<T> of facilities where T is of type FacilityViewItem.
To get the facilities that the location already has is simple - i make a query using Location.Facilities which returns an EntityCollection where T is of type Facility. This is because Facilities is a navigation property....
var facs = from f in location.Facilities
select new FacilityViewItem()
{
Id = f.FacilityId,
Name = f.Name,
Checked = true
};
So here is where my problem lies - i want the rest of the facilities, the ones that the Location does not have.
I have tried using Except() and Any() and Contains() but i get the same error.
Examples of queries that do not work...
var restOfFacilities = from f in ctx.Facilities
where !hasFacilities.Contains(f)
select new FacilityViewItem()
{
Id = f.FacilityId,
Name = f.Name
};
var restOfFacilities = ctx.Facilities.Except(facilitiesThatLocationHas);
var notFacs = from e in ctx.Facilities
where !hasFacilities.Any(m => m.FacilityId == e.FacilityId)
select new FacilityViewItem()
{
Id = e.FacilityId,
Name = e.Name
};
And the error i get with every implementation...
System.NotSupportedException was unhandled
Message=Unable to create a constant value of type 'Chapter2ConsoleApp.Facility'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
What am i overlooking here?
ironically enough i solved it in a matter of hours after i posted the question on here, after days of suffering.
The error is basically saying 'i dont know how to calculate what items are not included by comparing strongly typed objects. Give me a list of Ints or some simple types, and i can take care of it'.
So, first you need to get a list of the primary keys, then use that in the contains clause...
//get the primary key ids...
var hasFacilityIds = from f in hasFacilities
select f.FacilityId;
//now use them in the contains clause...
var restOfFacilities = from f in ctx.Facilities
where !hasFacilityIds.Contains(f.FacilityId)
select new FacilityViewItem()
{
Id = f.FacilityId,
Name = f.Name
};
The first query seems fine, but you need to compare the Ids:
var restOfFacilities = from f in ctx.Facilities
where !facs.Select(fac => fac.Id).Contains(f.Id)
select f;
I wanna see what's hasFacilities, anyway, as L2E shows, "Only primitive types ('such as Int32, String, and Guid') are supported in this context", so I suppose you must retrieve first the data and put into a collection of FacilityViewItem.
var restOfFacilities = ctx
.Facilities
.Where(f => !hasFacilities.Contains(f))
.Select(f => new { f.FacilityId, f.Name })
.ToList()
.Select(f => new FacilityViewItem {
Id = f.FacilityId,
Name = f.Name
});
var notFacs = ctx
.Facilities
.Where(e => !hasFacilities.Any(m => m.FacilityId == e.FacilityId))
.Select(e => new { e.FacilityId, e.Name })
.ToList()
.Select(e => new FacilityViewItem {
Id = e.FacilityId,
Name = e.Name
});
hope it helps
Here's the situation:
I'm attempting to get a collection of all types in my assembly that implement a specific generic interface along with the generic type parameters used. I have managed to put together a Linq query to perform this but it seems awfully redunant.
I've read up on let and joins but couldn't see how to I'd use them to reduce the verbosity of this particular query. Can anyone provide any tips on how to shorten/enhance the query please?
Here's an MSTest class that currently passes and demonstrates what I'm trying to achieve:
[TestClass]
public class Sample
{
[TestMethod]
public void MyTest()
{
var results =
(from type in Assembly.GetExecutingAssembly().GetTypes()
where type.GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(MyInterface<,>)
)
select new ResultObj(type,
type.GetInterfaces().First(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(MyInterface<,>)
).GetGenericArguments()[0],
type.GetInterfaces().First(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(MyInterface<,>)
).GetGenericArguments()[1]
)).ToList();
Assert.AreEqual(1, results.Count);
Assert.AreEqual(typeof(int), results[0].ArgA);
Assert.AreEqual(typeof(string), results[0].ArgB);
}
interface MyInterface<Ta, Tb>
{ }
class MyClassA : MyInterface<int, string>
{ }
class ResultObj
{
public Type Type { get; set; }
public Type ArgA { get; set; }
public Type ArgB { get; set; }
public ResultObj(Type type, Type argA, Type argB)
{
Type = type;
ArgA = argA;
ArgB = argB;
}
}
}
Regards,
Matt
Here is an example that shows how to rewrite this using the let keyword:
var results =
(from type in Assembly.GetExecutingAssembly().GetTypes()
// Try to find first such interface and assign the result to 'ifc'
// Note: we use 'FirstOrDefault', so if it is not found, 'ifc' will be null
let ifc = type.GetInterfaces().FirstOrDefault(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(MyInterface<,>))
// Filtering and projection can now use 'ifc' that we already have
where ifc != null
// Similarly to avoid multiple calls to 'GetGenericArguments'
let args = ifc.GetGenericArguments()
select new ResultObj(type, args[0], args[1])).ToList();
The let keyword works a bit like variable declaration, but lives within LINQ queries - it allows you to create a variable that stores some result that is needed in multiple places later in the query. You mention "joins" as well, but that's mostly used for database-like joins (and I'm not sure how it would apply here).