在EF6中,我有一个实体Customer,其导航属性为实体地址。地址实体包含属性“City”。
我可以急切加载地址实体,同时让所有客户都这样:
_dbSet.Customers.Include(customer => customer.Address);
这为我提供了所有客户,并且所有地址属性都已加载。
当然这很好用,但我在Address表中唯一需要的是“City”字段,从而不需要从持久数据存储(SQL Server)获取所有地址属性感觉不错它们。
我尝试了以下内容:
_dbSet.Customers.Include(customer => customer.Address.City);
...但这给了我一个运行时异常:
An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
Additional information: A specified Include path is not valid. The EntityType 'MyModel.Address'does not declare a navigation property with the name 'City'.
我理解这一点,因为City只是一个字段,而不是与另一个表/实体的关系。
但是,还有另一种方法可以实现我想要的,或者最好只包括整个地址实体,即使我只需要城市字段???
我想要的是我可以使用myCustomer.Address.City,而不需要对数据库进行额外的查询,但是当我使用myCustomer.Address.Street时,街道属性并不是急切加载的,而应该是另外的从数据库中获取...
答案 0 :(得分:4)
仅选择所需的属性,EF只会加载所需的属性。
var query = _dbSet.Customers.Include(customer => customer.Address);
var data = query.Select(c => new { Customer = c, City = c.Address.City });
答案 1 :(得分:4)
如果您确实设置在整个代码库中使用相同的实体,那么您可以使用类似于Stef建议的内容解决问题:
var query = _dbSet.Customers.Include(customer => customer.Address);
var data = query
.Select(c => new { Customer = c, City = c.Address.City })
.ToList() //executes the IQueryable, and fetches the Customer and City (only) from the DB
.ForEach(x => x.Customer.Address = new Address { City = x.City })
.Select(x => x.Customer)
.ToList();
我非常支持DTO和不在整个代码库中使用实体对象,但上面会给出一个Customer
列表Address
填充了City
字段的对象。显然,我假设你的对象有公共setter,实体对象通常都有。