Parent navigation property is `null` when selecting child object - c#

I have two classes that partake in a parent-child relationship. The parent class is Country, and the child class is City:
public partial class Country
{
public Country()
{
this.Cities = new List<City>();
}
public int Id { get; set; }
public string Name { get; set; }
public string AlphaCodeTwo { get; set; }
public string AlphaCodeThree { get; set; }
public Nullable<int> NumericCode { get; set; }
public string Capital { get; set; }
public string Nationality { get; set; }
public Nullable<decimal> CapitalArea { get; set; }
public Nullable<decimal> CapitalPopulation { get; set; }
public string Image { get; set; }
public virtual List<City> Cities { get; set; }
}
public partial class City
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public Nullable<int> NumericCode { get; set; }
public virtual Country Country { get; set; }
}
When I select a City object with the following LINQ query, the navigation property to the parent class is null:
private List<Country> _Country;
var City = _Country.SelectMany(c => c.Cities).OrderBy(ci => ci.Name).ToList();
I get all children, but no parent data.

If you're using Entity Framework, you can use .Include() to grab the navigation property data as you load the objects. Note that it tends to produce some pretty gnarly queries.
var city = (
from c in db.Cities.Include(c => c.Country)
where c.CountryId == CountryId
orderby c.Name
select c
).ToList();

Related

select multiple column from include table in LINQ

My question is about how can i select some one-two column from those tables are included and at the end when i am selecting as list it is returning list of parent object but child are contain those column i mention to select?
var testq = _db.Homes
.Include(x => x.Indexs.Cities.Proviences.Regions)
.Include(x => x.Images)
.Select(x => new Homes {
Images = x.Images,
Address = x.Address,
Indexs.Cities.Proviences.Regions =
x.Indexs.Cities.Proviences.Regions.Name });
At the end I need to have list of home model (List) and just images and Address and region name have value and important just those are selected from database not all infromation in the tables. I am trying to make a query with better performance
Edit Add Models
public partial class dbContext : DbContext
{
public virtual DbSet<City> Cities { get; set; }
public virtual DbSet<Province> Provinces { get; set; }
public virtual DbSet<Region> Regions { get; set; }
public virtual DbSet<Index> Indexs { get; set; }
public virtual DbSet<Home> Homes { get; set; }
public virtual DbSet<Images> Imageses { get; set; }
}
public partial class Home
{
public Home()
{
Imageses = new HashSet<Images>();
}
[Key]
public int IDHome { get; set; }
[Required]
[StringLength(5)]
public string Cap { get; set; }
[Required]
[StringLength(10)]
public string Number { get; set; }
[Required]
[StringLength(50)]
public string Address { get; set; }
....
public virtual Index Indexs { get; set; }
public virtual ICollection<Images> Imageses { get; set; }
}
public class Index
{
public int ID { get; set; }
public int IDHome { get; set; }
....
public virtual City Cities { get; set; }
}
public partial class City
{
[Key]
public int ID { get; set; }
public int IDProvincia { get; set; }
public decimal Latitudine { get; set; }
public decimal Longitudine { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
....
public virtual Province Provinces { get; set; }
}
public partial class Province
{
[Key]
public int ID { get; set; }
public int IDRegione { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[StringLength(3)]
public string Init { get; set; }
...
public virtual Region Regions { get; set; }
}
public partial class Region
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public DateTime DataInsert { get; set; }
...
}
public class Images
{
public int ID { get; set; }
public string Path { get; set; }
...
}
absolutely tables have more column just add here as example
you have to define a new type with the fields you need, or use an anonymous type.
.Select(x => new {
Images = x.Images,
Address = x.Address,
Indexs.Cities.Proviences.Regions =
x.Indexs.Cities.Proviences.Regions.Name });

RavenDB: how to transform a session.Query into a session.Advanced.DocumentQuery?

I stored the objects of the following classes in a ravendb database:
public class Continent
{
public string Name { get; set; }
public List<Country> Countries{ get; set; }
}
public class Countries
{
public string Name { get; set; }
public List<Province> Provinces{ get; set; }
}
public class Province
{
public string Name { get; set; }
public List<Province> Cities { get; set; }
}
public class City
{
public string Name { get; set; }
public string Address { get; set; }
}
Thanks to a post (RavenDB: how to retrieve the top nodes in a nested collection?) I have learned how to use session.Query to retrieve from the database all the continents having cities with Name and Address respectively set to "aloma" and "123". I would like to write the same query using session.Advanced.DocumentQuery. So can you please tell me how to transform the following query into a session.Advanced.DocumentQuery: var continents = session.Query() .Where(x=>x.Countries.Any(country => country.Provinces.Any(p=>p.Cities.Any(city => city.Name == "123" && city.Address == "aloma"))).OfType().ToList(); ?
Note, this is probably not the best way to do this but it's the only way I know how. Also, note the following will create an index once executed.
var results = session.Advanced.DocumentQuery<Continent>().Where("Countries,Provinces,Cities,Name: 123 AND Countries,Provinces,Cities,Address: aloma").ToList();
Model structure used:
public class Continent
{
public string Id { get; set; }
public string Name { get; set; }
public List<Country> Countries { get; set; }
}
public class Country
{
public string Name { get; set; }
public List<Province> Provinces { get; set; }
}
public class Province
{
public string Name { get; set; }
public List<City> Cities { get; set; }
}
public class City
{
public string Name { get; set; }
public string Address { get; set; }
}

RavenDB: how to retrieve the top nodes in a nested collection?

I stored the objects of the following classes in a ravendb database:
public class Continent
{
public string Name { get; set; }
public List<Country> Countries{ get; set; }
}
public class Countries
{
public string Name { get; set; }
public List<Province> Provinces{ get; set; }
}
public class Province
{
public string Name { get; set; }
public List<Province> Cities { get; set; }
}
public class City
{
public string Name { get; set; }
public string Address { get; set; }
}
How can I retrieve from the database all the continents having cities with Name and Address respectively set to "aloma" and "123"?
You can do that using the following query:
var continents = session.Query()
.Where(c=>x.Countries.Any(country => country.Provinces.Any(p=>p.Cities.Any(city => city.Name == "123" && city.Address == "aloma"))).ToList();

Add non-relational attribute to EF Entity (Join Operation)

I've a model as described below:
public class Student
{
public int Id { get; set; }
public string Level { get; set; }
public string Subject { get; set; }
public string School { get; set; }
public int CityId { get; set; } //from City
}
public class City
{
public int Id { get; set; }
public string City { get; set; }
public int StateId { get; set; } //from State
}
public class State
{
public int Id { get; set; }
public string State { get; set; }
public int CountryId { get; set; } //from Country
}
public class Country
{
public int Id { get; set; }
public string Country { get; set; }
}
I wants to query the Student Entity and needs to include the Country (Only Country) to the student Model.
The Database structure is like as above, I cannot change the DB Table Structure.
But I can able to edit the EF Entities above. Ultimately I need the Student info with country as a Student Entity, So that I can draw jqGrid and sort them based on country too.
Well if you can't modify your entity classes to add the corresponding navigation properties, you can try this:
var query = from student in context.Students
join city in context.Cities on student.CityId equals city.Id
join state in context.States on city.StateId equals state.Id
join country in context.Countries on state.CountryId equals country.Id
select new {
StudentId=student.Id,
Level=student.Level,
...
Country=country.Country
};
Or maybe:
select new {Student=student, Country=country.Country};
If your tables are related, I suggest you include the navigation properties to your model:
public class Student
{
public int Id { get; set; }
//...
public int CityId { get; set; } //from City
public virtual City City{get;set;}
}
public class City
{
public int Id { get; set; }
//...
public int StateId { get; set; } //from State
public virtual City City{get;set;}
public virtual ICollection<Student> Students{get;set;}
}
public class State
{
public int Id { get; set; }
//...
public int CountryId { get; set; } //from Country
public virtual Country Country {get;set;}
public virtual ICollection<City> Cities{get;set;}
}
public class Country
{
public int Id { get; set; }
public string Country { get; set; }
public virtual ICollection<State> States{get;set;}
}
That is not going to affect your current DB schema. This way is more easy to reach to the country name using a student instance (as #SteveGreene show in his answer):
var countryName=student.City.State.Country.Country;
You can project that into an anonymous object or viewmodel:
var studentWithCountry = context.Student.Where(Id = myVar.Id)
.Select(s => new { Level = s.Level,
Subject = s.Subject,
...
Country = s.City.State.Country.Country });

Large data object - am I worrying too much

I work with EF for the first time so I don't know is situation like this normal or I have serious performance issues.
I have following situation:
Bellow are the classes that I have. Item is the main object here. So when I pull a list of Items from database I get for example 1000 items. And now each of this item has all properties filed with data. City contains Country, Country contains list of cities, User has list of created items, each item all data again, city, city has country, country list of cities etc etc...
Maybe I am worrying too much and I don't know should this object's contain all those data and does this make performance issues, or I am doing something wrong here?
public abstract class Item
{
[Key]
public int ItemId { get; set; }
public int ItemTypeId { get; set; }
public Guid UserId { get; set; }
public DateTime CreatedOnDate { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int? MediaId { get; set; }
public int CityId { get; set; }
public virtual City City { get; set; }
public virtual User User { get; set; }
public virtual ICollection<ItemInBoard> ItemsInBoard { get; set; }
public virtual ICollection<Like> Likes { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class City
{
public int CityId { get; set; }
public string Name { get; set; }
public double Longitude { get; set; }
public double Latitude { get; set; }
public int CountryId { get; set; }
public virtual Country Country { get; set; }
}
public class Country
{
public int CountryId { get; set; }
public string Name { get; set; }
public string CountryCode { get; set; }
public virtual ICollection<City> Cities { get; set; }
}
public class User
{
public Guid UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Gender { get; set; }
public DateTime? BirthDay { get; set; }
public string AboutMe { get; set; }
public int? MediaId { get; set; }
public int CityId { get; set; }
public virtual City City { get; set; }
public virtual ICollection<Item> Items { get; set; }
public virtual ICollection<Board> Boards { get; set; }
public virtual ICollection<Like> Likes { get; set; }
}
It is up to you. This is a concept called lazy loading. You can enable or disable lazy loading with this code:
context.Configuration.LazyLoadingEnabled = false;
context.Configuration.LazyLoadingEnabled = true;
When enabling this option none of the dependent entities will be loaded. To enforce dependent entities to load you can use the Include lambada expression like this:
var test = context.Tests.Include("SomeOtherDependentEntity");
Hope I got you and this is what you meant.
I would say that what you have is fine for general business logic.
When I have to do a lot of time sensitive processing in a read-only fashion I use SQL commands like this to get exactly and only exactly what I want.
public class myQueryClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
var context = new MyDbContext();
context.Database.SqlQuery<myQueryClass>("SELECT Property1 = acolumn, Property2 = acolumn2 FROM myTable WHERE something = somestate");

Categories

Resources