How can I load collection with include, I have tried these:
Type.Where(t => t.Entity.Where(e => e.Parent == false).Count() > 0).Include(e => e.Entity)
But the filter is not supported here (Entities recovered not fulfill a condition).
With LinQ To Entities :
var v = from type in ObjectContext.Type
from entity in Type.Entities
where entity.Parent == false
select type;
But type do not contains it's associated Entities.
I can't write select new Type { type.Code, type.Entities } and I can't use anonymous type as it's not adapted for my repository layer.
Have you any ideas on how I can get a list of Type objects with its property Entities satisfying a condition?
Update
Thank you for your response
I think it's not a good idea to use the CTP , no ?
I am sorry, I did not explain my object model, I have :
class Type {
public string Code { get; set; }
public IList<Entity> Entities { get; set; }
...
}
class Entity {
public string Code { get; set; }
...
}
And I want to use your second filtering proposal : Filter both entity sets
Do you have any suggestions without using the CTP ?
Thanks
Rad
as you stated you want to apply filters to the related entities, best to look at the new CTP5 of the EF4 http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx
Look under "Applying filters when explicitly loading related entities"
Related
I tried to get all persons who have dogs older than 10 using the following line of code :
var persons = realm.All<Person>()
.Where(person => person.Dogs.Count(dog=>dog.Age > 10) > 0);
But I got this error:
System.NotSupportedException:
The lhs of the binary operator 'GreaterThan' should be a member expression.
Unable to process `person.Dogs.Count(dog => (dog.Age > 10))`
Does it mean that we are not able to filter on relations in Realm ?
Here are the models that I copied from Realm documentation:
public class Dog : RealmObject
{
public string Name { get; set; }
public int Age { get; set; }
public Person Owner { get; set; }
}
public class Person : RealmObject
{
public string Name { get; set; }
public IList<Dog> Dogs { get; }
}
Yeah sorry, this type of query is not yet supported. We are working on improving LINQ coverage, but I'm afraid you won't be able to perform this particular query in the near future.
Two workarounds that may or may not be applicable in your situation:
1) Add a boolean HasOldDogs property on your Person class. Note that in order to perform queries on it, it would have to be a persisted property so you would have to update it explicitly whenever you modify the Dogs property or any of the contained Dog instances.
2) Perform the query in memory. var persons = realm.All<Person>().ToList().Where( ... ) will work. However, this will perform the query with LINQ to Objects in memory which works best if you don't have a massive number of Person instances.
If you can describe in more detail what your situation requires, we might be able to think up alternatives.
may be you have to break your query to two queries instead of one.
Seems there are some issues with Realm that might require someone from Realm team to explain :)
The answer to this question gave rise to this other question: How to use LINQ expressions as static members of classes in queries when the class is related multiple times to a second class
I have an existing ASP.net MVC 4 site which I need to modify.
The core entity within this site are Items that are for sale, which are created by several different companies and divided into several categories. My task is to allow each company its own optional alias for the global categories. Getting the two categories set up in the database and model was no problem, making the application use the new optional alias when it exists and default to the global otherwise is where I'm struggling to find the optimal approach.
Adding a coalesce statement to every LINQ query will clearly work, but there are several dozen locations where this logic would need to exist and it would be preferable to keep this logic in one place for when the inevitable changes come.
The following code is my attempt to store the coalesce in the model, but this causes the "Only initializers, entity members, and entity navigation properties are supported." error to be thrown when the LINQ query is executed. I'm unsure how I could achieve something similar with a different method that is more LINQ friendly.
Model:
public class Item
{
[StringLength(10)]
[Key]
public String ItemId { get; set; }
public String CompanyId { get; set; }
public Int32 CategoryId { get; set; }
[ForeignKey("CategoryId")]
public virtual GlobalCategory GlobalCategory { get; set; }
[ForeignKey("CompanyId, CategoryId")]
public virtual CompanyCategory CompanyCategory { get; set; }
public String PreferredCategoryName
{
get{
return (CompanyCategory.CategoryAlias == null || CompanyCategory.CategoryAlias == "") ? GlobalCategory.CategoryName : CompanyCategory.CategoryAlias;
}
}
}
Controller LINQ examples:
var categories = (from i in db.Items
where i.CompanyId == siteCompanyId
orderby i.PreferredCategoryName
select i.PreferredCategoryName).Distinct();
var itemsInCategory = (from i in db.Items
where i.CompanyId == siteCompanyId
&& i.PreferredCategoryName == categoryName
select i);
For one you are using a compiled function (getPreferredCategoryName) in the query, unless EF knows how to translate that you are in trouble.
Try the following in item definition:
public static Expression<Func<Item,String>> PreferredCategoryName
{
get
{
return i => (i.CompanyCategory.CategoryAlias == null || i.CompanyCategory.CategoryAlias == "") ?
i.GlobalCategory.CategoryName :
i.CompanyCategory.CategoryAlias;
}
}
Which is used as follows:
var categories = db.Items.Where(i => i.CompanyID == siteCompanyId)
.OrderBy(Item.PreferredCategoryName)
.Select(Item.PreferredCategoryName)
.Distinct();
This should work as you have a generically available uncompiled expression tree that EF can then parse.
I have this structure:
class Foo {
IList<FooAttribute> Attributes { get; set; }
}
class FooAttribute {
bool IsSelected { get; set; }
string Value { get; set; }
}
And I have objects like:
IQuerable<Foo> foos; // Database repository object .AsQuerable()
IList<FooAttribute> attrs;
I need to filter only those items of foos that have all attributes of attrs list.
I tried this:
foos = foos.Where(foo =>
attrs.All(a =>
foo.Attributes.Any(at => at.Value == a)));
var filteredFoos = foos.ToList();
and i think it would work, but would be super slow and... it throws NotSupportedException...
By the way... I use ASP.NET MVC 3 and C# 4.0, so even the newest solutions are very welcome.
Thanks in advance.
FooAttribute fooAttributeAlias=null;
Session.QueryOver<Foo>().Inner.JoinAlias(x=>x.Attributes,()=>fooAttributeAlias)
.WhereRestrictionOn(()=>fooAttributeAlias).IsNotEmpty
.List();
I did not understand the query that you have written. I am not sure if the above query does what you expect, see the generated sql and see if it is correct.
Also what might help is the sql query that you expect to see which will give you the correct result.
i have the following lambda expression in MVC application.
var toprating= _db.Movie.SelectMany(m => m.Rating.Select(r=> new
{
movieID=r.MovieID,
MovieTitle= m.Title
})).GroupBy(m=>m.movieID).ToList();
ViewBag.TopMovie = toprating;
}
i want to pass this to my view.
i try writing the following in my view
IEnumerable<Movie> TopMovies = ViewBag.TopMovie;
but got this error
Cannot implicitly convert type 'object' to 'System.Collections.Generic.IEnumerable<Movie>'. An explicit conversion exists (are you missing a cast?)
any help will be appriciated.
i would recommend that you make a class that depicts your domain entity (Movie) like
public class MyMovie{
public int movieID { get; set; }
public string MovieTitle { get; set; }
}
and modify your linq query as
var toprating= _db.Movie.SelectMany(m => m.Rating.Select(r=> new MyMovie
{
movieID=r.MovieID,
MovieTitle= m.Title
})).GroupBy(m=>m.movieID).ToList();
ViewBag.TopMovie = toprating;
IEnumerable<MyMovie> TopMovies = ViewBag.TopMovie;
i have assumed that the Movie is your Domain entity, use view models to pass on to the views.
you may find this helpful
This might be a stupid question! (n00b to AutoMapper and time-short!)
I want to use AutoMapper to map from EF4 entities to ViewModel classes.
1) If I call
CreateMap<ModelClass, ViewModelClass>()
then do I also need to call
CreateMap<ViewModelClass, ModelClass>()
to perform the reverse?
2) If two classes have the same property names, then do I need a CreateMap statement at all, or is this just for "specific/custom" mappings?
For the info of the people who stumble upon this question. There appears to be now a built-in way to achieve a reverse mapping by adding a .ReverseMap() call at the end of your CreateMap() configuration chain.
In AutoMapper you have a Source type and a Destination type. So you will be able to map between this Source type and Destination type only if you have a corresponding CreateMap. So to answer your questions:
You don't need to define the reverse mapping. You have to do it only if you intend to map back.
Yes, you need to call CreateMap to indicate that those types are mappable otherwise an exception will be thrown when you call Map<TSource, TDest> telling you that a mapping doesn't exist between the source and destination type.
I've used an extension method do mapping both ways
public static IMappingExpression<TDestination, TSource> BothWays<TSource, TDestination>
(this IMappingExpression<TSource, TDestination> mappingExpression)
{
return Mapper.CreateMap<TDestination, TSource>();
}
usage:
CreateMap<Source, Dest>().BothWays();
Yes, or you can call CreateMap<ModelClass, ViewModelClass>().ReverseMap().
If two classes have same Member(Property,Field,GetMethod()), you needn't call CreateMap<TSrc,TDest>. Actually, if every member in TDest are all exist in TSrc, you needn't call CreateMap<TSrc,TDest>. The following code works.
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Person2
{
public string Name { get; set; }
public int? Age { get; set; }
public DateTime BirthTime { get; set; }
}
public class NormalProfile : Profile
{
public NormalProfile()
{
//CreateMap<Person2, Person>();//
}
}
var cfg = new MapperConfiguration(c =>
{
c.AddProfile<NormalProfile>();
});
//cfg.AssertConfigurationIsValid();
var mapper = cfg.CreateMapper();
var s3 = mapper.Map<Person>(new Person2 { Name = "Person2" });