0

I have a simple project in which i have the following model.

Customer 1--->N Addresses N<----1 City N<----1 Country
                     ^
                    N|
                     |
AddressTypes 1-------+

Here is my code:

public partial class Customer {
        public Customer() {
            this.Address = new HashSet<Address>();
        }
        public int Id {get;set;}
        public string FirstName {get;set;}
        public string LastName {get;set;}
        public System.DateTime Birthday {get;set;}

        public virtual ICollection<Address> Address {get;set;}
    }

public partial class Address {
        public int Id {get;set;}
        public string Street {get;set;}
        public string Area {get;set;}
        public string Post {get;set;}
        public bool isDeleted {get;set;}

        public virtual Customer Customer {get;set;}
        public virtual City City {get;set;}
        public virtual AddressType AddressType {get;set;}
    }

public partial class AddressType {
        public AddressType() {
            this.Address = new HashSet<Address>();
        }
        public int Id {get;set;}
        public string Name {get;set;}

        public virtual ICollection<Address> Address {get;set;}
    }

public partial class Country {
        public Country() {
            this.City = new HashSet<City>();
        }
        public int Id {get;set;}
        public string Name {get;set;}

        public virtual ICollection<City> City {get;set;}
    }

public partial class City {
        public City() {
            this.Address = new HashSet<Address>();
        }
        public int Id {get;set;}
        public string Name {get;set;}

        public virtual ICollection<Address> Address {get;set;}
        public virtual Country Country {get;set;}
    }


public partial class MyModelContext : DbContext {
        public MyModelContext()
            : base("name=MyModelContext") {
            this.Configuration.LazyLoadingEnabled = true;
            this.Configuration.ProxyCreationEnabled = false;
        }

        public virtual DbSet<Country> Countries {get;set;}
        public virtual DbSet<City> Cities {get;set;}
        public virtual DbSet<AddressType> AddressTypes {get;set;}
        public virtual DbSet<Address> Addresses {get;set;}
        public virtual DbSet<Customer> Customers {get;set;}
    }

I want to return a list of customers. At first i tried to do a simple Customers.ToList() but i was getting an exception during serialization and i read that this was caused by cyclical references. So i added

Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = false;

and then i was able to get the customers but without the addresses. I tried doing:

public List<Customer> getCustomers() {
    MyModelContext db = new MyModelContext();
    return db.Customers.Include("Address").ToList();
}

but i don't know how to retrieve ALL the properties. I want to get in the list every customer and his addresses including the city, country, addresstype of each address. How can i do it?

Christos Baziotis
  • 5,845
  • 16
  • 59
  • 80

2 Answers2

1

You have couple of options:

1. Use DTOs (Data Transfer Objects).

2. Explicitly ignore the problematic property that contains the circular references to the parent object by applying the below Attributes:

// in Address entity
[IgnoreDataMember]
[XmlIgnore]
[NonSerialized]
public Customer Custom { get; set; }

Also in AddressType.Address, City.Address, and Country.City.

3. Project your entities into anonymous objects and exclude the pr:

db.Customers.Select(c => new
            {
                c.Id,
                c.FirstName,
                c.LastName,
                c.Birthday,
                Address = c.Address.Select<Address, object>(a => new
                {
                    a.Id,
                    AddressType = new
                    {
                        a.AddressType.Id,
                        a.AddressType.Name
                    },
                    a.Area,
                    City = new
                    {
                        a.City.Id,
                        Country = new
                        {
                            a.City.Country.Id,
                            a.City.Country.Name
                        },
                        a.City.Name,
                    },
                    a.Post,
                    a.Street,
                    a.isDeleted
                }),
            });

You'll have to turn LazyLoadingEnabled and ProxyCreationEnabled back on in order for it to work (or use Include).

(As a side note, i don't really understand why you need this circular references at all, what benefit do you get from AddressType.Address?)

Community
  • 1
  • 1
haim770
  • 48,394
  • 7
  • 105
  • 133
0

I solved it this way:

public List<Customer> getCustomers() {

            var customers = db.CustomerSet.Include("Address")
                .Include("Address.AddressType")
                .Include("Address.City")
                .Include("Address.City.Country")
                .ToList();

            return customers;
        }

i don't really like that i have to explicitly write all the properties of the customer and there is not a generic way of doing what i want but it works.

Christos Baziotis
  • 5,845
  • 16
  • 59
  • 80
  • There is a `generic` way. You can use `.include()` with lambda expressions. Just import `System.Data.Entity`. And I think you don't have to explicitly include 'Address.City' because you already do that when you include 'Country'. – Loetn Jun 20 '14 at 06:49