我试图使用条件包含(在这里解释),但它没有检索子信息。为什么?我想我已经遵循了所有的步骤……我正在使用WebApi控制器和Visual Studio 2012
我已经检查过了,我给每个房子都分配了门的类型。这是一个多对多的关系。
我有这个:
DoorType有这个属性
public virtual ICollection<House> Houses{ get; set; }
House has this property
public virtual ICollection<Door> DoorTypes{ get; set; }
我正在查询这个方法
public IEnumerable<House> GetList(string latitude, string longitude, string idHousesTypeList)
{
IEnumerable<int> intIds = null;
if (!string.IsNullOrEmpty(idHousesTypeList))
{
var ids = idHousesTypeList.Split(',');
intIds = ids.Select(int.Parse);
}
var location = DbGeography.FromText(string.Format("POINT ({0} {1})", latitude, longitude), 4326);
var count = 0;
var radius = 0.0;
IEnumerable<House> houses = null;
while (count < 5 && radius < 500)
{
radius += 2.5;
var radiusLocal = radius;
var dbquery =
from house in Uow.Houses.GetAll()
where house.Location.Distance(location) / 1000 <= radiusLocal
orderby house.Location.Distance(location)
select new
{
house,
doorTypes= from doorType in house.DoorTypes
where intIds.Contains(doorType.Id)
select doorType
};
houses = dbquery
.AsEnumerable()
.Select(p => p.house);
count = houses.Count();
}
if (houses != null && houses.Any())
{
return houses;
}
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
我使用通用的EFRepository
public class EFRepository<T> : IRepository<T> where T : class
{
public EFRepository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
protected DbContext DbContext { get; set; }
protected DbSet<T> DbSet { get; set; }
public virtual IQueryable<T> GetAll()
{
return DbSet;
}
public virtual IQueryable<T> GetAllIncluding(params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = DbContext.Set<T>();
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query;
}
public virtual T GetById(long id)
{
return DbSet.Find(id);
}
public virtual IQueryable<T> GetByPredicate(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IQueryable<T> query = DbContext.Set<T>().Where(predicate);
return query;
}
public virtual IQueryable<T> GetByPredicateIncluding(System.Linq.Expressions.Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = DbContext.Set<T>().Where(predicate);
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query;
}
public virtual void Upsert(T entity, Func<T, bool> insertExpression)
{
if (insertExpression.Invoke(entity))
{
Add(entity);
}
else
{
Update(entity);
}
}
public virtual void Add(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
}
public virtual void Update(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached)
{
DbSet.Attach(entity);
}
dbEntityEntry.State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Deleted)
{
dbEntityEntry.State = EntityState.Deleted;
}
else
{
DbSet.Attach(entity);
DbSet.Remove(entity);
}
}
public virtual void Delete(int id)
{
var entity = GetById(id);
if (entity == null) return; // not found; assume already deleted.
Delete(entity);
}
}
输出正确显示了所有的房屋,但门类型数组为空。我错过了什么?
这是一个多对多的关系。
这就是问题所在。Relationship Fixup不适用于多对多关系,只适用于一对一或一对多关系。
您需要在执行查询之后手动构建导航属性。但在本例中,您可以做得相对简单:
houses = dbquery
.AsEnumerable()
.Select(p => {
p.house.DoorTypes = p.doorTypes;
return p.house;
});
这与显式加载导航集合到上下文中不能用于多对多关系的原因是一样的,参见这个问题:EF 4.1加载过滤子集合不能用于多对多以及它的答案,特别是参考Zeeshan Hirani关于关系修复的解释,以获得关于该主题的更深入的背景。
目前尚不清楚您的Uow.Houses.GetAll()
是如何实现的,但当您从上下文获得所有房屋时,请尝试将DoorTypes
纳入结果:
return context.Houses.Include("DoorTypes");
并确保您正在传递具有现有id的idHousesTypeLis
。
UPDATE: Include
是DbQuery的成员。当您将Set转换为IQueriable<T>
时,它将不可用。那么,试试这个:
public class HouseRepository : EFRepository<House>
{
public override IQueryable<House> GetAll()
{
return DbContext.Set<House>().Include("DoorTypes");
}
}