[英]Entity Framework not always including child entities
我有一个User
分配给一个Client
。 拔出User
对象时,我将Client
对象作为它的一部分。 简单。
这在登录时应能正常工作。无论我以谁身份登录, User
对象都有一个Client
。
然而,使用完全相同的方法来获取User
登录时,通过管理菜单进行编辑的,在Client
有时是null
。
我有时说:
1)在Firefox中-尝试查看大多数 (但不是全部)用户(和本人)的详细信息时,附加到User
的Client
为null
。 由于Client
实际存在,因此只能看到几个Users
。
2)在Chrome中-所有用户(我自己除外)都是可见的。 仅当尝试查看自己的用户时, Client
才会为null
。
我不明白 两种浏览器都直接使用相同的URL,即/Users/EditGet/28
,甚至使用两种不同的方法( GetById
和GetByUserName
),它也提供相同的结果-尽管可以GetById
,两者都使用了基本的Get函数:
编辑:将BaseService类一起进行编辑。
internal CustomContext context;
internal DbSet<TEntity> dbSet;
public BaseService(CustomContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet.Where(e => !e.Deleted);
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
return orderBy != null ? orderBy(query).ToList() : query.ToList();
}
我不确定为什么选择浏览器会完全影响后端查询的结果。 无论我使用哪种浏览器,它肯定都应该与User
一起返回Client
。
我假设基本的Get方法可能是一个基本的错误,但是它并不能解释我所看到的行为...
如果有人能对此有所启示,我将不胜感激。
编辑2:CustomContext:
public class CustomContext : DbContext, ICustomContext
{
public IDbSet<User> Users { get; set; }
public IDbSet<Client> Clients { get; set; }
}
您可能还想从逗号分隔的包含列表中更改-可能易于格式化错误; 您可以将其更改为param或类似这样的数组:
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
params string[] includeProperties) {
var query = ((DbQuery<TEntity>)dbset);
query = includeProperties.Aggregate(query, (q, s) => q.Include(s));
query = query.Where(e => !e.IsDeleted);
if (filter != null) {
query = query.Where(filter);
}
return orderBy != null ? orderBy(query).ToList() : query.ToList();
}
我在想,如果您所说的是依赖于浏览器的,则可能存在一些字符串格式问题...还是值得一试的。
编辑 :将查询更改回DbQuery
EDIT2 :修复方法是Where
必须在DbSet
或DbQuery
上调用Where
Include
之前,先将对Include
调用。 看起来随机的原因是,当没有过滤器时,包含被调用在DbSet / DbQuery上应该位于的位置。
不容易发现,因为代码已调用IQueryable<T>.Include
...,这不是开箱即用的标准功能。 Include
在DbSet或DbQuery上。
我看来,问题出在我们存储当前登录的User
。
当尝试检索同一User
对象中的另一个对象时,它随后也无法拉出Client
。
仍然不太确定为什么会这样。 我有一些暗示,它与Object State Manager
和跟踪多个对象有关-尽管当前登录的User
对象实际上并未从数据库中提取...
但是,解决此问题的方法是进行简单检查,以查看是否拉出的User
与当前登录的User
相同,并且是否存在问题( Client
为null
),然后拉出Client
并将其附加到User
对象。
private User GetUser(long id)
{
var user = Services.UserService.GetById(id);
if (user.Client == null && CurrentUser.Id == user.Id)
user.Client = Services.ClientService.GetByClient(CurrentUser.Client);
return user;
}
关于如何正确解决此问题,这还很粗略,远未达到一个合理的答案,但它确实有效,并且所有User
都可以再次完全编辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.