【问题标题】:Entity Framework - Eager loading, all properties to list实体框架 - 急切加载,列出所有属性
【发布时间】:2014-08-09 19:49:12
【问题描述】:

我有一个简单的项目,其中有以下模型。

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

这是我的代码:

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;}
    }

我想返回一份客户列表。起初我试图做一个简单的Customers.ToList(),但我得到了一个exception during serialization,我读到这是由循环引用引起的。所以我加了

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

然后我能够获得客户但没有地址。我试着做:

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

但我不知道如何检索所有属性。我想在列表中列出每个客户及其地址,包括每个地址的城市、国家和地址类型。我该怎么做?

【问题讨论】:

    标签: entity-framework eager-loading


    【解决方案1】:

    你有几个选择:

    1. 使用 DTO (Data Transfer Objects)。

    2.通过应用以下属性显式忽略包含对父对象的循环引用的有问题的属性:

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

    也在AddressType.AddressCity.AddressCountry.City 中。

    3.将您的实体投影到匿名对象中并排除公关:

    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
                    }),
                });
    

    您必须重新打开 LazyLoadingEnabledProxyCreationEnabled 才能使其工作(或使用 Include)。

    (顺便说一句,我完全不明白你为什么需要这个循环引用,你从AddressType.Address 得到什么好处?)

    【讨论】:

    • 感谢您的建议和回答,但我找到了一种更简单的方法来做我想做的事。
    【解决方案2】:

    我是这样解决的:

    public List<Customer> getCustomers() {
    
                var customers = db.CustomerSet.Include("Address")
                    .Include("Address.AddressType")
                    .Include("Address.City")
                    .Include("Address.City.Country")
                    .ToList();
    
                return customers;
            }
    

    我真的不喜欢我必须明确地编写客户的所有属性,并且没有通用的方法来做我想做的事情,但它可以工作。

    【讨论】:

    • 有一个generic 方式。您可以将 .include() 与 lambda 表达式一起使用。只需导入System.Data.Entity。而且我认为您不必明确包含“Address.City”,因为您在包含“Country”时已经这样做了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 2011-05-03
    • 2012-02-07
    • 1970-01-01
    相关资源
    最近更新 更多